From beb5a9d68d822471a7859571dc7c09b31ae6f276 Mon Sep 17 00:00:00 2001
From: HongKee Moon <moon@mpi-cbg.de>
Date: Wed, 9 Feb 2022 12:04:27 +0100
Subject: [PATCH] Close #50: Add EditUser component

---
 web/src/components/UserTable.vue |  10 +-
 web/src/router/index.js          |   5 +
 web/src/views/UpdateUser.vue     | 292 +++++++++++++++++++++++++++++++
 3 files changed, 304 insertions(+), 3 deletions(-)
 create mode 100644 web/src/views/UpdateUser.vue

diff --git a/web/src/components/UserTable.vue b/web/src/components/UserTable.vue
index d8deebe..8bdfd2a 100644
--- a/web/src/components/UserTable.vue
+++ b/web/src/components/UserTable.vue
@@ -1,6 +1,6 @@
 <template>
   <div class="flex items-center justify-center panel-table w-full md:w-auto pt-10">
-    <table :id=id class="table table-striped table-bordered table-hover" width="100%"></table>
+    <table :id=id class="table table-striped table-bordered table-hover"></table>
   </div>
 </template>
 
@@ -14,7 +14,11 @@ export default {
   name: 'user-table',
   props: ['id', 'data'],
   methods:{
-      createTable(id, data) {
+    editUser(id) {
+      // eslint-disable-next-line
+      this.$router.push('/updateuser/' + id)
+    },
+    createTable(id, data) {
           
       const vm = this;
 
@@ -92,7 +96,7 @@ export default {
         e.preventDefault()
         const tr = $(e.target).parent().parent();
         const row = table.row(tr);
-        // vm.editUpdateItem(row.data().id);
+        vm.editUser(row.data().id);
       });
     },
   },
diff --git a/web/src/router/index.js b/web/src/router/index.js
index c185c33..fd5608f 100644
--- a/web/src/router/index.js
+++ b/web/src/router/index.js
@@ -101,6 +101,11 @@ export default new Router({
       name: 'updateItem',
       component: () => import('@/views/UpdateItem'),
     },
+    {
+      path: '/updateuser/:user',
+      name: 'updateUser',
+      component: () => import('@/views/UpdateUser'),
+    },
     // { path: '/user/:id', component: User },
     // {
     //   path: '*',
diff --git a/web/src/views/UpdateUser.vue b/web/src/views/UpdateUser.vue
new file mode 100644
index 0000000..6520bf2
--- /dev/null
+++ b/web/src/views/UpdateUser.vue
@@ -0,0 +1,292 @@
+<template>
+  <div>
+    <h3 v-show="error" class="flex items-center justify-center text-2xl text-red-500">{{ errorMsg }}</h3>
+    <div class="flex items-center justify-center">
+      <div v-if="loaded" class="md:flex card p-2 mt-5">
+        <div class="p-5 mx-auto text-left font-raleway container max-w-screen-md">
+          <h1 class="font-bold text-left font-montserrat text-3xl sm:text-5xl mb-7">
+            {{ user }}
+          </h1>
+          <form @submit="update" class="w-full md:w-auto">
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-entity-type">
+                  Username
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <p class="mt-3">
+                  {{username}}
+                </p>
+              </div>
+            </div>
+
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-entity-id">
+                  Email
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <p class="mt-3">
+                  {{email}}
+                </p>
+              </div>
+            </div>
+
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-change-operation">
+                  Role
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <select v-model="role"  class="bg-white w-full py-2 text-gray-700 outline-none  bg-transparent border-b hover:border-blue-700 focus:bg-gray-200 focus:border-blue-700" id="inline-change-operation" >
+                  <option v-for="option in roles" v-bind:key="option.id" :selected="role.name === option.name" :disabled="option.name === 'Administrator' || option.name === 'Public'" v-bind:value="{ id: option.id, name: option.name }">
+                    {{ option.name }}
+                  </option>
+                </select>
+              </div>
+            </div>
+
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status">
+                  Affiliation
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <p class="mt-3">
+                  {{Affiliation}}
+                </p>
+              </div>
+            </div>
+
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status">
+                  Profile Link
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <p class="mt-3">
+                  {{ProfileLink}}
+                </p>
+              </div>
+            </div>
+
+            <div class="md:flex md:items-center mx-3 mb-6">
+              <div class="md:w-1/3">
+                <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status">
+                  Status
+                </label>
+              </div>
+              <div class="md:w-2/3">
+                <p class="mt-3">
+                  <input type="checkbox" id="confirmed_checkbox" v-model="confirmed" disabled>
+                  <label class="ml-3" for="confirmed_checkbox">Authenticated</label>
+                </p>
+                <p class="mt-3">
+                  <input type="checkbox" id="blocked_checkbox" v-model="blocked">
+                  <label class="ml-3" for="blocked_checkbox">Blocked</label>
+                </p>
+              </div>
+            </div>
+
+            <button type="submit" :disabled="role.length < 3" class="bg-green-400 p-5 text-white">
+              {{ 'Update' }}  <span class="fa fa-arrow-right"/>
+            </button>
+
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+const _ = require('lodash');
+let host = require('@/components/js/const').apiHost;
+
+export default {
+  name: 'UpdateUser',
+  props: ['userId'],
+  data() {
+    return {
+      user: this.$route.params.user ? this.$route.params.user : this.userId,
+      username: '',
+      email: '',
+      preRole: '',
+      role: {},
+      roles: [],
+      confirmed: false,
+      blocked: true,
+      Affiliation: '',
+      ProfileLink: '',
+      createdAt: '', // datetime
+      updatedAt: '', // datetime
+      loaded: false,
+      error: false,
+      errorMsg: `An error occurred, please try again`,
+      isDev: process.env.NODE_ENV === 'development',
+    }
+  },
+  computed: {
+    jwt: function () {
+      return this.$store.getters['User/jwt']
+    },
+    userData: function () {
+      return this.$store.getters['User/userData']
+    },
+    userRole: function () {
+      return this.$store.getters['User/userRole']
+    },
+  },
+  methods: {
+    async update(e) {
+      e.preventDefault()
+
+      const vm = this;
+
+      if(vm.isDev) {
+        host = require('@/components/js/const').devApiHost;
+      }
+
+      const jwt = vm.jwt;
+      if(jwt === null) {
+        vm.loaded = false;
+        return
+      }
+
+      // Prevent to update the Administrator status
+      if(vm.preRole === 'Administrator') {
+        this.error = true
+        this.errorMsg = `Cannot change the administrator's attributes.`
+        setTimeout(() => vm.$router.go(-1), 2000);
+        return
+      }
+
+      // console.log(vm.role)
+
+      let dat = {
+        id: vm.user,
+        role: vm.role.id,
+        blocked: vm.blocked,
+      };
+
+      try {
+        const res = await this.axios.put(`${host}/api/users/${vm.user}`, dat, {
+          headers: {
+            Authorization: `Bearer ${jwt}`
+          }
+        });
+
+        // console.log(res.data)
+
+        vm.$router.push('/profile')
+      } catch(error) {
+        // console.log(error.response.data.error.message)
+        // console.log(error.response)
+        this.error = true
+        this.errorMsg = error
+      }
+    },
+    async preload() {
+      const vm = this;
+
+      if(vm.isDev) {
+        host = require('@/components/js/const').devApiHost;
+      }
+
+      const jwt = vm.jwt;
+      if(jwt === null) {
+        vm.loaded = false;
+        return
+      }
+
+      // console.log(vm.userData)
+
+      try {
+        const res = await this.axios.get(`${host}/api/users-permissions/roles`, {
+          headers: {
+            Authorization: `Bearer ${jwt}`
+          }
+        });
+
+        if(res.data) {
+          vm.roles = _.sortBy(_.filter(res.data.roles, o => o.name !== 'Public'), ['name']);
+        }
+      } catch(error) {
+        // console.error(error)
+        this.error = true
+        this.errorMsg = "You are not authorized to access this item."
+        setTimeout(() => vm.$router.go(-1), 2000);
+      }
+    },
+    async load(id) {
+      const vm = this;
+
+      if(vm.isDev) {
+        host = require('@/components/js/const').devApiHost;
+      }
+
+      const jwt = vm.jwt;
+      if(jwt === null) {
+        vm.loaded = false;
+        return
+      }
+
+      // console.log(vm.userData)
+
+      try {
+        const res = await this.axios.get(`${host}/api/users/` + id, {
+          headers: {
+            Authorization: `Bearer ${jwt}`
+          }
+        });
+
+        // console.log(res)
+
+        if(res.data) {
+          const d = res.data;
+          vm.username = d.username;
+          vm.email = d.email;
+          vm.preRole = d.role.name;
+          vm.role.name = d.role.name;
+          vm.role.id = d.role.id;
+          vm.confirmed = d.confirmed;
+          vm.blocked = d.blocked;
+          vm.Affiliation = d.Affiliation;
+          vm.ProfileLink = d.ProfileLink;
+          vm.createdAt = d.createdAt;
+          vm.updatedAt = d.updatedAt;
+        }
+
+        vm.loaded = true;
+      } catch(error) {
+        // console.error(error)
+        this.error = true
+        this.errorMsg = "You are not authorized to access this item."
+        setTimeout(() => vm.$router.go(-1), 2000);
+      }
+    }
+  },
+  mounted: function () {
+    const vm = this;
+
+    const jwt = vm.jwt;
+    if(jwt === null) {
+      vm.$router.push('/login')
+    } else {
+      vm.preload();
+      vm.load(vm.user)
+    }
+  }
+}
+</script>
+<style>
+@import url('~@/assets/bootstrap.css');
+
+a {
+  color: #42b983;
+}
+</style>
\ No newline at end of file
-- 
GitLab