index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <template>
  2. <div>
  3. <page-metadata title="Admin | Users" />
  4. <div class="container">
  5. <advanced-table
  6. :column-default="columnDefault"
  7. :columns="columns"
  8. :filters="filters"
  9. data-action="users.getData"
  10. name="admin-users"
  11. max-width="1200"
  12. :events="events"
  13. >
  14. <template #column-options="slotProps">
  15. <div class="row-options">
  16. <button
  17. class="button is-primary icon-with-button material-icons"
  18. @click="edit(slotProps.item._id)"
  19. :disabled="slotProps.item.removed"
  20. content="Edit User"
  21. v-tippy
  22. >
  23. edit
  24. </button>
  25. <router-link
  26. :to="{ path: `/u/${slotProps.item.username}` }"
  27. target="_blank"
  28. class="button is-primary icon-with-button material-icons"
  29. :disabled="slotProps.item.removed"
  30. content="View Profile"
  31. v-tippy
  32. >
  33. person
  34. </router-link>
  35. </div>
  36. </template>
  37. <template #column-profilePicture="slotProps">
  38. <profile-picture
  39. :avatar="slotProps.item.avatar"
  40. :name="
  41. slotProps.item.name
  42. ? slotProps.item.name
  43. : slotProps.item.username
  44. "
  45. />
  46. </template>
  47. <template #column-name="slotProps">
  48. <span :title="slotProps.item.name">{{
  49. slotProps.item.name
  50. }}</span>
  51. </template>
  52. <template #column-username="slotProps">
  53. <span :title="slotProps.item.username">{{
  54. slotProps.item.username
  55. }}</span>
  56. </template>
  57. <template #column-_id="slotProps">
  58. <span :title="slotProps.item._id">{{
  59. slotProps.item._id
  60. }}</span>
  61. </template>
  62. <template #column-githubId="slotProps">
  63. <span
  64. v-if="slotProps.item.services.github"
  65. :title="slotProps.item.services.github.id"
  66. >{{ slotProps.item.services.github.id }}</span
  67. >
  68. </template>
  69. <template #column-hasPassword="slotProps">
  70. <span :title="slotProps.item.hasPassword">{{
  71. slotProps.item.hasPassword
  72. }}</span>
  73. </template>
  74. <template #column-role="slotProps">
  75. <span :title="slotProps.item.role">{{
  76. slotProps.item.role
  77. }}</span>
  78. </template>
  79. <template #column-emailAddress="slotProps">
  80. <span :title="slotProps.item.email.address">{{
  81. slotProps.item.email.address
  82. }}</span>
  83. </template>
  84. <template #column-emailVerified="slotProps">
  85. <span :title="slotProps.item.email.verified">{{
  86. slotProps.item.email.verified
  87. }}</span>
  88. </template>
  89. <template #column-songsRequested="slotProps">
  90. <span :title="slotProps.item.statistics.songsRequested">{{
  91. slotProps.item.statistics.songsRequested
  92. }}</span>
  93. </template>
  94. </advanced-table>
  95. </div>
  96. </div>
  97. </template>
  98. <script>
  99. import { mapState, mapActions } from "vuex";
  100. import AdvancedTable from "@/components/AdvancedTable.vue";
  101. import ProfilePicture from "@/components/ProfilePicture.vue";
  102. export default {
  103. components: {
  104. AdvancedTable,
  105. ProfilePicture
  106. },
  107. data() {
  108. return {
  109. columnDefault: {
  110. sortable: true,
  111. hidable: true,
  112. defaultVisibility: "shown",
  113. draggable: true,
  114. resizable: true,
  115. minWidth: 150,
  116. maxWidth: 600
  117. },
  118. columns: [
  119. {
  120. name: "options",
  121. displayName: "Options",
  122. properties: ["_id", "username"],
  123. sortable: false,
  124. hidable: false,
  125. resizable: false,
  126. minWidth: 85,
  127. defaultWidth: 85
  128. },
  129. {
  130. name: "profilePicture",
  131. displayName: "Image",
  132. properties: ["avatar", "name", "username"],
  133. sortable: false,
  134. resizable: false,
  135. minWidth: 71,
  136. defaultWidth: 71
  137. },
  138. {
  139. name: "name",
  140. displayName: "Display Name",
  141. properties: ["name"],
  142. sortProperty: "name"
  143. },
  144. {
  145. name: "username",
  146. displayName: "Username",
  147. properties: ["username"],
  148. sortProperty: "username"
  149. },
  150. {
  151. name: "_id",
  152. displayName: "User ID",
  153. properties: ["_id"],
  154. sortProperty: "_id",
  155. minWidth: 230,
  156. defaultWidth: 230
  157. },
  158. {
  159. name: "githubId",
  160. displayName: "GitHub ID",
  161. properties: ["services.github.id"],
  162. sortProperty: "services.github.id",
  163. minWidth: 115,
  164. defaultWidth: 115
  165. },
  166. {
  167. name: "hasPassword",
  168. displayName: "Has Password",
  169. properties: ["hasPassword"],
  170. sortProperty: "hasPassword"
  171. },
  172. {
  173. name: "role",
  174. displayName: "Role",
  175. properties: ["role"],
  176. sortProperty: "role",
  177. minWidth: 90,
  178. defaultWidth: 90
  179. },
  180. {
  181. name: "emailAddress",
  182. displayName: "Email Address",
  183. properties: ["email.address"],
  184. sortProperty: "email.address",
  185. defaultVisibility: "hidden"
  186. },
  187. {
  188. name: "emailVerified",
  189. displayName: "Email Verified",
  190. properties: ["email.verified"],
  191. sortProperty: "email.verified",
  192. defaultVisibility: "hidden",
  193. minWidth: 140,
  194. defaultWidth: 140
  195. },
  196. {
  197. name: "songsRequested",
  198. displayName: "Songs Requested",
  199. properties: ["statistics.songsRequested"],
  200. sortProperty: "statistics.songsRequested",
  201. minWidth: 170,
  202. defaultWidth: 170
  203. }
  204. ],
  205. filters: [
  206. {
  207. name: "_id",
  208. displayName: "User ID",
  209. property: "_id",
  210. filterTypes: ["exact"],
  211. defaultFilterType: "exact"
  212. },
  213. {
  214. name: "name",
  215. displayName: "Display Name",
  216. property: "name",
  217. filterTypes: ["contains", "exact", "regex"],
  218. defaultFilterType: "contains"
  219. },
  220. {
  221. name: "username",
  222. displayName: "Username",
  223. property: "username",
  224. filterTypes: ["contains", "exact", "regex"],
  225. defaultFilterType: "contains"
  226. },
  227. {
  228. name: "githubId",
  229. displayName: "GitHub ID",
  230. property: "services.github.id",
  231. filterTypes: ["contains", "exact", "regex"],
  232. defaultFilterType: "contains"
  233. },
  234. {
  235. name: "hasPassword",
  236. displayName: "Has Password",
  237. property: "hasPassword",
  238. filterTypes: ["boolean"],
  239. defaultFilterType: "boolean"
  240. },
  241. {
  242. name: "role",
  243. displayName: "Role",
  244. property: "role",
  245. filterTypes: ["exact"],
  246. defaultFilterType: "exact",
  247. dropdown: [
  248. ["admin", "Admin"],
  249. ["default", "Default"]
  250. ]
  251. },
  252. {
  253. name: "emailAddress",
  254. displayName: "Email Address",
  255. property: "email.address",
  256. filterTypes: ["contains", "exact", "regex"],
  257. defaultFilterType: "contains"
  258. },
  259. {
  260. name: "emailVerified",
  261. displayName: "Email Verified",
  262. property: "email.verified",
  263. filterTypes: ["boolean"],
  264. defaultFilterType: "boolean"
  265. },
  266. {
  267. name: "songsRequested",
  268. displayName: "Songs Requested",
  269. property: "statistics.songsRequested",
  270. filterTypes: [
  271. "numberLesserEqual",
  272. "numberLesser",
  273. "numberGreater",
  274. "numberGreaterEqual",
  275. "numberEquals"
  276. ],
  277. defaultFilterType: "numberLesser"
  278. }
  279. ],
  280. events: {
  281. adminRoom: "users",
  282. updated: {
  283. event: "admin.user.updated",
  284. id: "user._id",
  285. item: "user"
  286. },
  287. removed: {
  288. event: "user.removed",
  289. id: "userId"
  290. }
  291. }
  292. };
  293. },
  294. computed: {
  295. ...mapState("modalVisibility", {
  296. modals: state => state.modals
  297. })
  298. },
  299. mounted() {
  300. if (this.$route.query.userId) this.edit(this.$route.query.userId);
  301. },
  302. methods: {
  303. edit(userId) {
  304. this.openModal({ modal: "editUser", data: { userId } });
  305. },
  306. ...mapActions("modalVisibility", ["openModal"])
  307. }
  308. };
  309. </script>
  310. <style lang="less" scoped>
  311. .profile-picture {
  312. max-width: 50px !important;
  313. max-height: 50px !important;
  314. }
  315. :deep(.profile-picture.using-initials span) {
  316. font-size: 20px; // 2/5th of .profile-picture height/width
  317. }
  318. </style>