Files
classroomio/apps/dashboard/src/lib/utils/store/org.ts
T

179 lines
4.6 KiB
TypeScript
Raw Normal View History

import { browser, dev } from '$app/environment';
import { derived, writable } from 'svelte/store';
import merge from 'lodash/merge';
import type { AccountOrg } from '$features/app/types';
import type { OrgTeamMember } from '../types/org';
2025-11-01 15:49:29 +01:00
import { PLAN } from '@cio/utils/plans';
import { PUBLIC_IS_SELFHOSTED } from '$env/static/public';
import { ROLE } from '@cio/utils/constants';
import { STEPS } from '../constants/quiz';
import type { Writable } from 'svelte/store';
/** Deep-merge with this when hydrating an org from the API so nested `customization` keys stay stable. */
export const DEFAULT_ORG_CUSTOMIZATION = {
apps: { poll: true, comments: true },
course: { grading: true, newsfeed: true },
dashboard: { exercise: true, community: true, bannerText: '', bannerImage: '' },
auth: { backgroundImage: '' }
} as NonNullable<AccountOrg['customization']>;
export function mergeAccountOrgFromServer(org: AccountOrg): AccountOrg {
return {
...org,
customization: merge({}, DEFAULT_ORG_CUSTOMIZATION, org.customization ?? {}) as AccountOrg['customization']
};
}
export const orgs = writable<AccountOrg[]>([]);
export const currentOrg: Writable<AccountOrg> = writable({
avatarUrl: '',
createdAt: '',
customCode: '',
customDomain: '',
customization: {
...DEFAULT_ORG_CUSTOMIZATION
},
2026-03-09 11:18:22 +01:00
disableEmailPassword: false,
disableGoogleAuth: false,
disableSignup: false,
disableSignupMessage: '',
favicon: '',
id: '',
isCustomDomainVerified: false,
isRestricted: false,
landingpage: {},
name: '',
parentOrganizationId: null,
plans: [],
readOnlyUntil: null,
roleId: 0,
settings: {},
siteName: '',
theme: ''
});
export const isSecondaryWorkspace = derived(currentOrg, ($currentOrg) => Boolean($currentOrg.parentOrganizationId));
export const isPrimaryWorkspace = derived(
currentOrg,
($currentOrg) => Boolean($currentOrg.id) && !$currentOrg.parentOrganizationId
);
export const orgTeam = writable<OrgTeamMember[]>([]);
export const isOrgAdmin = derived(currentOrg, ($currentOrg) => {
if ($currentOrg.roleId === 0) return null;
return $currentOrg.roleId === ROLE.ADMIN;
});
const getActivePlan = (org: AccountOrg) => {
return org.plans.find((p) => p.isActive);
2024-09-12 23:54:04 +01:00
};
export const currentOrgPlan = derived(currentOrg, ($currentOrg) => getActivePlan($currentOrg));
2024-09-05 15:19:45 +01:00
export const currentOrgPath = derived(currentOrg, ($currentOrg) =>
$currentOrg.siteName ? `/org/${$currentOrg.siteName}` : '#'
2023-05-20 23:53:28 +00:00
);
2024-09-05 15:19:45 +01:00
2023-10-30 04:52:00 +00:00
export const currentOrgDomain = derived(currentOrg, ($currentOrg) => {
if (PUBLIC_IS_SELFHOSTED === 'true') return window.location.origin;
2023-10-30 04:52:00 +00:00
const browserOrigin = dev && browser && window.location.origin;
// Get the root domain from window.location
let rootDomain = '';
if (browser && typeof window !== 'undefined') {
const host = window.location.hostname;
const parts = host.split('.');
if (parts.length >= 2) {
rootDomain = parts.slice(-2).join('.');
} else {
rootDomain = host;
}
}
2023-10-30 04:52:00 +00:00
return browserOrigin
? browserOrigin
2024-09-05 15:19:45 +01:00
: $currentOrg.customDomain && $currentOrg.isCustomDomainVerified
? `https://${$currentOrg.customDomain}`
: $currentOrg.siteName
? `https://${$currentOrg.siteName}.${rootDomain}`
2024-09-05 15:19:45 +01:00
: '';
2023-10-30 04:52:00 +00:00
});
2023-06-17 19:11:29 +00:00
2024-09-12 23:54:04 +01:00
export const isFreePlan = derived(currentOrg, ($currentOrg) => {
2025-09-07 10:24:34 +01:00
if (!$currentOrg.id || PUBLIC_IS_SELFHOSTED === 'true') return false;
2024-09-12 23:54:04 +01:00
const plan = getActivePlan($currentOrg);
return !plan || plan.planName === PLAN.BASIC;
});
2024-09-12 23:54:04 +01:00
2026-03-09 11:18:22 +01:00
export const isEnterprisePlan = derived(currentOrg, ($currentOrg) => {
if (PUBLIC_IS_SELFHOSTED === 'true') return true;
const plan = getActivePlan($currentOrg);
return plan?.planName === PLAN.ENTERPRISE;
});
2024-04-07 06:08:34 +01:00
export const currentOrgMaxAudience = derived(currentOrgPlan, ($plan) =>
!$plan
2024-07-31 09:48:26 +01:00
? 20
: $plan.planName === PLAN.EARLY_ADOPTER
2024-04-07 06:08:34 +01:00
? 10000
: $plan.planName === PLAN.ENTERPRISE
2024-04-07 06:08:34 +01:00
? Number.MAX_SAFE_INTEGER
2024-07-31 09:48:26 +01:00
: 20
2024-04-07 06:08:34 +01:00
);
2023-06-17 19:11:29 +00:00
// Quiz
export const createQuizModal = writable({
open: false,
openEdit: false,
title: '',
id: null
2023-06-17 19:11:29 +00:00
});
export const deleteModal = writable({
id: null,
open: false,
isQuestion: false
2023-06-17 19:11:29 +00:00
});
2025-05-03 14:46:01 +01:00
interface QuizOption {
id: number;
label: string;
isCorrect: boolean;
}
2023-06-17 19:11:29 +00:00
2025-05-03 14:46:01 +01:00
interface QuizQuestion {
id: number;
label: string;
type: string;
options: QuizOption[];
}
interface QuizStore {
uuid: string;
title: string;
questions: QuizQuestion[];
timelimit: string;
theme: string;
pin: string;
}
export const quizStore = writable<QuizStore>({
2023-06-17 19:11:29 +00:00
uuid: '',
title: '',
questions: [],
timelimit: '10s',
theme: 'standard',
pin: ''
2023-06-17 19:11:29 +00:00
});
export const playQuizStore = writable({
step: STEPS.CONNECT_TO_PLAY
2023-06-17 19:11:29 +00:00
});