Spaces:
Build error
Build error
| <script lang="ts"> | |
| import { getContext, createEventDispatcher, onMount } from 'svelte'; | |
| const i18n = getContext('i18n'); | |
| import { toast } from 'svelte-sonner'; | |
| import { page } from '$app/stores'; | |
| import { goto } from '$app/navigation'; | |
| import { createNewChannel, deleteChannelById } from '$lib/apis/channels'; | |
| import { user } from '$lib/stores'; | |
| import Spinner from '$lib/components/common/Spinner.svelte'; | |
| import Modal from '$lib/components/common/Modal.svelte'; | |
| import AccessControl from '$lib/components/workspace/common/AccessControl.svelte'; | |
| import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte'; | |
| import XMark from '$lib/components/icons/XMark.svelte'; | |
| import MemberSelector from '$lib/components/workspace/common/MemberSelector.svelte'; | |
| import Visibility from '$lib/components/workspace/common/Visibility.svelte'; | |
| import Tooltip from '$lib/components/common/Tooltip.svelte'; | |
| import WebhooksModal from '$lib/components/channel/WebhooksModal.svelte'; | |
| export let show = false; | |
| export let onSubmit: Function = () => {}; | |
| export let onUpdate: Function = () => {}; | |
| export let channel: any = null; | |
| export let edit = false; | |
| let channelTypes = ['group', 'dm']; | |
| let type = ''; | |
| let name = ''; | |
| let isPrivate = null; | |
| let accessGrants = []; | |
| let groupIds = []; | |
| let userIds = []; | |
| let loading = false; | |
| $: if (name) { | |
| name = name.replace(/\s/g, '-').toLocaleLowerCase(); | |
| } | |
| $: onTypeChange(type); | |
| const onTypeChange = (type) => { | |
| if (type === 'group') { | |
| if (isPrivate === null) { | |
| isPrivate = true; | |
| } | |
| } else { | |
| isPrivate = null; | |
| } | |
| }; | |
| const submitHandler = async () => { | |
| loading = true; | |
| if (name.length > 128) { | |
| toast.error($i18n.t('Channel name must be less than 128 characters')); | |
| loading = false; | |
| return; | |
| } | |
| await onSubmit({ | |
| type: type, | |
| name: name.replace(/\s/g, '-'), | |
| is_private: type === 'group' ? (isPrivate ?? true) : null, | |
| access_grants: type === '' ? accessGrants : [], | |
| group_ids: groupIds, | |
| user_ids: userIds | |
| }); | |
| show = false; | |
| loading = false; | |
| }; | |
| const init = () => { | |
| if ($user?.role === 'admin') { | |
| channelTypes = ['', 'group', 'dm']; | |
| } else { | |
| channelTypes = ['group', 'dm']; | |
| } | |
| type = channel?.type ?? channelTypes[0]; | |
| if (channel) { | |
| name = channel?.name ?? ''; | |
| if (type === 'group') { | |
| isPrivate = typeof channel?.is_private === 'boolean' ? channel.is_private : true; | |
| } else { | |
| isPrivate = null; | |
| } | |
| accessGrants = channel?.access_grants ?? []; | |
| userIds = channel?.user_ids ?? []; | |
| } | |
| }; | |
| $: if (show) { | |
| init(); | |
| } else { | |
| resetHandler(); | |
| } | |
| let showDeleteConfirmDialog = false; | |
| let showWebhooksModal = false; | |
| const deleteHandler = async () => { | |
| showDeleteConfirmDialog = false; | |
| if (!channel?.id) { | |
| show = false; | |
| return; | |
| } | |
| const channelId = channel.id; | |
| const res = await deleteChannelById(localStorage.token, channelId).catch((error) => { | |
| toast.error(error.message); | |
| }); | |
| if (res) { | |
| toast.success($i18n.t('Channel deleted successfully')); | |
| onUpdate(); | |
| if ($page.url.pathname === `/channels/${channelId}`) { | |
| goto('/'); | |
| } | |
| } | |
| show = false; | |
| }; | |
| const resetHandler = () => { | |
| type = ''; | |
| name = ''; | |
| accessGrants = []; | |
| userIds = []; | |
| loading = false; | |
| }; | |
| </script> | |
| <Modal size="md" bind:show> | |
| <div> | |
| <div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-1"> | |
| <div class=" text-lg font-medium self-center"> | |
| {#if edit} | |
| {$i18n.t('Edit Channel')} | |
| {:else} | |
| {$i18n.t('Create Channel')} | |
| {/if} | |
| </div> | |
| <button | |
| class="self-center" | |
| on:click={() => { | |
| show = false; | |
| }} | |
| > | |
| <XMark className={'size-5'} /> | |
| </button> | |
| </div> | |
| <div class="flex flex-col md:flex-row w-full px-5 pb-4 md:space-x-4 dark:text-gray-200"> | |
| <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6"> | |
| <form | |
| class="flex flex-col w-full" | |
| on:submit|preventDefault={() => { | |
| submitHandler(); | |
| }} | |
| > | |
| {#if !edit} | |
| <div class="flex flex-col w-full mt-2 mb-1"> | |
| <div class=" mb-1 text-xs text-gray-500">{$i18n.t('Channel Type')}</div> | |
| <div class="flex-1"> | |
| <Tooltip | |
| content={type === 'dm' | |
| ? $i18n.t('A private conversation between you and selected users') | |
| : type === 'group' | |
| ? $i18n.t('A collaboration channel where people join as members') | |
| : $i18n.t( | |
| 'A discussion channel where access is controlled by groups and permissions' | |
| )} | |
| placement="top-start" | |
| > | |
| <select | |
| class="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden" | |
| bind:value={type} | |
| > | |
| {#each channelTypes as channelType, channelTypeIdx (channelType)} | |
| <option value={channelType} selected={channelTypeIdx === 0}> | |
| {#if channelType === 'group'} | |
| {$i18n.t('Group Channel')} | |
| {:else if channelType === 'dm'} | |
| {$i18n.t('Direct Message')} | |
| {:else if channelType === ''} | |
| {$i18n.t('Channel')} | |
| {/if} | |
| </option> | |
| {/each} | |
| </select> | |
| </Tooltip> | |
| </div> | |
| </div> | |
| {/if} | |
| <div class=" text-gray-300 dark:text-gray-700 text-xs"> | |
| {#if type === ''} | |
| {$i18n.t('Discussion channel where access is based on groups and permissions')} | |
| {:else if type === 'group'} | |
| {$i18n.t('Collaboration channel where people join as members')} | |
| {:else if type === 'dm'} | |
| {$i18n.t('Private conversation between selected users')} | |
| {/if} | |
| </div> | |
| <div class="flex flex-col w-full mt-2"> | |
| <div class=" mb-1 text-xs text-gray-500"> | |
| {$i18n.t('Channel Name')} | |
| <span class="text-xs text-gray-200 dark:text-gray-800 ml-0.5" | |
| >{type === 'dm' ? `${$i18n.t('Optional')}` : ''}</span | |
| > | |
| </div> | |
| <div class="flex-1"> | |
| <input | |
| class="w-full text-sm bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden" | |
| type="text" | |
| bind:value={name} | |
| placeholder={`${$i18n.t('new-channel')}`} | |
| autocomplete="off" | |
| required={type !== 'dm'} | |
| max="100" | |
| /> | |
| </div> | |
| </div> | |
| {#if type !== 'dm'} | |
| <div class="-mx-2 mb-1 mt-2.5 px-2"> | |
| {#if type === ''} | |
| <AccessControl bind:accessGrants accessRoles={['read', 'write']} /> | |
| {:else if type === 'group'} | |
| <Visibility | |
| state={isPrivate ? 'private' : 'public'} | |
| onChange={(value: string) => { | |
| if (value === 'private') { | |
| isPrivate = true; | |
| } else { | |
| isPrivate = false; | |
| } | |
| console.log(value, isPrivate); | |
| }} | |
| /> | |
| {/if} | |
| </div> | |
| {/if} | |
| {#if ['dm'].includes(type)} | |
| <div class=""> | |
| <MemberSelector bind:userIds includeGroups={false} /> | |
| </div> | |
| {/if} | |
| {#if edit} | |
| <div class="flex w-full mt-2 items-center justify-between"> | |
| <div class="text-xs text-gray-500">{$i18n.t('Webhooks')}</div> | |
| <button | |
| class="text-xs bg-transparent placeholder:text-gray-300 dark:placeholder:text-gray-700 outline-hidden text-left" | |
| type="button" | |
| on:click={() => { | |
| showWebhooksModal = true; | |
| }} | |
| > | |
| {$i18n.t('Manage')} | |
| </button> | |
| </div> | |
| {/if} | |
| <div class="flex justify-end pt-3 text-sm font-medium gap-1.5"> | |
| {#if edit} | |
| <button | |
| class="px-3.5 py-1.5 text-sm font-medium dark:bg-black dark:hover:bg-black/90 dark:text-white bg-white text-black hover:bg-gray-100 transition rounded-full flex flex-row space-x-1 items-center" | |
| type="button" | |
| on:click={() => { | |
| showDeleteConfirmDialog = true; | |
| }} | |
| > | |
| {$i18n.t('Delete')} | |
| </button> | |
| {/if} | |
| <button | |
| class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-950 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full flex flex-row space-x-1 items-center {loading | |
| ? ' cursor-not-allowed' | |
| : ''}" | |
| type="submit" | |
| disabled={loading} | |
| > | |
| {#if edit} | |
| {$i18n.t('Update')} | |
| {:else} | |
| {$i18n.t('Create')} | |
| {/if} | |
| {#if loading} | |
| <div class="ml-2 self-center"> | |
| <Spinner /> | |
| </div> | |
| {/if} | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| </Modal> | |
| <DeleteConfirmDialog | |
| bind:show={showDeleteConfirmDialog} | |
| message={$i18n.t('Are you sure you want to delete this channel?')} | |
| confirmLabel={$i18n.t('Delete')} | |
| on:confirm={() => { | |
| deleteHandler(); | |
| }} | |
| /> | |
| <WebhooksModal bind:show={showWebhooksModal} {channel} /> | |