diff --git a/rsconcept/frontend/src/components/RSInput/tooltip.ts b/rsconcept/frontend/src/components/RSInput/tooltip.ts index 3514aefb..abe1e069 100644 --- a/rsconcept/frontend/src/components/RSInput/tooltip.ts +++ b/rsconcept/frontend/src/components/RSInput/tooltip.ts @@ -42,7 +42,7 @@ export const getHoverTooltip = (items: IConstituenta[]) => { start--; while (end < to && /\w/.test(text[end - from])) end++; - if (start == pos && side < 0 || end == pos && side > 0) { + if (start === pos && side < 0 || end === pos && side > 0) { return null; } const alias = text.slice(start - from, end - from); diff --git a/rsconcept/frontend/src/context/LibraryContext.tsx b/rsconcept/frontend/src/context/LibraryContext.tsx index e19c78b1..96dc7c49 100644 --- a/rsconcept/frontend/src/context/LibraryContext.tsx +++ b/rsconcept/frontend/src/context/LibraryContext.tsx @@ -14,14 +14,14 @@ interface ILibraryContext { filter: (params: ILibraryFilter) => IRSFormMeta[] createSchema: (data: IRSFormCreateData, callback?: DataCallback) => void - cloneSchema: (target:number, data: IRSFormCreateData, callback: DataCallback) => void - destroySchema: (target: number, callback?: () => void) => void + cloneSchema: (target: string, data: IRSFormCreateData, callback: DataCallback) => void + destroySchema: (target: string, callback?: () => void) => void } const LibraryContext = createContext(null) export const useLibrary = (): ILibraryContext => { const context = useContext(LibraryContext); - if (context == null) { + if (context === null) { throw new Error( 'useLibrary has to be used within ' ); @@ -90,9 +90,9 @@ export const LibraryState = ({ children }: LibraryStateProps) => { }, [reload]); const destroySchema = useCallback( - (target: number, callback?: () => void) => { + (target: string, callback?: () => void) => { setError(undefined) - deleteRSForm(String(target), { + deleteRSForm(target, { showError: true, setLoading: setProcessing, onError: error => setError(error), @@ -103,12 +103,12 @@ export const LibraryState = ({ children }: LibraryStateProps) => { }, [setError, reload]); const cloneSchema = useCallback( - (target: number, data: IRSFormCreateData, callback: DataCallback) => { + (target: string, data: IRSFormCreateData, callback: DataCallback) => { if (!user) { return; } setError(undefined) - postCloneRSForm(String(target), { + postCloneRSForm(target, { data: data, showError: true, setLoading: setProcessing, diff --git a/rsconcept/frontend/src/context/RSFormContext.tsx b/rsconcept/frontend/src/context/RSFormContext.tsx index 2d519cd1..07d934b9 100644 --- a/rsconcept/frontend/src/context/RSFormContext.tsx +++ b/rsconcept/frontend/src/context/RSFormContext.tsx @@ -50,7 +50,7 @@ interface IRSFormContext { const RSFormContext = createContext(null) export const useRSForm = () => { const context = useContext(RSFormContext) - if (context == null) { + if (context === null) { throw new Error( 'useRSForm has to be used within ' ) @@ -205,7 +205,7 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => { const cstUpdate = useCallback( (data: ICstUpdateData, callback?: DataCallback) => { setError(undefined) - patchConstituenta(String(data.id), { + patchConstituenta(data.id, { data: data, showError: true, setLoading: setProcessing, diff --git a/rsconcept/frontend/src/context/UsersContext.tsx b/rsconcept/frontend/src/context/UsersContext.tsx index f14c817e..93800892 100644 --- a/rsconcept/frontend/src/context/UsersContext.tsx +++ b/rsconcept/frontend/src/context/UsersContext.tsx @@ -12,7 +12,7 @@ interface IUsersContext { const UsersContext = createContext(null) export const useUsers = (): IUsersContext => { const context = useContext(UsersContext); - if (context == null) { + if (context === null) { throw new Error( 'useUsers has to be used within ' ); diff --git a/rsconcept/frontend/src/hooks/useCheckExpression.ts b/rsconcept/frontend/src/hooks/useCheckExpression.ts index 82f524b7..66cbb3b1 100644 --- a/rsconcept/frontend/src/hooks/useCheckExpression.ts +++ b/rsconcept/frontend/src/hooks/useCheckExpression.ts @@ -13,7 +13,7 @@ function useCheckExpression({ schema }: { schema?: IRSForm }) { function checkExpression(expression: string, onSuccess?: DataCallback) { setError(undefined); - postCheckExpression(String(schema?.id), { + postCheckExpression(schema!.id, { data: { expression: expression }, showError: true, setLoading, diff --git a/rsconcept/frontend/src/pages/RSFormPage/DlgDeleteCst.tsx b/rsconcept/frontend/src/pages/RSFormPage/DlgDeleteCst.tsx index e04144f1..b9da09df 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/DlgDeleteCst.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/DlgDeleteCst.tsx @@ -7,15 +7,15 @@ import { getCstLabel } from '../../utils/staticUI'; interface DlgDeleteCstProps { hideWindow: () => void - selected: number[] - onDelete: (items: number[]) => void + selected: string[] + onDelete: (items: string[]) => void } function DlgDeleteCst({ hideWindow, selected, onDelete }: DlgDeleteCstProps) { const { schema } = useRSForm(); const [ expandOut, setExpandOut ] = useState(false); - const expansion: number[] = useMemo(() => schema?.graph.expandOutputs(selected) ?? [], [selected, schema?.graph]); + const expansion: string[] = useMemo(() => schema?.graph.expandOutputs(selected) ?? [], [selected, schema?.graph]); function handleSubmit() { hideWindow(); diff --git a/rsconcept/frontend/src/pages/RSFormPage/DlgShowAST.tsx b/rsconcept/frontend/src/pages/RSFormPage/DlgShowAST.tsx index 0823b73f..496b1ede 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/DlgShowAST.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/DlgShowAST.tsx @@ -28,7 +28,7 @@ function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) { () => { const result: GraphEdge[] = []; syntaxTree.forEach(node => { - if (node.parent != node.uid) { + if (node.parent !== node.uid) { result.push({ id: String(node.uid), source: String(node.parent), diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx index 5f4468b7..d49d7899 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta.tsx @@ -18,11 +18,11 @@ import ViewSideConstituents from './elements/ViewSideConstituents'; const UNFOLDED_HEIGHT = '59.1rem'; interface EditorConstituentaProps { - activeID?: number - onOpenEdit: (cstID: number) => void + activeID?: string + onOpenEdit: (cstID: string) => void onShowAST: (expression: string, ast: SyntaxTree) => void onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void - onDeleteCst: (selected: number[], callback?: (items: number[]) => void) => void + onDeleteCst: (selected: string[], callback?: (items: string[]) => void) => void } function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDeleteCst }: EditorConstituentaProps) { diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx index 3cd7a411..afa4d4ed 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorItems.tsx @@ -14,15 +14,15 @@ import { CstType, IConstituenta, ICstCreateData, ICstMovetoData } from '../../ut import { getCstTypePrefix, getCstTypeShortcut, getCstTypificationLabel, mapStatusInfo } from '../../utils/staticUI'; interface EditorItemsProps { - onOpenEdit: (cstID: number) => void + onOpenEdit: (cstID: string) => void onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void - onDeleteCst: (selected: number[], callback: (items: number[]) => void) => void + onDeleteCst: (selected: string[], callback: (items: string[]) => void) => void } function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps) { const { schema, isEditable, cstMoveTo, resetAliases } = useRSForm(); const { noNavigation } = useConceptTheme(); - const [selected, setSelected] = useState([]); + const [selected, setSelected] = useState([]); const nothingSelected = useMemo(() => selected.length === 0, [selected]); const [toggledClearRows, setToggledClearRows] = useState(false); diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx index 76f467e9..0f2790c4 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression.tsx @@ -184,7 +184,7 @@ function EditorRSExpression({ }, [handleEdit]); return ( -
+
void + onOpenEdit: (cstID: string) => void onCreateCst: (initial: ICstCreateData, skipDialog?: boolean) => void - onDeleteCst: (selected: number[], callback: (items: number[]) => void) => void + onDeleteCst: (selected: string[], callback: (items: string[]) => void) => void } function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGraphProps) { @@ -83,8 +83,8 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra const [ allowTheorem, setAllowTheorem ] = useLocalStorage('graph_allow_theorem', true); const [ filtered, setFiltered ] = useState(new Graph()); - const [ dismissed, setDismissed ] = useState([]); - const [ selectedDismissed, setSelectedDismissed ] = useState([]); + const [ dismissed, setDismissed ] = useState([]); + const [ selectedDismissed, setSelectedDismissed ] = useState([]); const graphRef = useRef(null); const [showOptions, setShowOptions] = useState(false); const [toggleUpdate, setToggleUpdate] = useState(false); @@ -92,7 +92,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra const [hoverID, setHoverID] = useState(undefined); const hoverCst = useMemo( () => { - return schema?.items.find(cst => String(cst.id) == hoverID); + return schema?.items.find(cst => String(cst.id) === hoverID); }, [schema?.items, hoverID]); const is3D = useMemo(() => layout.includes('3d'), [layout]); @@ -137,7 +137,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra } }); } - const newDismissed: number[] = []; + const newDismissed: string[] = []; schema.items.forEach(cst => { if (!graph.nodes.has(cst.id)) { newDismissed.push(cst.id); @@ -149,9 +149,9 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra setHoverID(undefined); }, [schema, noHermits, noTransitive, noTemplates, allowedTypes, toggleUpdate]); - function toggleDismissed(cstID: number) { + function toggleDismissed(cstID: string) { setSelectedDismissed(prev => { - const index = prev.findIndex(id => cstID == id); + const index = prev.findIndex(id => cstID === id); if (index !== -1) { prev.splice(index, 1); } else { @@ -171,12 +171,13 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra const cst = schema.items.find(cst => cst.id === node.id); if (cst) { result.push({ - id: String(node.id), + id: node.id, fill: getCstNodeColor(cst, coloringScheme, darkMode), label: cst.term.resolved && !noTerms ? `${cst.alias}: ${cst.term.resolved}` : cst.alias }); } }); + console.log(result); return result; }, [schema, coloringScheme, filtered.nodes, darkMode, noTerms]); @@ -188,12 +189,13 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra source.outputs.forEach(target => { result.push({ id: String(edgeID), - source: String(source.id), - target: String(target) + source: source.id, + target: target }); edgeID += 1; }); }); + console.log(result); return result; }, [filtered.nodes]); @@ -216,7 +218,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra const allSelected: string[] = useMemo( () => { - return [ ... selectedDismissed.map(id => String(id)), ... selections]; + return [ ... selectedDismissed, ... selections]; }, [selectedDismissed, selections]); const nothingSelected = useMemo(() => allSelected.length === 0, [allSelected]); @@ -241,7 +243,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra const handleNodeClick = useCallback( (node: GraphNode) => { if (selections.includes(node.id)) { - onOpenEdit(Number(node.id)); + onOpenEdit(node.id); return; } if (onNodeClick) onNodeClick(node); @@ -272,10 +274,10 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra } const data: ICstCreateData = { insert_after: null, - cst_type: allSelected.length == 0 ? CstType.BASE: CstType.TERM, + cst_type: allSelected.length === 0 ? CstType.BASE: CstType.TERM, alias: '', term_raw: '', - definition_formal: allSelected.map(id => schema.items.find(cst => cst.id === Number(id))!.alias).join(' '), + definition_formal: allSelected.map(id => schema.items.find(cst => cst.id === id)!.alias).join(' '), definition_raw: '', convention: '', }; @@ -286,7 +288,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra if (!schema) { return; } - onDeleteCst([... allSelected.map(id => Number(id))], () => { + onDeleteCst(allSelected, () => { clearSelections(); setDismissed([]); setSelectedDismissed([]); @@ -344,7 +346,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra }, [noNavigation]); const dismissedStyle = useCallback( - (cstID: number) => { + (cstID: string) => { return selectedDismissed.includes(cstID) ? {outlineWidth: '2px', outlineStyle: 'solid'}: {}; }, [selectedDismissed]); diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx index 7a004adf..11f48670 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx @@ -40,7 +40,7 @@ function RSTabs() { const { destroySchema } = useLibrary(); const [activeTab, setActiveTab] = useState(RSTabsList.CARD); - const [activeID, setActiveID] = useState(undefined); + const [activeID, setActiveID] = useState(undefined); const [showUpload, setShowUpload] = useState(false); const [showClone, setShowClone] = useState(false); @@ -49,8 +49,8 @@ function RSTabs() { const [expression, setExpression] = useState(''); const [showAST, setShowAST] = useState(false); - const [afterDelete, setAfterDelete] = useState<((items: number[]) => void) | undefined>(undefined); - const [toBeDeleted, setToBeDeleted] = useState([]); + const [afterDelete, setAfterDelete] = useState<((items: string[]) => void) | undefined>(undefined); + const [toBeDeleted, setToBeDeleted] = useState([]); const [showDeleteCst, setShowDeleteCst] = useState(false); const [createInitialData, setCreateInitialData] = useState(); @@ -70,7 +70,7 @@ function RSTabs() { const activeTab = Number(new URLSearchParams(search).get('tab')) ?? RSTabsList.CARD; const cstQuery = new URLSearchParams(search).get('active'); setActiveTab(activeTab); - setActiveID(Number(cstQuery) ?? (schema && schema?.items.length > 0 && schema?.items[0])); + setActiveID(cstQuery ?? ((schema && schema?.items.length > 0) ? schema.items[0].id : undefined)) }, [search, setActiveTab, setActiveID, schema]); function onSelectTab(index: number) { @@ -78,7 +78,7 @@ function RSTabs() { } const navigateTo = useCallback( - (tab: RSTabsList, activeID?: number) => { + (tab: RSTabsList, activeID?: string) => { if (activeID) { navigate(`/rsforms/${schema!.id}?tab=${tab}&active=${activeID}`, { replace: tab === activeTab && tab !== RSTabsList.CST_EDIT @@ -97,7 +97,7 @@ function RSTabs() { cstCreate(data, newCst => { toast.success(`Конституента добавлена: ${newCst.alias}`); navigateTo(activeTab, newCst.id); - if (activeTab === RSTabsList.CST_EDIT || activeTab == RSTabsList.CST_LIST) { + if (activeTab === RSTabsList.CST_EDIT || activeTab === RSTabsList.CST_LIST) { setTimeout(() => { const element = document.getElementById(`${prefixes.cst_list}${newCst.alias}`); if (element) { @@ -123,7 +123,7 @@ function RSTabs() { }, [handleCreateCst]); const handleDeleteCst = useCallback( - (deleted: number[]) => { + (deleted: string[]) => { if (!schema) { return; } @@ -148,9 +148,9 @@ function RSTabs() { }, [afterDelete, cstDelete, schema, activeID, activeTab, navigateTo]); const promptDeleteCst = useCallback( - (selected: number[], callback?: (items: number[]) => void) => { + (selected: string[], callback?: (items: string[]) => void) => { setAfterDelete(() => ( - (items: number[]) => { + (items: string[]) => { if (callback) callback(items); })); setToBeDeleted(selected); @@ -165,7 +165,7 @@ function RSTabs() { }, []); const onOpenCst = useCallback( - (cstID: number) => { + (cstID: string) => { navigateTo(RSTabsList.CST_EDIT, cstID) }, [navigateTo]); @@ -217,19 +217,19 @@ function RSTabs() { defaultFocus={true} selectedTabClassName='font-bold' > - + setShowClone(true)} showUploadDialog={() => setShowUpload(true)} /> - Паспорт схемы + Паспорт схемы Конституенты {`${schema.stats?.count_errors ?? 0} | ${schema.stats?.count_all ?? 0}`} - Редактор - Граф термов + Редактор + Граф термов diff --git a/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx b/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx index c015cd96..2951b95e 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/elements/ViewSideConstituents.tsx @@ -17,8 +17,12 @@ const LOCAL_NAVIGATION_H = '2.6rem'; interface ViewSideConstituentsProps { expression: string baseHeight: string - activeID?: number - onOpenEdit: (cstID: number) => void + activeID?: string + onOpenEdit: (cstID: string) => void +} + +function isMockCst(cst: IConstituenta) { + return cst.id[0] === '-' } function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: ViewSideConstituentsProps) { @@ -45,7 +49,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: const diff = Array.from(aliases).filter(name => !names.includes(name)); if (diff.length > 0) { diff.forEach( - (alias, index) => filtered.push(getMockConstituenta(-index, alias, CstType.BASE, 'Конституента отсутствует'))); + (alias, index) => filtered.push(getMockConstituenta(`-${index}`, alias, CstType.BASE, 'Конституента отсутствует'))); } } else if (!activeID) { filtered = schema.items @@ -60,14 +64,14 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: const handleRowClicked = useCallback( (cst: IConstituenta, event: React.MouseEvent) => { - if (event.altKey && cst.id > 0) { + if (event.altKey && !isMockCst(cst)) { onOpenEdit(cst.id); } }, [onOpenEdit]); const handleDoubleClick = useCallback( (cst: IConstituenta) => { - if (cst.id > 0) { + if (!isMockCst(cst)) { onOpenEdit(cst.id); } }, [onOpenEdit]); @@ -108,7 +112,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: maxWidth: '65px', conditionalCellStyles: [ { - when: (cst: IConstituenta) => cst.id <= 0, + when: (cst: IConstituenta) => isMockCst(cst), classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] } ] @@ -121,7 +125,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: wrap: true, conditionalCellStyles: [ { - when: (cst: IConstituenta) => cst.id <= 0, + when: (cst: IConstituenta) => isMockCst(cst), classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] } ] @@ -136,7 +140,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: wrap: true, conditionalCellStyles: [ { - when: (cst: IConstituenta) => cst.id <= 0, + when: (cst: IConstituenta) => isMockCst(cst), classNames: ['bg-[#ffc9c9]', 'dark:bg-[#592b2b]'] } ] diff --git a/rsconcept/frontend/src/pages/RegisterPage.tsx b/rsconcept/frontend/src/pages/RegisterPage.tsx index 9603853e..7362b39d 100644 --- a/rsconcept/frontend/src/pages/RegisterPage.tsx +++ b/rsconcept/frontend/src/pages/RegisterPage.tsx @@ -64,9 +64,12 @@ function RegisterPage() { onChange={event => { setPassword2(event.target.value); }} />
-

- минимум 8 символов

+

- используйте уникальный пароль

+

- портал функционирует в тестовом режиме

+

- безопасность информации пользователей не гарантируется

+ {/*

- минимум 8 символов

- большие, маленькие буквы, цифры

-

- минимум 1 спец. символ

+

- минимум 1 спец. символ

*/}
{ test('adding edges should create nodes', () => { const graph = new Graph(); - graph.addEdge(13, 37); - expect([... graph.nodes.keys()]).toStrictEqual([13, 37]); + graph.addEdge('13', '37'); + expect([... graph.nodes.keys()]).toStrictEqual(['13', '37']); - graph.addEdge(13, 38); - expect([... graph.nodes.keys()]).toStrictEqual([13, 37, 38]); + graph.addEdge('13', '38'); + expect([... graph.nodes.keys()]).toStrictEqual(['13', '37', '38']); }); test('creating from array', () => { - const graph = new Graph([[1, 2], [3], [4, 1]]); - expect([... graph.nodes.keys()]).toStrictEqual([1, 2, 3, 4]); - expect([... graph.nodes.get(1)!.outputs]).toStrictEqual([2]); + const graph = new Graph([['1', '2'], ['3'], ['4', '1']]); + expect([... graph.nodes.keys()]).toStrictEqual(['1', '2', '3', '4']); + expect([... graph.nodes.get('1')!.outputs]).toStrictEqual(['2']); }); test('cloning', () => { - const graph = new Graph([[1, 2], [3], [4, 1]]); + const graph = new Graph([['1', '2'], ['3'], ['4', '1']]); const clone = graph.clone(); expect([... graph.nodes.keys()]).toStrictEqual([... clone.nodes.keys()]); expect([... graph.nodes.values()]).toStrictEqual([... clone.nodes.values()]); - clone.removeNode(3); - expect(clone.nodes.get(3)).toBeUndefined(); - expect(graph.nodes.get(3)).not.toBeUndefined(); + clone.removeNode('3'); + expect(clone.nodes.get('3')).toBeUndefined(); + expect(graph.nodes.get('3')).not.toBeUndefined(); }); }); describe('Testing Graph editing', () => { test('removing edges should not remove nodes', () => { - const graph = new Graph([[1, 2], [3], [4, 1]]); - expect(graph.hasEdge(4, 1)).toBeTruthy(); + const graph = new Graph([['1', '2'], ['3'], ['4', '1']]); + expect(graph.hasEdge('4', '1')).toBeTruthy(); - graph.removeEdge(5, 0); - graph.removeEdge(4, 1); + graph.removeEdge('5', '0'); + graph.removeEdge('4', '1'); - expect([... graph.nodes.keys()]).toStrictEqual([1, 2, 3, 4]); - expect(graph.hasEdge(4, 1)).toBeFalsy(); + expect([... graph.nodes.keys()]).toStrictEqual(['1', '2', '3', '4']); + expect(graph.hasEdge('4', '1')).toBeFalsy(); }); test('folding node redirectes edges', () => { - const graph = new Graph([[1, 3], [2, 3], [3, 4], [3, 5], [3, 3]]); - graph.foldNode(3); - expect(graph.hasNode(3)).toBeFalsy(); - expect(graph.hasEdge(1, 4)).toBeTruthy(); - expect(graph.hasEdge(1, 5)).toBeTruthy(); - expect(graph.hasEdge(2, 4)).toBeTruthy(); - expect(graph.hasEdge(2, 5)).toBeTruthy(); + const graph = new Graph([['1', '3'], ['2', '3'], ['3', '4'], ['3', '5'], ['3', '3']]); + graph.foldNode('3'); + expect(graph.hasNode('3')).toBeFalsy(); + expect(graph.hasEdge('1', '4')).toBeTruthy(); + expect(graph.hasEdge('1', '5')).toBeTruthy(); + expect(graph.hasEdge('2', '4')).toBeTruthy(); + expect(graph.hasEdge('2', '5')).toBeTruthy(); }); test('removing isolated nodes', () => { - const graph = new Graph([[9, 1], [9, 2], [2, 1], [4, 3], [5, 9], [7], [8]]); + const graph = new Graph([['9', '1'], ['9', '2'], ['2', '1'], ['4', '3'], ['5', '9'], ['7'], ['8']]); graph.removeIsolated() - expect([... graph.nodes.keys()]).toStrictEqual([9, 1, 2, 4, 3, 5]); + expect([... graph.nodes.keys()]).toStrictEqual(['9', '1', '2', '4', '3', '5']); }); test('transitive reduction', () => { - const graph = new Graph([[1, 3], [1, 2], [2, 3]]); + const graph = new Graph([['1', '3'], ['1', '2'], ['2', '3']]); graph.transitiveReduction(); - expect(graph.hasEdge(1, 2)).toBeTruthy(); - expect(graph.hasEdge(2, 3)).toBeTruthy(); - expect(graph.hasEdge(1, 3)).toBeFalsy(); + expect(graph.hasEdge('1', '2')).toBeTruthy(); + expect(graph.hasEdge('2', '3')).toBeTruthy(); + expect(graph.hasEdge('1', '3')).toBeFalsy(); }); }); describe('Testing Graph sort', () => { test('topological order', () => { - const graph = new Graph([[9, 1], [9, 2], [2, 1], [4, 3], [5, 9]]); - expect(graph.tolopogicalOrder()).toStrictEqual([5, 4, 3, 9, 2, 1]); + const graph = new Graph([['9', '1'], ['9', '2'], ['2', '1'], ['4', '3'], ['5', '9']]); + expect(graph.tolopogicalOrder()).toStrictEqual(['5', '4', '3', '9', '2', '1']); }); }); describe('Testing Graph queries', () => { test('expand outputs', () => { - const graph = new Graph([[1, 2], [2, 3], [2, 5], [5, 6], [6, 1], [7]]); + const graph = new Graph([['1', '2'], ['2', '3'], ['2', '5'], ['5', '6'], ['6', '1'], ['7']]); expect(graph.expandOutputs([])).toStrictEqual([]); - expect(graph.expandOutputs([3])).toStrictEqual([]); - expect(graph.expandOutputs([7])).toStrictEqual([]); - expect(graph.expandOutputs([2, 5])).toStrictEqual([3, 6, 1]); + expect(graph.expandOutputs(['3'])).toStrictEqual([]); + expect(graph.expandOutputs(['7'])).toStrictEqual([]); + expect(graph.expandOutputs(['2', '5'])).toStrictEqual(['3', '6', '1']); }); test('expand into unique array', () => { - const graph = new Graph([[1, 2], [1, 3], [2, 5], [3, 5]]); - expect(graph.expandOutputs([1])).toStrictEqual([2, 3 ,5]); + const graph = new Graph([['1', '2'], ['1', '3'], ['2', '5'], ['3', '5']]); + expect(graph.expandOutputs(['1'])).toStrictEqual(['2', '3' , '5']); }); test('expand inputs', () => { - const graph = new Graph([[1, 2], [2, 3], [2, 5], [5, 6], [6, 1], [7]]); + const graph = new Graph([['1', '2'], ['2', '3'], ['2', '5'], ['5', '6'], ['6', '1'], ['7']]); expect(graph.expandInputs([])).toStrictEqual([]); - expect(graph.expandInputs([7])).toStrictEqual([]); - expect(graph.expandInputs([6])).toStrictEqual([5, 2, 1]); + expect(graph.expandInputs(['7'])).toStrictEqual([]); + expect(graph.expandInputs(['6'])).toStrictEqual(['5', '2', '1']); }); }); \ No newline at end of file diff --git a/rsconcept/frontend/src/utils/Graph.ts b/rsconcept/frontend/src/utils/Graph.ts index 206758a7..49c13e80 100644 --- a/rsconcept/frontend/src/utils/Graph.ts +++ b/rsconcept/frontend/src/utils/Graph.ts @@ -1,10 +1,10 @@ // ======== ID based fast Graph implementation ============= export class GraphNode { - id: number; - outputs: number[]; - inputs: number[]; + id: string; + outputs: string[]; + inputs: string[]; - constructor(id: number) { + constructor(id: string) { this.id = id; this.outputs = []; this.inputs = []; @@ -17,34 +17,34 @@ export class GraphNode { return result; } - addOutput(node: number): void { + addOutput(node: string): void { this.outputs.push(node); } - addInput(node: number): void { + addInput(node: string): void { this.inputs.push(node); } - removeInput(target: number): number | null { + removeInput(target: string): string | null { const index = this.inputs.findIndex(node => node === target); return index > -1 ? this.inputs.splice(index, 1)[0] : null; } - removeOutput(target: number): number | null { + removeOutput(target: string): string | null { const index = this.outputs.findIndex(node => node === target); return index > -1 ? this.outputs.splice(index, 1)[0] : null; } } export class Graph { - nodes: Map = new Map(); + nodes: Map = new Map(); - constructor(arr?: number[][]) { + constructor(arr?: string[][]) { if (!arr) { return; } arr.forEach(edge => { - if (edge.length == 1) { + if (edge.length === 1) { this.addNode(edge[0]); } else { this.addEdge(edge[0], edge[1]); @@ -58,7 +58,7 @@ export class Graph { return result; } - addNode(target: number): GraphNode { + addNode(target: string): GraphNode { let node = this.nodes.get(target); if (!node) { node = new GraphNode(target); @@ -67,11 +67,11 @@ export class Graph { return node; } - hasNode(target: number): boolean { + hasNode(target: string): boolean { return !!this.nodes.get(target); } - removeNode(target: number): GraphNode | null { + removeNode(target: string): GraphNode | null { const nodeToRemove = this.nodes.get(target); if (!nodeToRemove) { return null; @@ -84,7 +84,7 @@ export class Graph { return nodeToRemove; } - foldNode(target: number): GraphNode | null { + foldNode(target: string): GraphNode | null { const nodeToRemove = this.nodes.get(target); if (!nodeToRemove) { return null; @@ -107,14 +107,14 @@ export class Graph { return result; } - addEdge(source: number, destination: number): void { + addEdge(source: string, destination: string): void { const sourceNode = this.addNode(source); const destinationNode = this.addNode(destination); sourceNode.addOutput(destinationNode.id); destinationNode.addInput(sourceNode.id); } - removeEdge(source: number, destination: number): void { + removeEdge(source: string, destination: string): void { const sourceNode = this.nodes.get(source); const destinationNode = this.nodes.get(destination); if (sourceNode && destinationNode) { @@ -123,7 +123,7 @@ export class Graph { } } - hasEdge(source: number, destination: number): boolean { + hasEdge(source: string, destination: string): boolean { const sourceNode = this.nodes.get(source); if (!sourceNode) { return false; @@ -131,9 +131,9 @@ export class Graph { return !!sourceNode.outputs.find(id => id === destination); } - expandOutputs(origin: number[]): number[] { - const result: number[] = []; - const marked = new Map(); + expandOutputs(origin: string[]): string[] { + const result: string[] = []; + const marked = new Map(); origin.forEach(id => marked.set(id, true)); origin.forEach(id => { const node = this.nodes.get(id); @@ -161,9 +161,9 @@ export class Graph { return result; } - expandInputs(origin: number[]): number[] { - const result: number[] = []; - const marked = new Map(); + expandInputs(origin: string[]): string[] { + const result: string[] = []; + const marked = new Map(); origin.forEach(id => marked.set(id, true)); origin.forEach(id => { const node = this.nodes.get(id); @@ -191,10 +191,10 @@ export class Graph { return result; } - tolopogicalOrder(): number[] { - const result: number[] = []; - const marked = new Map(); - const toVisit: number[] = []; + tolopogicalOrder(): string[] { + const result: string[] = []; + const marked = new Map(); + const toVisit: string[] = []; this.nodes.forEach(node => { if (marked.get(node.id)) { return; @@ -225,12 +225,12 @@ export class Graph { transitiveReduction() { const order = this.tolopogicalOrder(); - const marked = new Map(); + const marked = new Map(); order.forEach(nodeID => { if (marked.get(nodeID)) { return; } - const stack: {id: number, parents: number[]}[] = []; + const stack: {id: string, parents: string[]}[] = []; stack.push({id: nodeID, parents: []}); while (stack.length > 0) { const item = stack.splice(0, 1)[0]; diff --git a/rsconcept/frontend/src/utils/backendAPI.ts b/rsconcept/frontend/src/utils/backendAPI.ts index c74807b1..084f9eb8 100644 --- a/rsconcept/frontend/src/utils/backendAPI.ts +++ b/rsconcept/frontend/src/utils/backendAPI.ts @@ -196,7 +196,7 @@ export function postNewConstituenta(schema: string, request: FrontExchange) { AxiosPatch({ - title: `Delete Constituents for RSForm id=${schema}: ${request.data.items.map(item => String(item.id)).join(' ')}`, + title: `Delete Constituents for RSForm id=${schema}: ${request.data.items.map(item => item.id).join(' ')}`, endpoint: `/api/rsforms/${schema}/cst-multidelete/`, request: request }); diff --git a/rsconcept/frontend/src/utils/enums.ts b/rsconcept/frontend/src/utils/enums.ts index 4ae91c97..24c37c84 100644 --- a/rsconcept/frontend/src/utils/enums.ts +++ b/rsconcept/frontend/src/utils/enums.ts @@ -162,11 +162,11 @@ const ERRCODE_LEXER_MASK = 0x0200; const ERRCODE_PARSER_MASK = 0x0400; const ERRCODE_TYPE_MASK = 0x0800; export function resolveErrorClass(error: RSErrorType): RSErrorClass { - if ((error & ERRCODE_LEXER_MASK) != 0) { + if ((error & ERRCODE_LEXER_MASK) !== 0) { return RSErrorClass.LEXER; - } else if ((error & ERRCODE_PARSER_MASK) != 0) { + } else if ((error & ERRCODE_PARSER_MASK) !== 0) { return RSErrorClass.PARSER; - } else if ((error & ERRCODE_TYPE_MASK) != 0) { + } else if ((error & ERRCODE_TYPE_MASK) !== 0) { return RSErrorClass.SEMANTIC; } else { return RSErrorClass.UNKNOWN; diff --git a/rsconcept/frontend/src/utils/models.ts b/rsconcept/frontend/src/utils/models.ts index b3947892..703715d6 100644 --- a/rsconcept/frontend/src/utils/models.ts +++ b/rsconcept/frontend/src/utils/models.ts @@ -109,7 +109,7 @@ export enum CstClass { } export interface IConstituenta { - id: number + id: string alias: string cstType: CstType convention: string @@ -138,8 +138,8 @@ export interface IConstituenta { } export interface IConstituentaMeta { - id: number - schema: number + id: string + schema: string order: number alias: string convention: string @@ -158,7 +158,7 @@ export interface IConstituentaList { export interface ICstCreateData extends Pick { - insert_after: number | null + insert_after: string | null } export interface ICstMovetoData extends IConstituentaList { @@ -168,6 +168,9 @@ export interface ICstMovetoData extends IConstituentaList { export interface ICstUpdateData extends Pick {} +export interface ICstRenameData +extends Pick {} + export interface ICstCreatedResponse { new_cst: IConstituentaMeta schema: IRSFormData @@ -193,7 +196,7 @@ export interface IRSFormStats { } export interface IRSForm { - id: number + id: string title: string alias: string comment: string @@ -365,7 +368,9 @@ export function LoadRSFormData(schema: IRSFormData): IRSForm { count_theorem: result.items.reduce( (sum, cst) => sum + (cst.cstType === CstType.THEOREM ? 1 : 0), 0) } + result.id = String(result.id) result.items.forEach(cst => { + cst.id = String(cst.id) cst.status = inferStatus(cst.parse.status, cst.parse.valueClass); cst.isTemplate = inferTemplate(cst.definition.formal); cst.cstClass = inferClass(cst.cstType, cst.isTemplate); @@ -411,11 +416,11 @@ export function matchRSFormMeta(query: string, target: IRSFormMeta) { } } -export function applyGraphFilter(schema: IRSForm, start: number, mode: DependencyMode): IConstituenta[] { +export function applyGraphFilter(schema: IRSForm, start: string, mode: DependencyMode): IConstituenta[] { if (mode === DependencyMode.ALL) { return schema.items; } - let ids: number[] | undefined = undefined + let ids: string[] | undefined = undefined switch (mode) { case DependencyMode.OUTPUTS: { ids = schema.graph.nodes.get(start)?.outputs; break; } case DependencyMode.INPUTS: { ids = schema.graph.nodes.get(start)?.inputs; break; } diff --git a/rsconcept/frontend/src/utils/staticUI.ts b/rsconcept/frontend/src/utils/staticUI.ts index 81c3dba5..62f042ed 100644 --- a/rsconcept/frontend/src/utils/staticUI.ts +++ b/rsconcept/frontend/src/utils/staticUI.ts @@ -407,7 +407,7 @@ export function createAliasFor(type: CstType, schema: IRSForm): string { return `${prefix}${index}`; } -export function getMockConstituenta(id: number, alias: string, type: CstType, comment: string): IConstituenta { +export function getMockConstituenta(id: string, alias: string, type: CstType, comment: string): IConstituenta { return { id: id, alias: alias,