* feat: new components, deploy storybook * refactor: simplify component field definitions and enhance button loading state - Removed unnecessary type imports and simplified the FIELDS array definitions across multiple components in Storybook. - Updated button component to use a loading state instead of isLoading, improving clarity and consistency in props. - Adjusted button stories to reflect the new loading prop and enhanced the button's loading visual feedback. - Minor CSS adjustments for better layout and styling consistency. * chore: add field, card, password components * feat: improve page component & update AuthUI path * chore: update bits-ui to version 2.14.4 and all org related UI's - Updated bits-ui dependency in pnpm-lock.yaml and package.json to version 2.14.4. - Refactored imports for RoleBasedSecurity and UpgradeBanner components to use the new ui feature directory. - Removed unused Course components and related files to clean up the codebase. - Enhanced various components to improve consistency and maintainability. * chore: move all setting buttons to the top and update auth ui styles * chore: remove svelte-loading-spinners and replace with @cio/ui/base/spinner - Removed all instances of svelte-loading-spinners from the project. - Updated components to use the new Spinner from @cio/ui/base/spinner. - Cleaned up pnpm-lock.yaml and package.json to reflect the removal of svelte-loading-spinners. - Added new CSS animations for rocket launch effects in app.css. - Enhanced email change flow with updated verification messages in translations. * chore: remove supabase file upload from dashboard and move to r2 * chore: update organization API and UI components - Added new API methods for organization plan operations and team management. - Introduced middleware for API key authentication and organization admin checks. - Refactored organization-related components to utilize the new API structure. - Updated various UI components to improve consistency and maintainability. - Enhanced error handling and validation for organization-related actions. - Removed deprecated services and streamlined the codebase.
188 lines
7.1 KiB
Svelte
188 lines
7.1 KiB
Svelte
<script lang="ts">
|
|
import { Label } from '@cio/ui/base/label';
|
|
import { Switch } from '@cio/ui/base/switch';
|
|
import SaveIcon from '@lucide/svelte/icons/save';
|
|
|
|
import { currentOrg } from '$lib/utils/store/org';
|
|
import { t } from '$lib/utils/functions/translations';
|
|
import { snackbar } from '$lib/components/Snackbar/store';
|
|
import { getSupabase } from '$lib/utils/functions/supabase';
|
|
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
|
import { handleOpenWidget } from '$lib/components/CourseLandingPage/store';
|
|
|
|
import { Row, Grid, Column } from './Layout';
|
|
import SectionTitle from '../SectionTitle.svelte';
|
|
import TextField from '$lib/components/Form/TextField.svelte';
|
|
import UploadWidget from '$lib/components/UploadWidget/index.svelte';
|
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
|
|
|
const supabase = getSupabase();
|
|
|
|
let widgetKey = $state('');
|
|
let isSaving = $state(false);
|
|
|
|
function widgetControl(key: string) {
|
|
widgetKey = key;
|
|
$handleOpenWidget.open = true;
|
|
}
|
|
|
|
async function handleSave() {
|
|
isSaving = true;
|
|
|
|
const { error } = await supabase
|
|
.from('organization')
|
|
.update({ customization: $currentOrg.customization })
|
|
.match({ id: $currentOrg.id });
|
|
|
|
if (error) {
|
|
const message = error?.message || 'snackbar.lms.error.try_again';
|
|
console.error('Error updating customizations', message);
|
|
snackbar.error('snackbar.update_failed');
|
|
} else {
|
|
snackbar.success('snackbar.success_update');
|
|
}
|
|
|
|
isSaving = false;
|
|
}
|
|
</script>
|
|
|
|
<Grid class="border-c relative mt-5 w-full rounded border-gray-200 dark:border-neutral-600">
|
|
<Row class="border-bottom-c flex flex-col items-start py-7 lg:flex-row">
|
|
<Column sm={4} md={4} lg={4}>
|
|
<SectionTitle>{$t('components.settings.customize_lms.dashboard.title')}</SectionTitle>
|
|
</Column>
|
|
|
|
<Column sm={8} md={8} lg={8} class="space-y-2">
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.dashboard.community')}</p>
|
|
<div class="mb-3 flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.dashboard.community} />
|
|
|
|
<Label class="text-sm">
|
|
{$currentOrg.customization.dashboard.community
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.dashboard.exercises')}</p>
|
|
<div class="mb-3 flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.dashboard.exercise} />
|
|
|
|
<Label class="text-sm">
|
|
{$currentOrg.customization.dashboard.exercise
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.dashboard.banner_image')}</p>
|
|
<PrimaryButton
|
|
variant={VARIANTS.OUTLINED}
|
|
label={$t('components.settings.customize_lms.dashboard.banner_image_btn')}
|
|
className="mt-3"
|
|
onClick={() => widgetControl('banner-image')}
|
|
/>
|
|
{#if $currentOrg.customization.dashboard.bannerImage}
|
|
<img alt="Banner" src={$currentOrg.customization.dashboard.bannerImage} class="mt-2 w-full rounded-md" />
|
|
{/if}
|
|
{#if $handleOpenWidget.open && widgetKey === 'banner-image'}
|
|
<UploadWidget bind:imageURL={$currentOrg.customization.dashboard.bannerImage} />
|
|
{/if}
|
|
</div>
|
|
|
|
<div>
|
|
<p>{$t('components.settings.customize_lms.dashboard.banner_text')}</p>
|
|
<TextField
|
|
label={$t('components.settings.customize_lms.dashboard.banner_text_label')}
|
|
placeholder={$t('components.settings.customize_lms.dashboard.banner_text_placeholder')}
|
|
bind:value={$currentOrg.customization.dashboard.bannerText}
|
|
/>
|
|
</div>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="border-bottom-c flex flex-col py-7 lg:flex-row">
|
|
<Column sm={4} md={4} lg={4}
|
|
><SectionTitle>{$t('components.settings.customize_lms.course.title')}</SectionTitle></Column
|
|
>
|
|
<Column sm={8} md={8} lg={8} class="space-y-4">
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.course.newsfeed')}</p>
|
|
<div class="flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.course.newsfeed} />
|
|
|
|
<Label class="text-gray-600">
|
|
{$currentOrg.customization.course.newsfeed
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.course.grading')}</p>
|
|
<div class="flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.course.grading} />
|
|
<Label class="text-gray-600">
|
|
{$currentOrg.customization.course.grading
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="border-bottom-c flex flex-col py-7 lg:flex-row">
|
|
<Column sm={4} md={4} lg={4}
|
|
><SectionTitle>{$t('components.settings.customize_lms.apps.title')}</SectionTitle></Column
|
|
>
|
|
<Column sm={8} md={8} lg={8} class="space-y-4">
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.apps.poll')}</p>
|
|
<div class="flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.apps.poll} />
|
|
|
|
<Label class="text-gray-600">
|
|
{$currentOrg.customization.apps.poll
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col gap-3">
|
|
<p class="text-sm">{$t('components.settings.customize_lms.apps.live_comment')}</p>
|
|
<div class="flex items-center space-x-2">
|
|
<Switch bind:checked={$currentOrg.customization.apps.comments} />
|
|
|
|
<Label class="text-gray-600">
|
|
{$currentOrg.customization.apps.comments
|
|
? $t('components.settings.customize_lms.enabled')
|
|
: $t('components.settings.customize_lms.disabled')}
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
</Column>
|
|
</Row>
|
|
|
|
<div class="sticky bottom-12 z-[120] float-right mr-2 hidden md:block">
|
|
<PrimaryButton
|
|
label={$t('components.settings.customize_lms.save')}
|
|
onClick={handleSave}
|
|
isLoading={isSaving}
|
|
isDisabled={isSaving}
|
|
/>
|
|
</div>
|
|
</Grid>
|
|
|
|
<div class="absolute bottom-8 right-6 z-[120] block md:hidden">
|
|
<PrimaryButton onClick={handleSave} isLoading={isSaving} isDisabled={isSaving}>
|
|
<SaveIcon size={16} />
|
|
</PrimaryButton>
|
|
</div>
|