init
This commit is contained in:
commit
d761a10bf7
102 changed files with 4761 additions and 0 deletions
452
lib/stores/editor.ts
Normal file
452
lib/stores/editor.ts
Normal file
|
@ -0,0 +1,452 @@
|
|||
import { SocialLink } from '$lib/models/socials';
|
||||
import type Sortable from 'sortablejs';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
interface EditorData {
|
||||
loadTime: number;
|
||||
editMode: boolean;
|
||||
draggingWidget: boolean;
|
||||
edits: EditorPublish;
|
||||
previews: EmbedCacheFetched['widgets'];
|
||||
widget?: BioSiteWidget | null;
|
||||
widgetPreview?: WidgetPreview | null;
|
||||
avatar?: string | null;
|
||||
banner?: string | null;
|
||||
sortables?: {
|
||||
left?: Sortable;
|
||||
right?: Sortable;
|
||||
};
|
||||
socialSortables?: {
|
||||
links?: Sortable;
|
||||
texts?: Sortable;
|
||||
};
|
||||
updatedSortable?: boolean;
|
||||
}
|
||||
|
||||
interface EditorStore extends EditorData {
|
||||
toggleEditMode: () => void;
|
||||
setDraggingWidget: (draggingWidget: boolean) => void;
|
||||
setActive: (widget?: BioSiteWidget) => void;
|
||||
setPreview: (preview?: WidgetPreview) => void;
|
||||
editWidget: (widget: BioSiteWidget) => void;
|
||||
deleteWidget: (id: string | number) => void;
|
||||
applyIndex: () => void;
|
||||
setSortables: (left?: Sortable, right?: Sortable) => void;
|
||||
setDisplayName: (displayName: string) => void;
|
||||
setUsername: (username: string) => void;
|
||||
setDescription: (description: string) => void;
|
||||
setLocation: (location: string) => void;
|
||||
setSchool: (school: string) => void;
|
||||
setWorkplace: (workplace: string) => void;
|
||||
setAvatar: (file: File) => void;
|
||||
deleteAvatar: () => void;
|
||||
setBanner: (file: File) => void;
|
||||
deleteBanner: () => void;
|
||||
setSocials: (
|
||||
createSocialLinks: BioSiteSocialLink[],
|
||||
createSocialTexts: BioSiteSocialText[],
|
||||
indexSocialLinks: IndexSocialLink[],
|
||||
indexSocialTexts: IndexSocialText[],
|
||||
deleteSocialLinks: number[],
|
||||
deleteSocialTexts: number[],
|
||||
) => void;
|
||||
toggleUid: (uid: boolean) => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
export const generateResetState = (): EditorData => {
|
||||
return {
|
||||
loadTime: Date.now(),
|
||||
editMode: false,
|
||||
widget: null,
|
||||
widgetPreview: null,
|
||||
avatar: null,
|
||||
banner: null,
|
||||
edits: {
|
||||
edits: {
|
||||
createWidgets: [],
|
||||
updateWidgets: [],
|
||||
deleteWidgets: [],
|
||||
indexWidgets: [],
|
||||
alignWidgets: [],
|
||||
imageWidgets: [],
|
||||
updateDisplayName: null,
|
||||
updateUsername: null,
|
||||
updateDescription: null,
|
||||
updateLocation: null,
|
||||
updateSchool: null,
|
||||
updateWorkplace: null,
|
||||
deleteBanner: null,
|
||||
deleteAvatar: null,
|
||||
toggleUid: null,
|
||||
createSocialLinks: [],
|
||||
indexSocialLinks: [],
|
||||
deleteSocialLinks: [],
|
||||
createSocialTexts: [],
|
||||
indexSocialTexts: [],
|
||||
deleteSocialTexts: [],
|
||||
},
|
||||
avatar: null,
|
||||
banner: null,
|
||||
},
|
||||
previews: {},
|
||||
updatedSortable: false,
|
||||
draggingWidget: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const editorStore = writable({
|
||||
...generateResetState(),
|
||||
toggleEditMode: () => {
|
||||
editorStore.update((store) => ({ ...store, editMode: !store.editMode }));
|
||||
},
|
||||
setDraggingWidget: (draggingWidget) => {
|
||||
editorStore.update((store) => ({ ...store, draggingWidget, updatedSortable: true }));
|
||||
},
|
||||
setActive: (widget) => {
|
||||
editorStore.update((store) => ({ ...store, widget }));
|
||||
},
|
||||
setPreview(preview) {
|
||||
editorStore.update((store) => ({ ...store, widgetPreview: preview }));
|
||||
},
|
||||
editWidget: (widget) => {
|
||||
editorStore.update((store) => {
|
||||
const edits = store.edits;
|
||||
|
||||
if (widget.id.toString().startsWith('new+')) {
|
||||
const index = edits.edits.createWidgets.findIndex((edit) => edit.widgetId === widget.id);
|
||||
|
||||
if (index !== -1) {
|
||||
edits.edits.createWidgets[index] = {
|
||||
...edits.edits.createWidgets[index],
|
||||
...widget,
|
||||
align: edits.edits.createWidgets[index].align,
|
||||
};
|
||||
} else {
|
||||
edits.edits.createWidgets.push({
|
||||
widgetId: widget.id,
|
||||
type: widget.type,
|
||||
visible: widget.visible,
|
||||
align: 2,
|
||||
index: -1,
|
||||
data: widget.data,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const index = edits.edits.updateWidgets.findIndex((edit) => edit.widgetId === widget.id);
|
||||
if (index !== -1) {
|
||||
edits.edits.updateWidgets[index] = { ...edits.edits.updateWidgets[index], ...widget };
|
||||
} else {
|
||||
edits.edits.updateWidgets.push({
|
||||
widgetId: widget.id,
|
||||
align: 2,
|
||||
data: widget.data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!store.widgetPreview || !store.widget) return { ...store };
|
||||
|
||||
const previews = store.previews;
|
||||
previews[store.widget.id] = store.widgetPreview;
|
||||
|
||||
return { ...store };
|
||||
});
|
||||
},
|
||||
deleteWidget: (id) => {
|
||||
editorStore.update((store) => {
|
||||
const edits = store.edits;
|
||||
|
||||
if (!id.toString().startsWith('new+') && typeof id === 'number') edits.edits.deleteWidgets.push({ widgetId: id });
|
||||
|
||||
return {
|
||||
...store,
|
||||
edits: {
|
||||
...edits,
|
||||
edits: {
|
||||
...edits.edits,
|
||||
createWidgets: edits.edits.createWidgets.filter(function (edit) {
|
||||
return edit.widgetId !== id;
|
||||
}),
|
||||
updateWidgets: edits.edits.updateWidgets.filter(function (edit) {
|
||||
return edit.widgetId !== id;
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
applyIndex: () => {
|
||||
editorStore.update((store) => {
|
||||
if (!store.sortables?.left || !store.sortables?.right) return store;
|
||||
|
||||
const sortables = {
|
||||
left: store.sortables.left.toArray(),
|
||||
right: store.sortables.right.toArray(),
|
||||
};
|
||||
|
||||
const map = (id: string, index: number) => {
|
||||
if (id.toString().startsWith('new+')) {
|
||||
const edits = store.edits;
|
||||
const createIndex = edits.edits.createWidgets.findIndex((edit) => edit.widgetId === id);
|
||||
if (createIndex !== -1) {
|
||||
const align = sortables.right.findIndex((sortableId) => sortableId === id) !== -1 ? 2 : 0;
|
||||
edits.edits.createWidgets[createIndex] = { ...edits.edits.createWidgets[createIndex], index, align };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
widgetId: Number.parseInt(id),
|
||||
index,
|
||||
} as IndexWidget;
|
||||
};
|
||||
|
||||
const sorted = {
|
||||
left: sortables.left.map(map).filter(Boolean) as IndexWidget[],
|
||||
right: sortables.right.map(map).filter(Boolean) as IndexWidget[],
|
||||
};
|
||||
|
||||
const aligned = {
|
||||
left: sorted.left.map((widget) => ({ ...widget, align: 0 } as AlignWidget)) as AlignWidget[],
|
||||
right: sorted.right.map((widget) => ({ ...widget, align: 2 } as AlignWidget)) as AlignWidget[],
|
||||
};
|
||||
|
||||
return {
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
indexWidgets: [...sorted.left, ...sorted.right],
|
||||
alignWidgets: [...aligned.left, ...aligned.right],
|
||||
},
|
||||
} as EditorPublish,
|
||||
};
|
||||
});
|
||||
},
|
||||
setSortables: (left, right) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
sortables: { left: left ? left : store.sortables?.left, right: right ? right : store.sortables?.right },
|
||||
}));
|
||||
},
|
||||
setDisplayName: (displayName) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateDisplayName: { newDisplayName: displayName },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setUsername: (username) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateUsername: { newUsername: username },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setDescription: (description) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateDescription: { newDescription: description },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setLocation: (location) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateLocation: { newLocation: location },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setSchool: (school) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateSchool: { newSchool: school },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setWorkplace: (workplace) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
updateWorkplace: { newWorkplace: workplace },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
setAvatar: (file) => {
|
||||
const url = URL.createObjectURL(file);
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
avatar: url,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
deleteAvatar: null,
|
||||
},
|
||||
avatar: file,
|
||||
},
|
||||
}));
|
||||
},
|
||||
deleteAvatar: () => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
avatar: null,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
deleteAvatar: {},
|
||||
},
|
||||
avatar: null,
|
||||
},
|
||||
}));
|
||||
},
|
||||
setBanner: (file) => {
|
||||
const url = URL.createObjectURL(file);
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
banner: url,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
deleteBanner: null,
|
||||
},
|
||||
banner: file,
|
||||
},
|
||||
}));
|
||||
},
|
||||
deleteBanner: () => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
banner: null,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
deleteBanner: {},
|
||||
},
|
||||
banner: null,
|
||||
},
|
||||
}));
|
||||
},
|
||||
setSocials: (
|
||||
createSocialLinks,
|
||||
createSocialTexts,
|
||||
indexSocialLinks,
|
||||
indexSocialTexts,
|
||||
deleteSocialLinks,
|
||||
deleteSocialTexts,
|
||||
) => {
|
||||
editorStore.update((store) => {
|
||||
return {
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
createSocialLinks: createSocialLinks
|
||||
.filter((x) => x.type != 'UNKNOWN' && x.value)
|
||||
.map(
|
||||
(x) =>
|
||||
({
|
||||
id: x.id,
|
||||
index: x.index,
|
||||
type: Object.values(SocialLink).indexOf(x.type),
|
||||
value: x.value,
|
||||
} as CreateSocialLink),
|
||||
),
|
||||
createSocialTexts: createSocialTexts
|
||||
.filter((x) => x.value)
|
||||
.map((x) => ({ id: x.id, index: x.index, title: x.title, value: x.value })),
|
||||
indexSocialLinks,
|
||||
indexSocialTexts,
|
||||
deleteSocialLinks: deleteSocialLinks.map((x) => ({ id: x })),
|
||||
deleteSocialTexts: deleteSocialTexts.map((x) => ({ id: x })),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
toggleUid: (visible) => {
|
||||
editorStore.update((store) => ({
|
||||
...store,
|
||||
edits: {
|
||||
...store.edits,
|
||||
edits: {
|
||||
...store.edits.edits,
|
||||
toggleUid: { visible },
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
reset: () => {
|
||||
editorStore.update((store) => {
|
||||
return {
|
||||
...store,
|
||||
...generateResetState(),
|
||||
};
|
||||
});
|
||||
},
|
||||
} as EditorStore);
|
||||
|
||||
export const hasEdits = (edits: EditorStore['edits']) => {
|
||||
return (
|
||||
[
|
||||
...edits.edits.createWidgets,
|
||||
...edits.edits.updateWidgets,
|
||||
...edits.edits.deleteWidgets,
|
||||
...edits.edits.indexWidgets,
|
||||
...edits.edits.alignWidgets,
|
||||
...edits.edits.imageWidgets,
|
||||
...edits.edits.createSocialTexts,
|
||||
...edits.edits.indexSocialTexts,
|
||||
...edits.edits.deleteSocialTexts,
|
||||
...edits.edits.createSocialLinks,
|
||||
...edits.edits.indexSocialLinks,
|
||||
...edits.edits.deleteSocialLinks,
|
||||
].length !== 0 ||
|
||||
edits.edits.deleteAvatar ||
|
||||
edits.edits.deleteBanner ||
|
||||
edits.edits.updateDescription ||
|
||||
edits.edits.updateDisplayName ||
|
||||
edits.edits.updateLocation ||
|
||||
edits.edits.updateUsername ||
|
||||
edits.edits.updateSchool ||
|
||||
edits.edits.updateWorkplace ||
|
||||
edits.edits.toggleUid ||
|
||||
edits.avatar ||
|
||||
edits.banner
|
||||
);
|
||||
};
|
39
lib/stores/modal.ts
Normal file
39
lib/stores/modal.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { browser } from '$app/environment';
|
||||
import Modal from '$lib/models/modal';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
interface ModalStore {
|
||||
visible: boolean;
|
||||
type?: Modal | null;
|
||||
data?: any;
|
||||
warn?: boolean | null;
|
||||
showModal: (type: Modal, data?: any) => void;
|
||||
hideModal: (noConfirm?: boolean | null) => void;
|
||||
disableWarn: () => void;
|
||||
}
|
||||
|
||||
export const modalStore = browser
|
||||
? writable({
|
||||
visible: false,
|
||||
type: null,
|
||||
data: null,
|
||||
warn: null,
|
||||
showModal: (type: Modal, data?: any) => {
|
||||
modalStore?.update((store) => ({ ...store, type, data, visible: true, warn: true }));
|
||||
},
|
||||
hideModal: (noConfirm) => {
|
||||
modalStore?.update((store) => {
|
||||
if (!noConfirm && store.type === Modal.EditWidget && store.warn) {
|
||||
toast.push('Click again to dismiss.');
|
||||
return { ...store, warn: false };
|
||||
}
|
||||
return { ...store, type: null, data: null, visible: false, warn: false };
|
||||
});
|
||||
},
|
||||
disableWarn: () => {
|
||||
modalStore?.update((store) => ({ ...store, warn: false }));
|
||||
},
|
||||
} as ModalStore)
|
||||
: null;
|
Loading…
Add table
Add a link
Reference in a new issue