2024-06-07 20:17:03 +03:00
|
|
|
'use client';
|
|
|
|
|
2025-03-05 00:09:00 +03:00
|
|
|
import { createContext, use, useEffect, useState } from 'react';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-02-10 01:32:16 +03:00
|
|
|
import { urls, useConceptNavigation } from '@/app';
|
2025-02-12 13:41:58 +03:00
|
|
|
import { useAuthSuspense } from '@/features/auth';
|
2025-02-26 00:16:22 +03:00
|
|
|
import { useLibrarySearchStore } from '@/features/library';
|
|
|
|
import { useDeleteItem } from '@/features/library/backend/useDeleteItem';
|
2025-02-10 01:32:16 +03:00
|
|
|
import { RSTabID } from '@/features/rsform/pages/RSFormPage/RSEditContext';
|
2025-02-12 15:12:59 +03:00
|
|
|
import { useRoleStore, UserRole } from '@/features/users';
|
2025-02-12 21:36:03 +03:00
|
|
|
|
2025-01-14 21:57:32 +03:00
|
|
|
import { usePreferencesStore } from '@/stores/preferences';
|
2025-02-12 01:34:35 +03:00
|
|
|
import { promptText } from '@/utils/labels';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-02-20 20:22:05 +03:00
|
|
|
import { type IOperationPosition, OperationType } from '../../backend/types';
|
2025-02-10 01:32:16 +03:00
|
|
|
import { useOssSuspense } from '../../backend/useOSS';
|
2025-02-26 12:54:51 +03:00
|
|
|
import { type IOperation, type IOperationSchema } from '../../models/oss';
|
2025-02-10 01:32:16 +03:00
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
export enum OssTabID {
|
|
|
|
CARD = 0,
|
|
|
|
GRAPH = 1
|
|
|
|
}
|
2024-08-19 19:53:51 +03:00
|
|
|
|
2024-08-02 11:17:27 +03:00
|
|
|
export interface ICreateOperationPrompt {
|
2024-09-16 19:38:24 +03:00
|
|
|
defaultX: number;
|
|
|
|
defaultY: number;
|
2025-02-17 15:11:32 +03:00
|
|
|
inputs: number[];
|
2024-08-02 11:17:27 +03:00
|
|
|
positions: IOperationPosition[];
|
2025-02-17 15:11:32 +03:00
|
|
|
callback: (newID: number) => void;
|
2024-08-02 11:17:27 +03:00
|
|
|
}
|
|
|
|
|
2025-02-20 14:45:12 +03:00
|
|
|
export interface IOssEditContext {
|
2025-01-26 22:24:34 +03:00
|
|
|
schema: IOperationSchema;
|
2025-02-17 15:11:32 +03:00
|
|
|
selected: number[];
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-01-23 19:41:31 +03:00
|
|
|
isOwned: boolean;
|
2024-06-07 20:17:03 +03:00
|
|
|
isMutable: boolean;
|
2024-07-26 00:33:22 +03:00
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
navigateTab: (tab: OssTabID) => void;
|
2025-02-17 15:11:32 +03:00
|
|
|
navigateOperationSchema: (target: number) => void;
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-02-26 12:54:51 +03:00
|
|
|
canDeleteOperation: (target: IOperation) => boolean;
|
2025-01-26 22:24:34 +03:00
|
|
|
deleteSchema: () => void;
|
2025-02-17 15:11:32 +03:00
|
|
|
setSelected: React.Dispatch<React.SetStateAction<number[]>>;
|
2024-06-07 20:17:03 +03:00
|
|
|
}
|
|
|
|
|
2025-03-05 00:09:00 +03:00
|
|
|
export const OssEditContext = createContext<IOssEditContext | null>(null);
|
2024-06-07 20:17:03 +03:00
|
|
|
export const useOssEdit = () => {
|
2025-03-05 00:09:00 +03:00
|
|
|
const context = use(OssEditContext);
|
2024-06-07 20:17:03 +03:00
|
|
|
if (context === null) {
|
2024-12-12 21:58:07 +03:00
|
|
|
throw new Error('useOssEdit has to be used within <OssEditState>');
|
2024-06-07 20:17:03 +03:00
|
|
|
}
|
|
|
|
return context;
|
|
|
|
};
|
|
|
|
|
|
|
|
interface OssEditStateProps {
|
2025-02-12 15:12:59 +03:00
|
|
|
itemID: number;
|
2024-06-07 20:17:03 +03:00
|
|
|
}
|
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEditStateProps>) => {
|
2024-07-24 18:11:28 +03:00
|
|
|
const router = useConceptNavigation();
|
2025-01-14 21:57:32 +03:00
|
|
|
const adminMode = usePreferencesStore(state => state.adminMode);
|
2025-01-15 23:03:23 +03:00
|
|
|
|
|
|
|
const role = useRoleStore(state => state.role);
|
|
|
|
const adjustRole = useRoleStore(state => state.adjustRole);
|
2025-02-04 23:54:24 +03:00
|
|
|
const setSearchLocation = useLibrarySearchStore(state => state.setLocation);
|
|
|
|
const searchLocation = useLibrarySearchStore(state => state.location);
|
2025-01-28 19:45:31 +03:00
|
|
|
|
|
|
|
const { user } = useAuthSuspense();
|
2025-01-26 22:24:34 +03:00
|
|
|
const { schema } = useOssSuspense({ itemID: itemID });
|
2025-01-23 19:41:31 +03:00
|
|
|
|
2025-01-28 19:45:31 +03:00
|
|
|
const isOwned = !!user.id && user.id === schema.owner;
|
2025-01-26 22:24:34 +03:00
|
|
|
const isMutable = role > UserRole.READER && !schema.read_only;
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-02-17 15:11:32 +03:00
|
|
|
const [selected, setSelected] = useState<number[]>([]);
|
2024-08-02 11:17:27 +03:00
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
const { deleteItem } = useDeleteItem();
|
2024-07-20 18:26:32 +03:00
|
|
|
|
2024-12-12 20:57:45 +03:00
|
|
|
useEffect(
|
2024-06-07 20:17:03 +03:00
|
|
|
() =>
|
2025-01-15 23:03:23 +03:00
|
|
|
adjustRole({
|
2025-01-26 22:24:34 +03:00
|
|
|
isOwner: isOwned,
|
2025-01-28 19:45:31 +03:00
|
|
|
isEditor: !!user.id && schema.editors.includes(user.id),
|
|
|
|
isStaff: user.is_staff,
|
2025-01-15 23:03:23 +03:00
|
|
|
adminMode: adminMode
|
2024-06-07 20:17:03 +03:00
|
|
|
}),
|
2025-01-26 22:24:34 +03:00
|
|
|
[schema, adjustRole, isOwned, user, adminMode]
|
2024-06-07 20:17:03 +03:00
|
|
|
);
|
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
function navigateTab(tab: OssTabID) {
|
|
|
|
const url = urls.oss_props({
|
|
|
|
id: schema.id,
|
|
|
|
tab: tab
|
|
|
|
});
|
2025-02-26 16:28:16 +03:00
|
|
|
router.push({ path: url });
|
2025-01-26 22:24:34 +03:00
|
|
|
}
|
2024-06-07 20:17:03 +03:00
|
|
|
|
2025-02-17 15:11:32 +03:00
|
|
|
function navigateOperationSchema(target: number) {
|
2025-01-27 15:02:00 +03:00
|
|
|
const node = schema.operationByID.get(target);
|
|
|
|
if (!node?.result) {
|
|
|
|
return;
|
|
|
|
}
|
2025-02-26 16:28:16 +03:00
|
|
|
router.push({ path: urls.schema_props({ id: node.result, tab: RSTabID.CST_LIST }) });
|
2025-01-27 15:02:00 +03:00
|
|
|
}
|
2024-07-24 18:11:28 +03:00
|
|
|
|
2025-01-26 22:24:34 +03:00
|
|
|
function deleteSchema() {
|
2025-02-12 01:34:35 +03:00
|
|
|
if (!window.confirm(promptText.deleteOSS)) {
|
2025-01-26 22:24:34 +03:00
|
|
|
return;
|
|
|
|
}
|
2025-02-26 16:28:16 +03:00
|
|
|
void deleteItem({
|
|
|
|
target: schema.id,
|
|
|
|
beforeInvalidate: () => {
|
|
|
|
if (searchLocation === schema.location) {
|
|
|
|
setSearchLocation('');
|
|
|
|
}
|
|
|
|
return router.pushAsync({ path: urls.library, force: true });
|
2025-02-04 23:54:24 +03:00
|
|
|
}
|
|
|
|
});
|
2025-01-26 22:24:34 +03:00
|
|
|
}
|
|
|
|
|
2025-02-26 12:54:51 +03:00
|
|
|
function canDeleteOperation(target: IOperation) {
|
|
|
|
if (target.operation_type === OperationType.INPUT) {
|
2025-01-26 22:24:34 +03:00
|
|
|
return true;
|
|
|
|
}
|
2025-02-26 12:54:51 +03:00
|
|
|
return schema.graph.expandOutputs([target.id]).length === 0;
|
2025-01-26 22:24:34 +03:00
|
|
|
}
|
2025-01-16 16:31:03 +03:00
|
|
|
|
2024-06-07 20:17:03 +03:00
|
|
|
return (
|
2024-12-12 21:58:07 +03:00
|
|
|
<OssEditContext
|
2024-06-07 20:17:03 +03:00
|
|
|
value={{
|
2025-01-26 22:24:34 +03:00
|
|
|
schema,
|
2024-07-23 23:03:58 +03:00
|
|
|
selected,
|
|
|
|
|
2025-01-23 19:41:31 +03:00
|
|
|
isOwned,
|
2024-06-07 20:17:03 +03:00
|
|
|
isMutable,
|
|
|
|
|
2025-02-26 12:54:51 +03:00
|
|
|
navigateTab,
|
2025-01-26 22:24:34 +03:00
|
|
|
navigateOperationSchema,
|
2025-02-26 12:54:51 +03:00
|
|
|
|
|
|
|
canDeleteOperation,
|
|
|
|
deleteSchema,
|
|
|
|
setSelected
|
2024-06-07 20:17:03 +03:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{children}
|
2024-12-12 21:58:07 +03:00
|
|
|
</OssEditContext>
|
2024-06-07 20:17:03 +03:00
|
|
|
);
|
|
|
|
};
|