diff --git a/.eslintrc.json b/.eslintrc.json index dde9519..aea44ae 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,7 @@ { "plugins": ["prettier"], - "extends": ["next/core-web-vitals", "plugin:prettier/recommended"] + "extends": ["next/core-web-vitals", "plugin:prettier/recommended"], + "rules": { + "react-hooks/exhaustive-deps": "off" + } } diff --git a/.github/workflows/check-copyright-license.yml b/.github/workflows/check-copyright-license.yml new file mode 100644 index 0000000..73ea3a7 --- /dev/null +++ b/.github/workflows/check-copyright-license.yml @@ -0,0 +1,31 @@ +# Workflow name +name: 'Check copyright license on files' + +# Event for the workflow +on: + workflow_call: + inputs: + company: + description: Company name owner of the license + required: true + type: string + extensions: + description: Extensions list where license will add + required: true + type: string + +# List of jobs +jobs: + Check-Copyright-License: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-go@v4 + with: + go-version: '1.20.4' + - run: go install github.com/google/addlicense@latest + - run: addlicense -c '${{ inputs.company }}' -l apache ${{ inputs.extensions }} + - run: git status --porcelain + - run: git diff --exit-code \ No newline at end of file diff --git a/.github/workflows/pr-build-test.yml b/.github/workflows/pr-build-test.yml index 774e264..0185435 100644 --- a/.github/workflows/pr-build-test.yml +++ b/.github/workflows/pr-build-test.yml @@ -1,4 +1,3 @@ - # Workflow name name: 'Build and Test' @@ -11,21 +10,33 @@ on: # List of jobs jobs: + Check-License: + uses: ./.github/workflows/check-copyright-license.yml + with: + company: Arkemis S.r.l. + extensions: ./**/*.js ./**/*.ts ./**/*.tsx ./**/*.css Build-Test: runs-on: ubuntu-latest + needs: Check-License steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Setup pnpm uses: pnpm/action-setup@v2.2.1 with: - version: 8.6.1 + version: latest - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build package run: pnpm build - name: Test run: pnpm test -- --coverage --bail --detectOpenHandles -# - name: Upload coverage reports to Codecov -# uses: codecov/codecov-action@v3 \ No newline at end of file + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage/cobertura-coverage.xml + directory: coverage + fail_ci_if_error: true + verbose: true \ No newline at end of file diff --git a/arke/getClient.ts b/arke/getClient.ts index 1eee7cb..00aa357 100644 --- a/arke/getClient.ts +++ b/arke/getClient.ts @@ -14,12 +14,13 @@ * limitations under the License. */ -import { Client, TToken } from "@arkejs/client"; +import { Client, HTTPStatusCode, TToken } from "@arkejs/client"; import { GetServerSidePropsContext } from "next"; import { getSession } from "next-auth/react"; import { getToken } from "next-auth/jwt"; import { getCookie } from "cookies-next"; import { getCookieName } from "../utils/auth"; +import toast from "react-hot-toast"; const getServerUrl = () => { if ( @@ -60,5 +61,20 @@ export const getClient = (context?: { } return getSession() as Promise; }, + httpClientConfig: (api) => { + api.interceptors.request.use((config) => config); + api.interceptors.response.use( + (config) => { + return config; + }, + (err) => { + if (err.response.status === HTTPStatusCode.InternalServerError) { + toast.error(`${err.message}: ${err.response.data?.errors?.detail}`); + } + return Promise.reject(err); + } + ); + return api; + }, }); }; diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..d245fca --- /dev/null +++ b/codecov.yml @@ -0,0 +1,22 @@ +# Validate: curl --data-binary @codecov.yml https://codecov.io/validate +codecov: + # set new Default branch + branch: main + # Specify a branch you want Codecov to always only read the YAML from + strict_yaml_branch: main; + # When Codecov generates a comparison for a pull-request, but the pull-request’s base + # does not have coverage information, Codecov will try to find an appropriate substitute (a “pseudo-base”) + allow_pseudo_compare: True + +coverage: + status: + project: + default: + target: 70% + threshold: 5% + patch: false + +comment: + require_changes: true + layout: "diff, reach" + behavior: default \ No newline at end of file diff --git a/components/Icon/CompassIcon.tsx b/components/Icon/CompassIcon.tsx new file mode 100644 index 0000000..a9ab6fe --- /dev/null +++ b/components/Icon/CompassIcon.tsx @@ -0,0 +1,36 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function CompassIcon({ className }: { className?: string }) { + return ( + + + + ); +} diff --git a/components/Icon/RemoveIcon.tsx b/components/Icon/RemoveIcon.tsx new file mode 100644 index 0000000..46db46d --- /dev/null +++ b/components/Icon/RemoveIcon.tsx @@ -0,0 +1,36 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function RemoveIcon({ className }: { className?: string }) { + return ( + + + + ); +} diff --git a/components/Sidebar/Sidebar.tsx b/components/Sidebar/Sidebar.tsx index 76a2247..9caaa3a 100644 --- a/components/Sidebar/Sidebar.tsx +++ b/components/Sidebar/Sidebar.tsx @@ -29,6 +29,7 @@ import { CopyIcon, HomeIcon } from "@/components/Icon"; import { Button, Input } from "@arkejs/ui"; import { getCookie } from "cookies-next"; import toast from "react-hot-toast"; +import { CompassIcon } from "@/components/Icon/CompassIcon"; function Sidebar() { const project = @@ -74,6 +75,7 @@ function Sidebar() { + ({ + add: false, + edit: false, + delete: false, + link: false, + }); + const { + arke, + parameters, + onLoadData, + onUnassignParameter, + onEditArke, + onDeleteArke, + } = props.data; + const defaults = ["id", "arke_id", "metadata", "inserted_at", "updated_at"]; + + return ( +
+
+
+
+ {arke.label} +
onEditArke(arke)}> + +
+
+
+
onDeleteArke(arke)}> + +
+
+
+
+
setCrud((p) => ({ ...p, add: true }))} + > + + Assign new parameter +
+
setCrud((prevState) => ({ ...prevState, link: true }))} + > + + Connect arke or group +
+ + {parameters.map((item: TUnit & any) => ( +
+
onUnassignParameter(arke, item)} + > + +
+ + {!item.ref ? ( + <> +
{item.label}
+
({item.type})
+ + ) : ( +
+
{item.ref.label}
+
({item.ref.type})
+
+ )} +
+ ))} +
+ + setCrud((prevState) => ({ ...prevState, add: false }))} + onSubmit={() => { + toast.success(`Parameters assigned correctly`); + onLoadData(); + setCrud((prevState) => ({ ...prevState, add: false })); + }} + /> + + setCrud((prevState) => ({ ...prevState, link: false }))} + onSubmit={() => { + toast.success(`Link connected correctly`); + onLoadData(); + setCrud((prevState) => ({ ...prevState, link: false })); + }} + /> +
+ ); +} + +export default memo(ArkeNode); diff --git a/components/VisualSchema/NoDataNode.tsx b/components/VisualSchema/NoDataNode.tsx new file mode 100644 index 0000000..422a520 --- /dev/null +++ b/components/VisualSchema/NoDataNode.tsx @@ -0,0 +1,33 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { memo } from "react"; +import { AddIcon } from "@/components/Icon"; + +interface NoDataNodeProps { + data: {}; +} +function NoDataNode(props: NoDataNodeProps) { + const {} = props.data; + + return ( + + Use the Right Click to create your first Arke + + ); +} + +export default NoDataNode; diff --git a/components/VisualSchema/RightClickMenuContext.tsx b/components/VisualSchema/RightClickMenuContext.tsx new file mode 100644 index 0000000..95d39b0 --- /dev/null +++ b/components/VisualSchema/RightClickMenuContext.tsx @@ -0,0 +1,75 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { ReactNode, useRef, useState } from "react"; +import useOnClickOutside from "@/hooks/useOnClickOutside"; +import { PlusIcon } from "@heroicons/react/24/outline"; + +interface RightClickMenuContextProps { + children: ReactNode; + onCreateArke(): void; +} + +export default function RightClickMenuContext( + props: RightClickMenuContextProps +) { + const { onCreateArke } = props; + const [showContextMenu, setShowContextMenu] = useState(false); + const rightClickMenuRef = useRef(null); + const clickOutsideHandler = () => { + setShowContextMenu(false); + }; + useOnClickOutside(rightClickMenuRef, clickOutsideHandler); + const [position, setPosition] = useState<{ top: number; left: number }>({ + top: 0, + left: 0, + }); + + return ( + { + e.preventDefault(); // prevent the default behaviour when right-clicked + setPosition({ + left: e.nativeEvent.offsetX, + top: e.nativeEvent.offsetY, + }); + setShowContextMenu(true); + }} + > + {props.children} + + {showContextMenu && ( +
+
{ + setShowContextMenu(false); + onCreateArke(); + }} + > + + Create new Arke +
+
+ )} +
+ ); +} diff --git a/crud/arke/AssignParameterCrud.tsx b/crud/arke/AssignParameterCrud.tsx index 6139be8..f6953e3 100644 --- a/crud/arke/AssignParameterCrud.tsx +++ b/crud/arke/AssignParameterCrud.tsx @@ -19,7 +19,10 @@ import React, { useCallback, useEffect, useState } from "react"; import useDebounce from "@/hooks/useDebounce"; import useClient from "@/arke/useClient"; import { TBaseParameter, TUnit } from "@arkejs/client"; -import { LinkIcon, TrashIcon } from "@/components/Icon"; +import { AddIcon, LinkIcon, TrashIcon } from "@/components/Icon"; +import toast from "react-hot-toast"; +import { ParameterAdd } from "@/crud/parameter"; +import { CrudState } from "@/types/crud"; function AssignParameterAdd({ open, @@ -27,13 +30,18 @@ function AssignParameterAdd({ arkeId, onSubmit, }: { - open: boolean; + open?: boolean; onClose: () => void; linkedParameters: TUnit[]; arkeId: string; onSubmit: () => void; }) { const client = useClient(); + const [crud, setCrud] = useState({ + add: false, + edit: false, + delete: false, + }); const [inputValue, setInputValue] = useState(""); const [values, setValues] = useState([]); const [selected, setSelected] = useState([]); @@ -68,53 +76,79 @@ function AssignParameterAdd({ }, [selected, arkeId, onSubmit]); return ( - - - Assign Parameters + <> + + + Assign Parameters +
+ } + className="flex min-h-[400px] flex-col" + onClose={onClose} + > + { + setSelected([...val]); + }} + onInputChange={(event) => setInputValue(event.target.value)} + multiple + values={values} + value={selected} + getDisplayValue={(val) => val.id} + renderChips={false} + placeholder="Search a parameter" + /> +
+ or{" "} + setCrud((p) => ({ ...p, add: true }))} + > + create new one +
- } - className="flex min-h-[400px] flex-col" - onClose={onClose} - > - { - setSelected([...val]); +
+ {selected.map((sel) => ( + + setSelected((prevState) => + prevState.filter((item) => item.id !== sel.id) + ) + } + > + {sel.id} + + ))} +
+
+ + +
+ + + + + Add Parameter + + } + open={crud.add} + onClose={() => setCrud((p) => ({ ...p, add: false }))} + onSubmit={(res) => { + toast.success(`Parameter ${res.data.content.id} created correctly`); + setCrud((p) => ({ ...p, add: false })); }} - onInputChange={(event) => setInputValue(event.target.value)} - multiple - values={values} - value={selected} - getDisplayValue={(val) => val.id} - renderChips={false} - placeholder="Search a parameter" /> -
- {selected.map((sel) => ( - - setSelected((prevState) => - prevState.filter((item) => item.id !== sel.id) - ) - } - > - {sel.id} - - ))} -
-
- - -
- + ); } @@ -164,7 +198,7 @@ function AssignParameterDelete({ Cancel diff --git a/crud/arke/LinkArkeOrGroup.tsx b/crud/arke/LinkArkeOrGroup.tsx new file mode 100644 index 0000000..980f723 --- /dev/null +++ b/crud/arke/LinkArkeOrGroup.tsx @@ -0,0 +1,129 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Autocomplete, Button, Chip, Dialog } from "@arkejs/ui"; +import React, { useCallback, useEffect, useState } from "react"; +import useDebounce from "@/hooks/useDebounce"; +import useClient from "@/arke/useClient"; +import { HTTPStatusCode, TBaseParameter, TUnit } from "@arkejs/client"; +import { AddIcon, LinkIcon, TrashIcon } from "@/components/Icon"; +import toast from "react-hot-toast"; +import { ParameterAdd } from "@/crud/parameter"; +import { CrudState } from "@/types/crud"; +import { ArkeCrud as ArkeAdd } from "@/crud/arke/ArkeCrud"; + +function LinkArkeOrGroup({ + open, + onClose, + arkeId, + onSubmit, +}: { + open?: boolean; + onClose: () => void; + arkeId: string; + onSubmit: () => void; +}) { + const client = useClient(); + const [crud, setCrud] = useState({ + add: false, + edit: false, + delete: false, + }); + const [inputValue, setInputValue] = useState(""); + const [values, setValues] = useState([]); + const [selected, setSelected] = useState(); + const debouncedInputValue = useDebounce(inputValue, 500); + + useEffect(() => { + if (debouncedInputValue) { + client.arke + .getAll({ + params: { + offset: 0, + limit: 5, + filter: `and(contains(id,${debouncedInputValue}))`, + order: `label;asc`, + }, + }) + .then((res) => { + setValues(res.data.content.items); + }); + } + }, [debouncedInputValue]); + + const handleSubmit = useCallback(async () => { + const linkId = `link_${selected?.id}`; + const linkParameter = () => + client.arke + .addParameter(arkeId, "link", linkId) + .then((res) => onSubmit()) + .catch((err) => { + toast.error("Something went wrong during link connection"); + }); + + await client.unit + .create("link", { + id: linkId, + label: `Link ${selected?.label}`, + type: "link", + arke_or_group_id: selected?.id, + }) + .then((res) => linkParameter()) + .catch((err) => { + // Arke Link not exist + if (err.status !== HTTPStatusCode.BadRequest) { + linkParameter(); + } + }); + }, [selected, arkeId, onSubmit]); + + return ( + <> + + + Link Arke or Group + + } + className="flex min-h-[400px] flex-col" + onClose={onClose} + > + setSelected(val)} + onInputChange={(event) => setInputValue(event.target.value)} + values={values} + value={selected} + getDisplayValue={(val) => val.id} + renderChips={false} + placeholder="Search an Arke or Group" + /> + +
+ + +
+
+ + ); +} + +export { LinkArkeOrGroup }; diff --git a/hooks/useOnClickOutside.ts b/hooks/useOnClickOutside.ts new file mode 100644 index 0000000..8a78c35 --- /dev/null +++ b/hooks/useOnClickOutside.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useEffect, RefObject } from "react"; + +type Event = MouseEvent | TouchEvent; + +const useOnClickOutside = ( + ref: RefObject, + handler: (event: Event) => void +) => { + useEffect(() => { + const listener = (event: Event) => { + const el = ref?.current; + if (!el || el.contains((event?.target as Node) || null)) { + return; + } + + handler(event); // Call the handler only if the click is outside of the element passed. + }; + + document.addEventListener("mousedown", listener); + document.addEventListener("touchstart", listener); + + return () => { + document.removeEventListener("mousedown", listener); + document.removeEventListener("touchstart", listener); + }; + }, [ref, handler]); // Reload only if ref or handler changes +}; + +export default useOnClickOutside; diff --git a/jest.config.js b/jest.config.js index 801d8b1..40740c3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -26,6 +26,7 @@ const createJestConfig = nextJest({ const config = { setupFilesAfterEnv: ["/jest.setup.ts"], testEnvironment: "jest-environment-jsdom", + coverageReporters: ["text", "html", "cobertura"], moduleNameMapper: { "^@/components/(.*)$": "/components/$1", }, diff --git a/package.json b/package.json index bf63030..7c4b3e9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "test": "jest --silent" }, "dependencies": { - "@arkejs/client": "2.2.0", + "@arkejs/client": "2.4.0", "@arkejs/form": "1.2.2", "@arkejs/table": "0.7.1", "@arkejs/ui": "0.27.0", @@ -22,7 +22,8 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.43.7", - "react-hot-toast": "2.4.1" + "react-hot-toast": "2.4.1", + "reactflow": "^11.7.4" }, "devDependencies": { "@swc/core": "^1.3.52", diff --git a/pages/visual-schema/index.tsx b/pages/visual-schema/index.tsx new file mode 100644 index 0000000..8b91d6d --- /dev/null +++ b/pages/visual-schema/index.tsx @@ -0,0 +1,265 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Layout } from "@/components/Layout"; +import ReactFlow, { + addEdge, + MiniMap, + Controls, + Background, + useNodesState, + useEdgesState, + BackgroundVariant, + Connection, +} from "reactflow"; +import React, { useCallback, useEffect, useState } from "react"; +import ArkeNode from "@/components/VisualSchema/ArkeNode"; +import "reactflow/dist/style.css"; +import RightClickMenuContext from "@/components/VisualSchema/RightClickMenuContext"; +import useClient from "@/arke/useClient"; +import { Client, TBaseParameter, TUnit } from "@arkejs/client"; +import { Filter, Sort } from "@arkejs/table"; +import { AddIcon, EditIcon } from "@/components/Icon"; +import toast from "react-hot-toast"; +import { + ArkeCrud as ArkeEdit, + ArkeCrud as ArkeAdd, + ArkeDelete, + AssignParameterDelete, +} from "@/crud/arke"; +import { CrudState } from "@/types/crud"; +import { GetServerSideProps } from "next"; +import { withAuth } from "@/server/withAuth"; +import NoDataNode from "@/components/VisualSchema/NoDataNode"; + +const PAGE_SIZE = 10; +const fetchArke = async ( + client: Client, + page?: number, + filters?: Filter[], + sort?: Sort[] +) => { + return client.arke.getAll({ + params: { + filter: + filters && filters?.length > 0 + ? `and(${filters.map( + (f) => `${f.operator}(${f.columnId},${f.value})` + )})` + : null, + offset: (page ?? 0) * PAGE_SIZE, + limit: PAGE_SIZE, + order: sort?.map((sort) => `${sort.columnId};${sort.type}`), + }, + }); +}; + +// defined outside component +const nodeTypes = { + noData: NoDataNode, + arke: ArkeNode, +}; + +function VisualSchema() { + const client = useClient(); + const [activeArke, setActiveArke] = useState(); + const [arkeCrud, setArkeCrud] = useState({ + add: false, + edit: false, + delete: false, + }); + const [activeParameter, setActiveParameter] = useState(); + const [parametersCrud, setParametersCrud] = useState({ + add: false, + edit: false, + delete: false, + }); + const [nodes, setNodes, onNodesChange] = useNodesState([]); + const [edges, setEdges, onEdgesChange] = useEdgesState([]); + + useEffect(() => { + loadData(); + }, []); + + function loadData() { + fetchArke(client).then(async (res) => { + if (res.data.content.items.length > 0) { + const structPromises = res.data.content.items.map( + async (item, index) => { + const response = await client.arke.struct(item.id); + return { + id: item.id, + type: "arke", + position: { x: index * 200, y: 0 }, + data: { + arke: item, + parameters: response.data.content.parameters, + onLoadData: loadData, + onEditArke: (arke: TUnit) => { + setActiveArke(arke); + setArkeCrud((p) => ({ ...p, edit: true })); + }, + onDeleteArke: (arke: TUnit) => { + setActiveArke(arke); + setArkeCrud((p) => ({ ...p, delete: true })); + }, + onUnassignParameter: ( + arke: TUnit, + parameter: TBaseParameter + ) => { + setActiveArke(arke); + setActiveParameter(parameter); + setParametersCrud((prevState) => ({ + ...prevState, + delete: true, + })); + }, + }, + }; + } + ); + Promise.all(structPromises).then((data) => setNodes(data)); + } else { + setNodes([ + { + id: "no_data", + type: "noData", + position: { x: 0, y: 0 }, + data: {}, + }, + ]); + } + }); + } + + const onConnect = useCallback((params: Connection) => { + setEdges((eds) => addEdge(params, eds)); + }, []); + + return ( + + setArkeCrud((p) => ({ ...p, add: true }))} + > + } + fitView + attributionPosition="top-right" + nodeTypes={nodeTypes} + > + + + + + + + + + Add Arke + + } + open={arkeCrud.add} + onClose={() => setArkeCrud((p) => ({ ...p, add: false }))} + onSubmit={(res) => { + toast.success(`Arke ${res.data.content.id} created correctly`); + loadData(); + setArkeCrud((p) => ({ ...p, add: false })); + }} + /> + + {activeArke && ( + <> + + + Edit Arke + + } + open={!!arkeCrud.edit} + arkeId={activeArke.id} + onClose={() => setArkeCrud((p) => ({ ...p, edit: false }))} + onSubmit={(res) => { + loadData(); + toast.success(`Arke ${res.data.content.id} edited correctly`); + setArkeCrud((p) => ({ ...p, edit: false })); + }} + /> + + setArkeCrud((p) => ({ ...p, delete: false }))} + arkeId={activeArke.id} + onDelete={() => { + loadData(); + toast.success(`Arke deleted correctly`); + setArkeCrud((p) => ({ ...p, delete: false })); + }} + /> + + )} + + {activeArke && activeParameter && ( + <> + + setParametersCrud((prevState) => ({ + ...prevState, + delete: false, + })) + } + arkeId={activeArke?.id} + onDelete={() => { + loadData(); + setParametersCrud((prevState) => ({ + ...prevState, + delete: false, + })); + }} + open={!!parametersCrud.delete} + /> + + )} + + ); +} + +export const getServerSideProps: GetServerSideProps = withAuth(() => { + return { + props: {}, + }; +}); + +export default VisualSchema; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94ccebb..db16a3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@arkejs/client': - specifier: 2.2.0 - version: 2.2.0 + specifier: 2.4.0 + version: 2.4.0 '@arkejs/form': specifier: 1.2.2 version: 1.2.2(react-dom@18.2.0)(react@18.2.0) @@ -44,6 +44,9 @@ dependencies: react-hot-toast: specifier: 2.4.1 version: 2.4.1(csstype@3.1.1)(react-dom@18.2.0)(react@18.2.0) + reactflow: + specifier: ^11.7.4 + version: 11.7.4(react-dom@18.2.0)(react@18.2.0) devDependencies: '@swc/core': @@ -129,10 +132,10 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 - /@arkejs/client@2.2.0: - resolution: {integrity: sha512-B0L3zVK/TLZdZhtIFtWe39+8msBQd41slvwLUiU8q8Mo0PSQY8ahhWjUORMJA/GSicpM8X1OT8KX4A3Nap0wMg==} + /@arkejs/client@2.4.0: + resolution: {integrity: sha512-WsrIsWXT1npGx5IbJxypvBbp42H1xra1gqT4KdJHDFLB/mDJtXuFLnfgegns7geTnOyDNj6ZFoU+Q4KEIXckGA==} dependencies: - axios: 0.24.0 + axios: 1.4.0 transitivePeerDependencies: - debug dev: false @@ -1037,6 +1040,108 @@ packages: resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==} dev: false + /@reactflow/background@11.2.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-SYQbCRCU0GuxT/40Tm7ZK+l5wByGnNJSLtZhbL9C/Hl7JhsJXV3UGXr0vrlhVZUBEtkWA7XhZM/5S9XEA5XSFA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + classcat: 5.0.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + + /@reactflow/controls@11.1.15(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-//33XfBYu8vQ6brfmlZwKrDoh+8hh93xO2d88XiqfIbrPEEb32SYjsb9mS9VuHKNlSIW+eB27fBA1Gt00mEj5w==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + classcat: 5.0.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + + /@reactflow/core@11.7.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nt0T8ERp8TE7YCDQViaoEY9lb0StDPrWHVx3zBjhStFYET3wc88t8QRasZdf99xRTmyNtI3U3M40M5EBLNUpMw==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@types/d3': 7.4.0 + '@types/d3-drag': 3.0.2 + '@types/d3-selection': 3.0.5 + '@types/d3-zoom': 3.0.3 + classcat: 5.0.4 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + + /@reactflow/minimap@11.5.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1tDBj2zX2gxu2oHU6qvH5RGNrOWRfRxu8369KhDotuuBN5yJrGXJzWIKikwhzjsNsQJYOB+B0cS44yWAfwSwzw==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + '@types/d3-selection': 3.0.5 + '@types/d3-zoom': 3.0.3 + classcat: 5.0.4 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + + /@reactflow/node-resizer@2.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5Q+IBmZfpp/bYsw3+KRVJB1nUbj6W3XAp5ycx4uNWH+K98vbssymyQsW0vvKkIhxEPg6tkiMzO4UWRWvwBwt1g==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + classcat: 5.0.4 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + + /@reactflow/node-toolbar@1.2.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-uFQy9xpog92s0G1wsPLniwV9nyH4i/MmL7QoMsWdnKaOi7XMhd8SJcCzUdHC3imR21HltsuQITff/XQ51ApMbg==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + classcat: 5.0.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.3.8(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + /@rushstack/eslint-patch@1.2.0: resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==} dev: true @@ -1271,6 +1376,189 @@ packages: resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} dev: false + /@types/d3-array@3.0.5: + resolution: {integrity: sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A==} + dev: false + + /@types/d3-axis@3.0.2: + resolution: {integrity: sha512-uGC7DBh0TZrU/LY43Fd8Qr+2ja1FKmH07q2FoZFHo1eYl8aj87GhfVoY1saJVJiq24rp1+wpI6BvQJMKgQm8oA==} + dependencies: + '@types/d3-selection': 3.0.5 + dev: false + + /@types/d3-brush@3.0.2: + resolution: {integrity: sha512-2TEm8KzUG3N7z0TrSKPmbxByBx54M+S9lHoP2J55QuLU0VSQ9mE96EJSAOVNEqd1bbynMjeTS9VHmz8/bSw8rA==} + dependencies: + '@types/d3-selection': 3.0.5 + dev: false + + /@types/d3-chord@3.0.2: + resolution: {integrity: sha512-abT/iLHD3sGZwqMTX1TYCMEulr+wBd0SzyOQnjYNLp7sngdOHYtNkMRI5v3w5thoN+BWtlHVDx2Osvq6fxhZWw==} + dev: false + + /@types/d3-color@3.1.0: + resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==} + dev: false + + /@types/d3-contour@3.0.2: + resolution: {integrity: sha512-k6/bGDoAGJZnZWaKzeB+9glgXCYGvh6YlluxzBREiVo8f/X2vpTEdgPy9DN7Z2i42PZOZ4JDhVdlTSTSkLDPlQ==} + dependencies: + '@types/d3-array': 3.0.5 + '@types/geojson': 7946.0.10 + dev: false + + /@types/d3-delaunay@6.0.1: + resolution: {integrity: sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==} + dev: false + + /@types/d3-dispatch@3.0.2: + resolution: {integrity: sha512-rxN6sHUXEZYCKV05MEh4z4WpPSqIw+aP7n9ZN6WYAAvZoEAghEK1WeVZMZcHRBwyaKflU43PCUAJNjFxCzPDjg==} + dev: false + + /@types/d3-drag@3.0.2: + resolution: {integrity: sha512-qmODKEDvyKWVHcWWCOVcuVcOwikLVsyc4q4EBJMREsoQnR2Qoc2cZQUyFUPgO9q4S3qdSqJKBsuefv+h0Qy+tw==} + dependencies: + '@types/d3-selection': 3.0.5 + dev: false + + /@types/d3-dsv@3.0.1: + resolution: {integrity: sha512-76pBHCMTvPLt44wFOieouXcGXWOF0AJCceUvaFkxSZEu4VDUdv93JfpMa6VGNFs01FHfuP4a5Ou68eRG1KBfTw==} + dev: false + + /@types/d3-ease@3.0.0: + resolution: {integrity: sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==} + dev: false + + /@types/d3-fetch@3.0.2: + resolution: {integrity: sha512-gllwYWozWfbep16N9fByNBDTkJW/SyhH6SGRlXloR7WdtAaBui4plTP+gbUgiEot7vGw/ZZop1yDZlgXXSuzjA==} + dependencies: + '@types/d3-dsv': 3.0.1 + dev: false + + /@types/d3-force@3.0.4: + resolution: {integrity: sha512-q7xbVLrWcXvSBBEoadowIUJ7sRpS1yvgMWnzHJggFy5cUZBq2HZL5k/pBSm0GdYWS1vs5/EDwMjSKF55PDY4Aw==} + dev: false + + /@types/d3-format@3.0.1: + resolution: {integrity: sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==} + dev: false + + /@types/d3-geo@3.0.3: + resolution: {integrity: sha512-bK9uZJS3vuDCNeeXQ4z3u0E7OeJZXjUgzFdSOtNtMCJCLvDtWDwfpRVWlyt3y8EvRzI0ccOu9xlMVirawolSCw==} + dependencies: + '@types/geojson': 7946.0.10 + dev: false + + /@types/d3-hierarchy@3.1.2: + resolution: {integrity: sha512-9hjRTVoZjRFR6xo8igAJyNXQyPX6Aq++Nhb5ebrUF414dv4jr2MitM2fWiOY475wa3Za7TOS2Gh9fmqEhLTt0A==} + dev: false + + /@types/d3-interpolate@3.0.1: + resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==} + dependencies: + '@types/d3-color': 3.1.0 + dev: false + + /@types/d3-path@3.0.0: + resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==} + dev: false + + /@types/d3-polygon@3.0.0: + resolution: {integrity: sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==} + dev: false + + /@types/d3-quadtree@3.0.2: + resolution: {integrity: sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==} + dev: false + + /@types/d3-random@3.0.1: + resolution: {integrity: sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==} + dev: false + + /@types/d3-scale-chromatic@3.0.0: + resolution: {integrity: sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==} + dev: false + + /@types/d3-scale@4.0.3: + resolution: {integrity: sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==} + dependencies: + '@types/d3-time': 3.0.0 + dev: false + + /@types/d3-selection@3.0.5: + resolution: {integrity: sha512-xCB0z3Hi8eFIqyja3vW8iV01+OHGYR2di/+e+AiOcXIOrY82lcvWW8Ke1DYE/EUVMsBl4Db9RppSBS3X1U6J0w==} + dev: false + + /@types/d3-shape@3.1.1: + resolution: {integrity: sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==} + dependencies: + '@types/d3-path': 3.0.0 + dev: false + + /@types/d3-time-format@4.0.0: + resolution: {integrity: sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==} + dev: false + + /@types/d3-time@3.0.0: + resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==} + dev: false + + /@types/d3-timer@3.0.0: + resolution: {integrity: sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==} + dev: false + + /@types/d3-transition@3.0.3: + resolution: {integrity: sha512-/S90Od8Id1wgQNvIA8iFv9jRhCiZcGhPd2qX0bKF/PS+y0W5CrXKgIiELd2CvG1mlQrWK/qlYh3VxicqG1ZvgA==} + dependencies: + '@types/d3-selection': 3.0.5 + dev: false + + /@types/d3-zoom@3.0.3: + resolution: {integrity: sha512-OWk1yYIIWcZ07+igN6BeoG6rqhnJ/pYe+R1qWFM2DtW49zsoSjgb9G5xB0ZXA8hh2jAzey1XuRmMSoXdKw8MDA==} + dependencies: + '@types/d3-interpolate': 3.0.1 + '@types/d3-selection': 3.0.5 + dev: false + + /@types/d3@7.4.0: + resolution: {integrity: sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==} + dependencies: + '@types/d3-array': 3.0.5 + '@types/d3-axis': 3.0.2 + '@types/d3-brush': 3.0.2 + '@types/d3-chord': 3.0.2 + '@types/d3-color': 3.1.0 + '@types/d3-contour': 3.0.2 + '@types/d3-delaunay': 6.0.1 + '@types/d3-dispatch': 3.0.2 + '@types/d3-drag': 3.0.2 + '@types/d3-dsv': 3.0.1 + '@types/d3-ease': 3.0.0 + '@types/d3-fetch': 3.0.2 + '@types/d3-force': 3.0.4 + '@types/d3-format': 3.0.1 + '@types/d3-geo': 3.0.3 + '@types/d3-hierarchy': 3.1.2 + '@types/d3-interpolate': 3.0.1 + '@types/d3-path': 3.0.0 + '@types/d3-polygon': 3.0.0 + '@types/d3-quadtree': 3.0.2 + '@types/d3-random': 3.0.1 + '@types/d3-scale': 4.0.3 + '@types/d3-scale-chromatic': 3.0.0 + '@types/d3-selection': 3.0.5 + '@types/d3-shape': 3.1.1 + '@types/d3-time': 3.0.0 + '@types/d3-time-format': 4.0.0 + '@types/d3-timer': 3.0.0 + '@types/d3-transition': 3.0.3 + '@types/d3-zoom': 3.0.3 + dev: false + + /@types/geojson@7946.0.10: + resolution: {integrity: sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==} + dev: false + /@types/graceful-fs@4.1.6: resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} dependencies: @@ -1621,7 +1909,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true /autoprefixer@10.4.14(postcss@8.4.21): resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} @@ -1649,10 +1936,12 @@ packages: engines: {node: '>=4'} dev: true - /axios@0.24.0: - resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} + /axios@1.4.0: + resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 transitivePeerDependencies: - debug dev: false @@ -1857,6 +2146,10 @@ packages: resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} dev: true + /classcat@5.0.4: + resolution: {integrity: sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==} + dev: false + /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false @@ -1916,7 +2209,6 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: true /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1983,6 +2275,71 @@ packages: /csstype@3.1.1: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + /d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + dev: false + + /d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + dev: false + + /d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + dev: false + + /d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + dev: false + + /d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + dependencies: + d3-color: 3.1.0 + dev: false + + /d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + dev: false + + /d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + dev: false + + /d3-transition@3.0.1(d3-selection@3.0.0): + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + dev: false + + /d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + dev: false + /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true @@ -2083,7 +2440,6 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true /detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} @@ -2721,7 +3077,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true /fraction.js@4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} @@ -3938,14 +4293,12 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: true /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - dev: true /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} @@ -4530,6 +4883,10 @@ packages: object-assign: 4.1.1 react-is: 16.13.1 + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true @@ -4631,6 +4988,24 @@ packages: dependencies: loose-envify: 1.4.0 + /reactflow@11.7.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-QI6+oc1Ft6oFeLSdHlp+SmgymbI5Tm49wj5JyE84O4A54yN/ImfYaBhLit9Cmfzxn9Tz6tDqmGMGbk4bdtB8/w==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + dependencies: + '@reactflow/background': 11.2.4(react-dom@18.2.0)(react@18.2.0) + '@reactflow/controls': 11.1.15(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.7.4(react-dom@18.2.0)(react@18.2.0) + '@reactflow/minimap': 11.5.4(react-dom@18.2.0)(react@18.2.0) + '@reactflow/node-resizer': 2.1.1(react-dom@18.2.0)(react@18.2.0) + '@reactflow/node-toolbar': 1.2.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + transitivePeerDependencies: + - immer + dev: false + /read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} dependencies: @@ -5185,6 +5560,14 @@ packages: requires-port: 1.0.0 dev: true + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5374,3 +5757,19 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true + + /zustand@4.3.8(react@18.2.0): + resolution: {integrity: sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==} + engines: {node: '>=12.7.0'} + peerDependencies: + immer: '>=9.0' + react: '>=16.8' + peerDependenciesMeta: + immer: + optional: true + react: + optional: true + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false diff --git a/styles/globals.css b/styles/globals.css index 8d9b1c0..86f9eb2 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -14,6 +14,8 @@ * limitations under the License. */ +@import "./visual-schema.css"; + @tailwind base; @tailwind components; @tailwind utilities; @@ -134,4 +136,8 @@ .project__input { @apply w-full pr-10 text-sm text-neutral-200 focus:outline-none focus:ring-0 } -} + + .card { + @apply bg-background p-2 border border-neutral rounded-theme shadow-2xl + } +} \ No newline at end of file diff --git a/styles/visual-schema.css b/styles/visual-schema.css new file mode 100644 index 0000000..a740aab --- /dev/null +++ b/styles/visual-schema.css @@ -0,0 +1,43 @@ +/** + * Copyright 2023 Arkemis S.r.l. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@layer visual-schema { + /* Visual composer */ + .arke-node { + @apply text-[10px] w-[180px] border text-white shadow-lg rounded-lg !border-neutral border-solid bg-background-200 + } + .arke-node__header { + @apply flex items-center px-2.5 py-1 !border-neutral !border-b border-solid; + } + .react-flow__minimap svg { + @apply bg-background-400; + } + .react-flow__minimap-node { + @apply fill-background-200 stroke-none; + } + .react-flow__minimap-mask { + @apply fill-black; + } + .react-flow__controls-button { + @apply !border-neutral border-b border-solid !bg-background-200; + } + .react-flow__controls-button svg { + @apply fill-white; + } + .react-flow__panel { + @apply !bg-background-200; + } +} \ No newline at end of file