Update local user component

- Add, edit, delete user basic functionality complete
- Rename components and creating separate modal components
- Update button styles to match design and included icons
- Update grid layout to use container with max width set
- Add aria labels to table action buttons
- Refactor LocalUserManagementStore

Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Signed-off-by: Derick Montague <derick.montague@ibm.com>
Change-Id: Iab31ccabeb5a53ec03dc3ce3949fb20ded1ffbcf
diff --git a/src/main.js b/src/main.js
index 6f4acc6..695c008 100644
--- a/src/main.js
+++ b/src/main.js
@@ -11,6 +11,8 @@
   FormCheckboxPlugin,
   FormGroupPlugin,
   FormInputPlugin,
+  FormRadioPlugin,
+  FormSelectPlugin,
   LayoutPlugin,
   LinkPlugin,
   ListGroupPlugin,
@@ -29,6 +31,8 @@
 Vue.use(FormCheckboxPlugin);
 Vue.use(FormGroupPlugin);
 Vue.use(FormInputPlugin);
+Vue.use(FormRadioPlugin);
+Vue.use(FormSelectPlugin);
 Vue.use(LayoutPlugin);
 Vue.use(LayoutPlugin);
 Vue.use(LinkPlugin);
diff --git a/src/store/modules/AccessControl/LocalUserMangementStore.js b/src/store/modules/AccessControl/LocalUserMangementStore.js
index 41bbe0d..de79a2d 100644
--- a/src/store/modules/AccessControl/LocalUserMangementStore.js
+++ b/src/store/modules/AccessControl/LocalUserMangementStore.js
@@ -19,19 +19,45 @@
     getUsers({ commit }) {
       api
         .get("/redfish/v1/AccountService/Accounts")
-        .then(response => {
-          return response.data.Members.map(user => user["@odata.id"]);
-        })
-        .then(userIds => {
-          return api.all(userIds.map(user => api.get(user)));
-        })
+        .then(response => response.data.Members.map(user => user["@odata.id"]))
+        .then(userIds => api.all(userIds.map(user => api.get(user))))
         .then(users => {
           const userData = users.map(user => user.data);
           commit("setUsers", userData);
         })
-        .catch(error => {
-          console.log(error);
-        });
+        .catch(error => console.log(error));
+    },
+    createUser({ dispatch }, { username, password, privilege, status }) {
+      const data = {
+        UserName: username,
+        Password: password,
+        RoleId: privilege,
+        Enabled: status
+      };
+      api
+        .post("/redfish/v1/AccountService/Accounts", data)
+        .then(() => dispatch("getUsers"))
+        .catch(error => console.log(error));
+    },
+    updateUser(
+      { dispatch },
+      { originalUsername, username, password, privilege, status }
+    ) {
+      const data = {};
+      if (username) data.UserName = username;
+      if (password) data.Password = password;
+      if (privilege) data.RoleId = privilege;
+      if (status !== undefined) data.Enabled = status;
+      api
+        .patch(`/redfish/v1/AccountService/Accounts/${originalUsername}`, data)
+        .then(() => dispatch("getUsers"))
+        .catch(error => console.log(error));
+    },
+    deleteUser({ dispatch }, username) {
+      api
+        .delete(`/redfish/v1/AccountService/Accounts/${username}`)
+        .then(() => dispatch("getUsers"))
+        .catch(error => console.log(error));
     }
   }
 };
diff --git a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue
index cca068d..c671679 100644
--- a/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue
+++ b/src/views/AccessControl/LocalUserManagement/LocalUserManagement.vue
@@ -1,83 +1,93 @@
 <template>
-  <b-container fluid>
+  <b-container class="ml-0">
     <b-row>
-      <b-col lg="8">
+      <b-col lg="10">
         <h1>Local user management</h1>
       </b-col>
     </b-row>
     <b-row>
-      <b-col lg="8" md="10">
-        <b-button v-b-modal.modal-settings variant="secondary"
-          >Account policy settings</b-button
-        >
-        <b-button v-b-modal.modal-add-user variant="primary">Add user</b-button>
+      <b-col lg="10">
+        <b-button @click="initModalSettings" variant="link">
+          <icon-settings />
+          Account policy settings
+        </b-button>
+        <b-button @click="initModalUser(null)" variant="primary">
+          <icon-add />
+          Add user
+        </b-button>
       </b-col>
     </b-row>
     <b-row>
-      <b-col lg="8" md="10">
-        <b-table bordered head-variant="dark" :items="tableItems" show-empty>
+      <b-col lg="10">
+        <b-table bordered show-empty head-variant="dark" :items="tableItems">
           <template v-slot:head(actions)="data"></template>
           <template v-slot:cell(actions)="data">
             <b-button
+              aria-label="Edit user"
+              variant="link"
               :disabled="!data.value.edit"
-              v-b-modal.modal-user-settings
+              @click="initModalUser(data.item)"
             >
-              <Edit20 />
+              <icon-edit />
             </b-button>
             <b-button
+              aria-label="Delete user"
+              variant="link"
               :disabled="!data.value.delete"
-              v-b-modal.modal-user-delete
+              @click="initModalDelete(data.item)"
             >
