Groups.svelte 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <script>
  2. import { toast } from 'svelte-sonner';
  3. import dayjs from 'dayjs';
  4. import relativeTime from 'dayjs/plugin/relativeTime';
  5. dayjs.extend(relativeTime);
  6. import { onMount, getContext } from 'svelte';
  7. import { goto } from '$app/navigation';
  8. import { WEBUI_NAME, config, user, showSidebar } from '$lib/stores';
  9. import { WEBUI_BASE_URL } from '$lib/constants';
  10. import Tooltip from '$lib/components/common/Tooltip.svelte';
  11. import Plus from '$lib/components/icons/Plus.svelte';
  12. const i18n = getContext('i18n');
  13. let loaded = false;
  14. let groups = [];
  15. let filteredGroups;
  16. $: filteredGroups = groups.filter((user) => {
  17. if (search === '') {
  18. return true;
  19. } else {
  20. let name = user.name.toLowerCase();
  21. const query = search.toLowerCase();
  22. return name.includes(query);
  23. }
  24. });
  25. let search = '';
  26. let showCreateGroupModal = false;
  27. onMount(async () => {
  28. if ($user?.role !== 'admin') {
  29. await goto('/');
  30. } else {
  31. groups = [];
  32. }
  33. loaded = true;
  34. });
  35. </script>
  36. {#if loaded}
  37. <div class="mt-0.5 mb-2 gap-1 flex flex-col md:flex-row justify-between">
  38. <div class="flex md:self-center text-lg font-medium px-0.5">
  39. {$i18n.t('Groups')}
  40. <div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-50 dark:bg-gray-850" />
  41. <span class="text-lg font-medium text-gray-500 dark:text-gray-300">{groups.length}</span>
  42. </div>
  43. <div class="flex gap-1">
  44. <div class=" flex w-full space-x-2">
  45. <div class="flex flex-1">
  46. <div class=" self-center ml-1 mr-3">
  47. <svg
  48. xmlns="http://www.w3.org/2000/svg"
  49. viewBox="0 0 20 20"
  50. fill="currentColor"
  51. class="w-4 h-4"
  52. >
  53. <path
  54. fill-rule="evenodd"
  55. d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z"
  56. clip-rule="evenodd"
  57. />
  58. </svg>
  59. </div>
  60. <input
  61. class=" w-full text-sm pr-4 py-1 rounded-r-xl outline-none bg-transparent"
  62. bind:value={search}
  63. placeholder={$i18n.t('Search')}
  64. />
  65. </div>
  66. <div>
  67. <Tooltip content={$i18n.t('Create Group')}>
  68. <button
  69. class=" p-2 rounded-xl hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 transition font-medium text-sm flex items-center space-x-1"
  70. on:click={() => {
  71. showCreateGroupModal = !showCreateGroupModal;
  72. }}
  73. >
  74. <Plus className="size-3.5" />
  75. </button>
  76. </Tooltip>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. <div>
  82. {#if filteredGroups.length === 0}
  83. <div class="flex flex-col items-center justify-center h-40">
  84. <div class=" text-xl font-medium">
  85. {$i18n.t('Organize your users')}
  86. </div>
  87. <div class="mt-1 text-sm dark:text-gray-300">
  88. {$i18n.t('Use groups to group your users and assign permissions.')}
  89. </div>
  90. <div class="mt-3">
  91. <button
  92. class=" px-4 py-1.5 text-sm rounded-full bg-black hover:bg-gray-800 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition font-medium flex items-center space-x-1"
  93. aria-label={$i18n.t('Create Group')}
  94. on:click={() => {
  95. showCreateGroupModal = true;
  96. }}
  97. >
  98. {$i18n.t('Create Group')}
  99. </button>
  100. </div>
  101. </div>
  102. {:else}
  103. <div></div>
  104. {/if}
  105. </div>
  106. {/if}