You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.6 KiB

  1. <template lang="pug">
  2. div.user-table
  3. div.columns.is-multiline
  4. div.column.is-12
  5. a.button.is-primary(v-on:click="createNewRoleMapping()") Add Existing User
  6. div.column.is-12(v-if="newRoleMapping")
  7. div.box
  8. div.columns.is-multiline
  9. div.column
  10. b-field(
  11. label="User Name"
  12. v-bind:type="{ 'is-danger': getAddUserMessage }"
  13. v-bind:message="getAddUserMessage"
  14. )
  15. b-autocomplete(
  16. v-model="newRoleMapping.username"
  17. placeholder="e.g. Anne"
  18. open-on-focus=true
  19. v-bind:data="otherUsers"
  20. field="username"
  21. v-on:select="option => {selected = option; newRoleMapping.userid = selected.id}"
  22. v-on:input="value => checkValidExistingUser(value)"
  23. )
  24. div.column
  25. b-field(label="Role")
  26. b-select(
  27. placeholder="Select a role"
  28. v-model="newRoleMapping.roleid"
  29. )
  30. option(v-for="role in roles", v-bind:value="role.id", v-bind:key="role.id")
  31. | {{ role.name }}
  32. div.column
  33. div.field
  34. label.label &nbsp;
  35. div.field.is-grouped
  36. p.control
  37. b-button(type="is-light", v-on:click="cancelCreate()") Cancel
  38. p.control
  39. b-button(
  40. type="is-primary"
  41. v-on:click="addRoleMapping()"
  42. v-bind:disabled="isDisabled"
  43. ) Add User
  44. div.card
  45. b-table(v-bind:data="roleMappings", icon-pack="fas", default-sort="username", striped=true)
  46. template(slot-scope="props")
  47. b-table-column(field="username", label="User Name", sortable="")
  48. | {{ props.row.username }}
  49. b-table-column(field="rolename", label="Role", sortable="")
  50. b-dropdown(aria-role="list")
  51. button.button.is-primary(slot="trigger")
  52. span {{ props.row.rolename }}
  53. b-icon(icon="chevron-down", pack="fas", size="is-small", custom-size="fa-xs")
  54. b-dropdown-item(
  55. v-for="otherRole in getOtherRoles(props.row.role)"
  56. v-bind:key="otherRole.id"
  57. aria-role="listitem"
  58. v-on:click="switchRole(props.row.user, otherRole.id)"
  59. )
  60. | {{ otherRole.name }}
  61. b-table-column(label="Action")
  62. a.button.is-text(v-on:click="removeRoleMapping(props.row.id)")
  63. span.icon.is-small
  64. i.fas.fa-trash
  65. span Delete
  66. </template>
  67. <style scoped>
  68. .user-table {
  69. padding: 40px 20px;
  70. }
  71. </style>
  72. <script>
  73. import HTTP, { defaultHttpClient } from './http';
  74. export default {
  75. data: () => ({
  76. input: '',
  77. project: Object,
  78. newRoleMapping: null,
  79. hasNewUserError: false,
  80. roleMappings: [],
  81. allUsers: [],
  82. otherUsers: [],
  83. roles: [],
  84. }),
  85. computed: {
  86. isDisabled() {
  87. return !this.newRoleMapping.userid || !this.newRoleMapping.roleid || this.hasNewUserError;
  88. },
  89. getAddUserMessage() {
  90. if (this.hasNewUserError) {
  91. return 'Not an exsiting user!';
  92. }
  93. if (!this.otherUsers.length) {
  94. return 'No other users left to add!';
  95. }
  96. return null;
  97. },
  98. },
  99. created() {
  100. Promise.all([
  101. HTTP.get('roles'),
  102. defaultHttpClient.get('/v1/users'),
  103. defaultHttpClient.get('/v1/roles'),
  104. ]).then(([projectRoles, users, roles]) => {
  105. this.roleMappings = projectRoles.data;
  106. this.allUsers = users.data;
  107. this.otherUsers = this.getOtherUsers();
  108. this.roles = roles.data;
  109. });
  110. },
  111. methods: {
  112. createNewRoleMapping() {
  113. this.newRoleMapping = {
  114. userid: null,
  115. roleid: null,
  116. username: null,
  117. };
  118. },
  119. addRoleMapping() {
  120. HTTP.post('roles', { user: this.newRoleMapping.userid, role: this.newRoleMapping.roleid })
  121. .then((response) => {
  122. this.roleMappings.push(response.data);
  123. this.otherUsers = this.getOtherUsers();
  124. this.cancelCreate();
  125. });
  126. },
  127. checkValidExistingUser(inputValue) {
  128. this.hasNewUserError = !this.otherUsers.some(user => user.username === inputValue);
  129. return inputValue;
  130. },
  131. cancelCreate() {
  132. this.newRoleMapping = null;
  133. },
  134. removeRoleMapping(roleMappingId) {
  135. HTTP.delete(`roles/${roleMappingId}`).then(() => {
  136. this.roleMappings = this.roleMappings.filter(
  137. roleMapping => roleMapping.id !== roleMappingId,
  138. );
  139. this.otherUsers = this.getOtherUsers();
  140. });
  141. },
  142. switchRole(userId, newRoleId) {
  143. const currentRoleMapping = this.roleMappings.find(roleMapping => roleMapping.user === userId);
  144. const newRole = this.roles.find(role => role.id === newRoleId);
  145. HTTP.patch(`roles/${currentRoleMapping.id}`, { role: newRoleId }).then(() => {
  146. this.roleMappings = this.roleMappings.map((roleMapping) => {
  147. if (roleMapping.id === currentRoleMapping.id) {
  148. return {
  149. ...currentRoleMapping,
  150. role: newRole.id,
  151. rolename: newRole.name,
  152. };
  153. }
  154. return roleMapping;
  155. });
  156. });
  157. },
  158. getOtherRoles(currentRoleID) {
  159. return this.roles.filter(role => role.id !== currentRoleID);
  160. },
  161. getOtherUsers() {
  162. const currentUserIds = new Set(this.roleMappings.map(roleMapping => roleMapping.user));
  163. return this.allUsers.filter(user => !currentUserIds.has(user.id));
  164. },
  165. },
  166. };
  167. </script>