-              <TrashCan20 />
+              <icon-trashcan />
             </b-button>
           </template>
         </b-table>
       </b-col>
     </b-row>
     <b-row>
-      <b-col lg="6" md="8">
-        <b-button v-b-toggle.collapse-role-table variant="info" class="mt-3"
-          >View privilege role descriptions</b-button
-        >
+      <b-col lg="8">
+        <b-button v-b-toggle.collapse-role-table variant="link" class="mt-3">
+          View privilege role descriptions
+        </b-button>
         <b-collapse id="collapse-role-table" class="mt-3">
-          <role-table />
+          <table-roles />
         </b-collapse>
       </b-col>
     </b-row>
     <!-- Modals -->
-    <b-modal id="modal-add-user" title="Add user" ref="modal">
-      <template v-slot:modal-footer="{ ok, cancel, hide }">
-        <b-button
-          size="sm"
-          variant="secondary"
-          @click="$bvModal.hide('modal-add-user')"
-          >Cancel</b-button
-        >
-        <b-button
-          size="sm"
-          variant="primary"
-          @click="$bvModal.hide('modal-add-user')"
-          >Add user</b-button
-        >
-      </template>
-    </b-modal>
-    <b-modal id="modal-settings" title="Account policy settings"></b-modal>
-    <b-modal id="modal-user-delete" title="Delete user"></b-modal>
-    <b-modal id="modal-user-settings" title="User settings"></b-modal>
+    <modal-settings v-bind:settings="settings"></modal-settings>
+    <modal-user
+      v-bind:user="activeUser"
+      @ok="saveUser"
+      @hidden="clearActiveUser"
+    ></modal-user>
   </b-container>
 </template>
 
 <script>
