+layout.svelte 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <script lang="ts">
  2. import { onMount, getContext } from 'svelte';
  3. import {
  4. WEBUI_NAME,
  5. showSidebar,
  6. functions,
  7. user,
  8. mobile,
  9. models,
  10. prompts,
  11. knowledge,
  12. tools
  13. } from '$lib/stores';
  14. import { page } from '$app/stores';
  15. import { goto } from '$app/navigation';
  16. import MenuLines from '$lib/components/icons/MenuLines.svelte';
  17. const i18n = getContext('i18n');
  18. let loaded = false;
  19. onMount(async () => {
  20. if ($user?.role !== 'admin') {
  21. if ($page.url.pathname.includes('/models') && !$user?.permissions?.workspace?.models) {
  22. goto('/');
  23. } else if (
  24. $page.url.pathname.includes('/knowledge') &&
  25. !$user?.permissions?.workspace?.knowledge
  26. ) {
  27. goto('/');
  28. } else if (
  29. $page.url.pathname.includes('/prompts') &&
  30. !$user?.permissions?.workspace?.prompts
  31. ) {
  32. goto('/');
  33. } else if ($page.url.pathname.includes('/tools') && !$user?.permissions?.workspace?.tools) {
  34. goto('/');
  35. }
  36. }
  37. loaded = true;
  38. });
  39. </script>
  40. <svelte:head>
  41. <title>
  42. {$i18n.t('Workspace')} | {$WEBUI_NAME}
  43. </title>
  44. </svelte:head>
  45. {#if loaded}
  46. <div
  47. class=" relative flex flex-col w-full h-screen max-h-[100dvh] {$showSidebar
  48. ? 'md:max-w-[calc(100%-260px)]'
  49. : ''}"
  50. >
  51. <nav class=" px-2.5 pt-1 backdrop-blur-xl drag-region">
  52. <div class=" flex items-center gap-1">
  53. <div class="{$showSidebar ? 'md:hidden' : ''} self-center flex flex-none items-center">
  54. <button
  55. id="sidebar-toggle-button"
  56. class="cursor-pointer p-1.5 flex rounded-xl hover:bg-gray-100 dark:hover:bg-gray-850 transition"
  57. on:click={() => {
  58. showSidebar.set(!$showSidebar);
  59. }}
  60. aria-label="Toggle Sidebar"
  61. >
  62. <div class=" m-auto self-center">
  63. <MenuLines />
  64. </div>
  65. </button>
  66. </div>
  67. <div class="">
  68. <div
  69. class="flex gap-1 scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium rounded-full bg-transparent py-1 touch-auto pointer-events-auto"
  70. >
  71. {#if $user?.role === 'admin' || $user?.permissions?.workspace?.models}
  72. <a
  73. class="min-w-fit rounded-full p-1.5 {$page.url.pathname.includes(
  74. '/workspace/models'
  75. )
  76. ? ''
  77. : 'text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
  78. href="/workspace/models">{$i18n.t('Models')}</a
  79. >
  80. {/if}
  81. {#if $user?.role === 'admin' || $user?.permissions?.workspace?.knowledge}
  82. <a
  83. class="min-w-fit rounded-full p-1.5 {$page.url.pathname.includes(
  84. '/workspace/knowledge'
  85. )
  86. ? ''
  87. : 'text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
  88. href="/workspace/knowledge"
  89. >
  90. {$i18n.t('Knowledge')}
  91. </a>
  92. {/if}
  93. {#if $user?.role === 'admin' || $user?.permissions?.workspace?.prompts}
  94. <a
  95. class="min-w-fit rounded-full p-1.5 {$page.url.pathname.includes(
  96. '/workspace/prompts'
  97. )
  98. ? ''
  99. : 'text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
  100. href="/workspace/prompts">{$i18n.t('Prompts')}</a
  101. >
  102. {/if}
  103. {#if $user?.role === 'admin' || $user?.permissions?.workspace?.tools}
  104. <a
  105. class="min-w-fit rounded-full p-1.5 {$page.url.pathname.includes('/workspace/tools')
  106. ? ''
  107. : 'text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'} transition"
  108. href="/workspace/tools"
  109. >
  110. {$i18n.t('Tools')}
  111. </a>
  112. {/if}
  113. </div>
  114. </div>
  115. <!-- <div class="flex items-center text-xl font-semibold">{$i18n.t('Workspace')}</div> -->
  116. </div>
  117. </nav>
  118. <div class=" pb-1 px-[18px] flex-1 max-h-full overflow-y-auto" id="workspace-container">
  119. <slot />
  120. </div>
  121. </div>
  122. {/if}