-import LocalUserManagementRoleTable from "./LocalUserMangementRoleTable";
-import TrashCan20 from "@carbon/icons-vue/es/trash-can/20";
-import Edit20 from "@carbon/icons-vue/es/edit/20";
+import IconTrashcan from "@carbon/icons-vue/es/trash-can/20";
+import IconEdit from "@carbon/icons-vue/es/edit/20";
+import IconAdd from "@carbon/icons-vue/es/add--alt/20";
+import IconSettings from "@carbon/icons-vue/es/settings/20";
+
+import TableRoles from "./TableRoles";
+import ModalUser from "./ModalUser";
+import ModalSettings from "./ModalSettings";
 
 export default {
   name: "local-users",
   components: {
-    TrashCan20,
-    Edit20,
-    roleTable: LocalUserManagementRoleTable
+    IconAdd,
+    IconEdit,
+    IconSettings,
+    IconTrashcan,
+    ModalSettings,
+    ModalUser,
+    TableRoles
+  },
+  data() {
+    return {
+      activeUser: null,
+      settings: null
+    };
   },
   created() {
     this.getUsers();
@@ -108,6 +118,45 @@
   methods: {
     getUsers() {
       this.$store.dispatch("localUsers/getUsers");
+    },
+    initModalUser(user) {
+      this.activeUser = user;
+      this.$bvModal.show("modal-user");
+    },
+    initModalDelete(user) {
+      this.$bvModal
+        .msgBoxConfirm(
+          `Are you sure you want to delete user '${user.username}'? This action cannot be undone.`,
+          {
+            title: "Delete user",
+            okTitle: "Delete user"
+          }
+        )
+        .then(deleteConfirmed => {
+          if (deleteConfirmed) {
+            this.deleteUser(user);
+          }
+        });
+    },
+    initModalSettings() {
+      if (this.settings) {
+        this.$bvModal.show("modal-settings");
+      } else {
+        // fetch settings then show modal
+      }
+    },
+    saveUser({ newUser, form }) {
+      if (newUser) {
+        this.$store.dispatch("localUsers/createUser", form);
+      } else {
+        this.$store.dispatch("localUsers/updateUser", form);
+      }
+    },
+    deleteUser({ username }) {
+      this.$store.dispatch("localUsers/deleteUser", username);
+    },
+    clearActiveUser() {
+      this.activeUser = null;
     }
   }
 };
diff --git a/src/views/AccessControl/LocalUserManagement/ModalSettings.vue b/src/views/AccessControl/LocalUserManagement/ModalSettings.vue
new file mode 100644
index 0000000..3d985ac
--- /dev/null
+++ b/src/views/AccessControl/LocalUserManagement/ModalSettings.vue
@@ -0,0 +1,9 @@
+<template>
+  <b-modal id="modal-settings" title="Account policy settings"> </b-modal>
+</template>
+
+<script>
+export default {
+  props: ["settings"]
+};
+</script>
diff --git a/src/views/AccessControl/LocalUserManagement/ModalUser.vue b/src/views/AccessControl/LocalUserManagement/ModalUser.vue
new file mode 100644
index 0000000..70cd614
--- /dev/null
+++ b/src/views/AccessControl/LocalUserManagement/ModalUser.vue
@@ -0,0 +1,75 @@
+<template>
+  <b-modal
+    id="modal-user"
+    @ok="$emit('ok', { newUser, form })"
+    @hidden="$emit('hidden')"
+  >
+    <template v-slot:modal-title>
+      <template v-if="newUser">
+        Add user
+      </template>
+      <template v-else>
+        Edit user
+      </template>
+    </template>
+    <b-form>
+      <b-form-group label="Account status">
+        <b-form-radio v-model="form.status" name="user-status" value="true"
+          >Enabled</b-form-radio
+        >
+        <b-form-radio v-model="form.status" name="user-status" value="false"
+          >Disabled</b-form-radio
+        >
+      </b-form-group>
+      <b-form-group label="Username">
+        <b-form-input type="text" v-model="form.username" />
+      </b-form-group>
+      <b-form-group label="Privilege">
+        <b-form-select
+          v-model="form.privilege"
+          :options="privilegeTypes"
+        ></b-form-select>
+      </b-form-group>
+      <b-form-group label="Password">
+        <b-form-input type="password" v-model="form.password" />
+      </b-form-group>
+    </b-form>
+    <template v-slot:modal-ok>
+      <template v-if="newUser">
+        Add user
+      </template>
+      <template v-else>
+        Save
+      </template>
+    </template>
+  </b-modal>
+</template>
+
+<script>
+export default {
+  props: ["user"],
+  data() {
+    return {
+      privilegeTypes: ["Administrator", "Operator", "ReadOnly", "NoAccess"]
+    };
+  },
+  computed: {
+    newUser() {
+      return this.user ? false : true;
+    },
+    form() {
+      return {
+        originalUsername: this.newUser ? null : this.user.username,
+        status: this.newUser
+          ? true
+          : this.user.status === "Enabled"
+          ? true
+          : false,
+        username: this.newUser ? "" : this.user.username,
+        privilege: this.newUser ? "" : this.user.privilege,
+        password: ""
+      };
+    }
+  }
+};
+</script>
diff --git a/src/views/AccessControl/LocalUserManagement/LocalUserMangementRoleTable.vue b/src/views/AccessControl/LocalUserManagement/TableRoles.vue
similarity index 69%
rename from src/views/AccessControl/LocalUserManagement/LocalUserMangementRoleTable.vue
rename to src/views/AccessControl/LocalUserManagement/TableRoles.vue
index 1eca05f..7aa1dc8 100644
--- a/src/views/AccessControl/LocalUserManagement/LocalUserMangementRoleTable.vue
+++ b/src/views/AccessControl/LocalUserManagement/TableRoles.vue
@@ -1,6 +1,6 @@
 <template>
   <b-table bordered small head-variant="dark" :items="items" :fields="fields">
-    <template v-slot:cell(admin)="data">
+    <template v-slot:cell(administrator)="data">
       <template v-if="data.value">
         <Checkmark20 />
       </template>
@@ -10,7 +10,7 @@
         <Checkmark20 />
       </template>
     </template>
-    <template v-slot:cell(user)="data">
+    <template v-slot:cell(readonly)="data">
       <template v-if="data.value">
         <Checkmark20 />
       </template>
@@ -35,73 +35,73 @@
       items: [
         {
           description: "Configure components managed by this service",
-          admin: true,
+          administrator: true,
           operator: false,
-          user: false,
+          readonly: false,
           noaccess: false
         },
         {
           description: "Configure manager resources",
-          admin: true,
+          administrator: true,
           operator: false,
-          user: false,
+          readonly: false,
           noaccess: false
         },
         {
           description: "Update password for current user account",
-          admin: true,
-          operator: true,
-          user: true,
+          administrator: true,
+          operator: false, // TODO Set to true when profile page added
+          readonly: false, // TODO Set to true when profile page added
           noaccess: false
         },
         {
           description: "Configure users and their accounts",
-          admin: true,
+          administrator: true,
           operator: false,
-          user: false,
+          readonly: false,
           noaccess: false
         },
         {
           description: "Log in to the service and read resources",
-          admin: true,
+          administrator: true,
           operator: true,
-          user: true,
+          readonly: true,
           noaccess: false
         },
         {
           description: "IPMI access point",
-          admin: true,
+          administrator: true,
           operator: true,
-          user: true,
-          noaccess: true
+          readonly: true,
+          noaccess: false
         },
         {
           description: "Redfish access point",
-          admin: true,
+          administrator: true,
           operator: true,
-          user: true,
+          readonly: true,
           noaccess: false
         },
         {
           description: "SSH access point",
-          admin: true,
+          administrator: true,
           operator: false,
-          user: false,
+          readonly: false,
           noaccess: false
         },
         {
           description: "WebUI access point",
-          admin: true,
+          administrator: true,
           operator: true,
-          user: true,
+          readonly: true,
           noaccess: false
         }
       ],
       fields: [
         { key: "description", label: "" },
-        { key: "admin", label: "Admin", class: "text-center" },
+        { key: "administrator", label: "Administrator", class: "text-center" },
         { key: "operator", label: "Operator", class: "text-center" },
-        { key: "user", label: "User", class: "text-center" },
+        { key: "readonly", label: "ReadOnly", class: "text-center" },
         { key: "noaccess", label: "NoAccess", class: "text-center" }
       ]
     };