Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c07a02ef31 | ||
![]() |
3c44f55f19 |
@@ -20,6 +20,7 @@
|
||||
"db:migrate": "node ./bin/database/convert-migrations.js && knex migrate:latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@atproto/api": "^0.12.13",
|
||||
"@bull-board/express": "^3.10.1",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
||||
|
@@ -0,0 +1,41 @@
|
||||
import { BskyAgent, RichText } from '@atproto/api';
|
||||
|
||||
import defineAction from '../../../../helpers/define-action.js';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create post',
|
||||
key: 'createPost',
|
||||
description: 'Creates a new post.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Text',
|
||||
key: 'text',
|
||||
type: 'string',
|
||||
required: true,
|
||||
variables: true,
|
||||
description: '',
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const text = $.step.parameters.text;
|
||||
const agent = new BskyAgent({ service: 'https://bsky.social/xrpc' });
|
||||
const richText = new RichText({ text });
|
||||
await richText.detectFacets(agent);
|
||||
|
||||
const body = {
|
||||
repo: $.auth.data.did,
|
||||
collection: 'app.bsky.feed.post',
|
||||
record: {
|
||||
$type: 'app.bsky.feed.post',
|
||||
text: richText.text,
|
||||
facets: richText.facets,
|
||||
createdAt: new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
|
||||
const { data } = await $.http.post('/com.atproto.repo.createRecord', body);
|
||||
|
||||
$.setActionItem({ raw: data });
|
||||
},
|
||||
});
|
3
packages/backend/src/apps/bluesky/actions/index.js
Normal file
3
packages/backend/src/apps/bluesky/actions/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import createPost from './create-post/index.js';
|
||||
|
||||
export default [createPost];
|
4
packages/backend/src/apps/bluesky/assets/favicon.svg
Normal file
4
packages/backend/src/apps/bluesky/assets/favicon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-50 -50 430 390" fill="#1185fd" aria-hidden="true">
|
||||
<path d="M180 141.964C163.699 110.262 119.308 51.1817 78.0347 22.044C38.4971 -5.86834 23.414 -1.03207 13.526 3.43594C2.08093 8.60755 0 26.1785 0 36.5164C0 46.8542 5.66748 121.272 9.36416 133.694C21.5786 174.738 65.0603 188.607 105.104 184.156C107.151 183.852 109.227 183.572 111.329 183.312C109.267 183.642 107.19 183.924 105.104 184.156C46.4204 192.847 -5.69621 214.233 62.6582 290.33C137.848 368.18 165.705 273.637 180 225.702C194.295 273.637 210.76 364.771 295.995 290.33C360 225.702 313.58 192.85 254.896 184.158C252.81 183.926 250.733 183.645 248.671 183.315C250.773 183.574 252.849 183.855 254.896 184.158C294.94 188.61 338.421 174.74 350.636 133.697C354.333 121.275 360 46.8568 360 36.519C360 26.1811 357.919 8.61012 346.474 3.43851C336.586 -1.02949 321.503 -5.86576 281.965 22.0466C240.692 51.1843 196.301 110.262 180 141.964Z">
|
||||
</path>
|
||||
</svg>
|
After Width: | Height: | Size: 956 B |
34
packages/backend/src/apps/bluesky/auth/index.js
Normal file
34
packages/backend/src/apps/bluesky/auth/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import verifyCredentials from './verify-credentials.js';
|
||||
import isStillVerified from './is-still-verified.js';
|
||||
import refreshToken from './refresh-token.js';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'handle',
|
||||
label: 'Your Bluesky Handle',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: '',
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'password',
|
||||
label: 'Your Bluesky Password',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: '',
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
refreshToken,
|
||||
};
|
@@ -0,0 +1,8 @@
|
||||
import getCurrentUser from '../common/get-current-user.js';
|
||||
|
||||
const isStillVerified = async ($) => {
|
||||
const currentUser = await getCurrentUser($);
|
||||
return !!currentUser.did;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
24
packages/backend/src/apps/bluesky/auth/refresh-token.js
Normal file
24
packages/backend/src/apps/bluesky/auth/refresh-token.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const refreshToken = async ($) => {
|
||||
const { refreshJwt } = $.auth.data;
|
||||
|
||||
const { data } = await $.http.post(
|
||||
'/com.atproto.server.refreshSession',
|
||||
null,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${refreshJwt}`,
|
||||
},
|
||||
additionalProperties: {
|
||||
skipAddingAuthHeader: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await $.auth.set({
|
||||
accessJwt: data.accessJwt,
|
||||
refreshJwt: data.refreshJwt,
|
||||
did: data.did,
|
||||
});
|
||||
};
|
||||
|
||||
export default refreshToken;
|
20
packages/backend/src/apps/bluesky/auth/verify-credentials.js
Normal file
20
packages/backend/src/apps/bluesky/auth/verify-credentials.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const verifyCredentials = async ($) => {
|
||||
const handle = $.auth.data.handle;
|
||||
const password = $.auth.data.password;
|
||||
|
||||
const body = {
|
||||
identifier: handle,
|
||||
password,
|
||||
};
|
||||
|
||||
const { data } = await $.http.post('/com.atproto.server.createSession', body);
|
||||
|
||||
await $.auth.set({
|
||||
accessJwt: data.accessJwt,
|
||||
refreshJwt: data.refreshJwt,
|
||||
did: data.did,
|
||||
screenName: data.handle,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
12
packages/backend/src/apps/bluesky/common/add-auth-header.js
Normal file
12
packages/backend/src/apps/bluesky/common/add-auth-header.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const addAuthHeader = ($, requestConfig) => {
|
||||
if (requestConfig.additionalProperties?.skipAddingAuthHeader)
|
||||
return requestConfig;
|
||||
|
||||
if ($.auth.data?.accessJwt) {
|
||||
requestConfig.headers.Authorization = `Bearer ${$.auth.data.accessJwt}`;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
15
packages/backend/src/apps/bluesky/common/get-current-user.js
Normal file
15
packages/backend/src/apps/bluesky/common/get-current-user.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const getCurrentUser = async ($) => {
|
||||
const handle = $.auth.data.handle;
|
||||
|
||||
const params = {
|
||||
actor: handle,
|
||||
};
|
||||
|
||||
const { data: currentUser } = await $.http.get('/app.bsky.actor.getProfile', {
|
||||
params,
|
||||
});
|
||||
|
||||
return currentUser;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
18
packages/backend/src/apps/bluesky/index.js
Normal file
18
packages/backend/src/apps/bluesky/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import defineApp from '../../helpers/define-app.js';
|
||||
import addAuthHeader from './common/add-auth-header.js';
|
||||
import auth from './auth/index.js';
|
||||
import actions from './actions/index.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Bluesky',
|
||||
key: 'bluesky',
|
||||
iconUrl: '{BASE_URL}/apps/bluesky/assets/favicon.svg',
|
||||
authDocUrl: '{DOCS_URL}/apps/bluesky/connection',
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://bluesky.app',
|
||||
apiBaseUrl: 'https://bsky.social/xrpc',
|
||||
primaryColor: '1185fd',
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
actions,
|
||||
});
|
@@ -52,7 +52,7 @@ const appConfig = {
|
||||
isDev: appEnv === 'development',
|
||||
isTest: appEnv === 'test',
|
||||
isProd: appEnv === 'production',
|
||||
version: '0.12.0',
|
||||
version: '0.11.0',
|
||||
postgresDatabase: process.env.POSTGRES_DATABASE || 'automatisch_development',
|
||||
postgresSchema: process.env.POSTGRES_SCHEMA || 'public',
|
||||
postgresPort: parseInt(process.env.POSTGRES_PORT || '5432'),
|
||||
|
@@ -10,7 +10,7 @@ describe('GET /api/v1/automatisch/version', () => {
|
||||
|
||||
const expectedPayload = {
|
||||
data: {
|
||||
version: '0.12.0',
|
||||
version: '0.11.0',
|
||||
},
|
||||
meta: {
|
||||
count: 1,
|
||||
|
@@ -1,11 +0,0 @@
|
||||
export async function up(knex) {
|
||||
return knex.schema.alterTable('datastore', (table) => {
|
||||
table.text('value').alter();
|
||||
});
|
||||
}
|
||||
|
||||
export async function down(knex) {
|
||||
return knex.schema.alterTable('datastore', (table) => {
|
||||
table.string('value').alter();
|
||||
});
|
||||
}
|
@@ -50,6 +50,15 @@ export default defineConfig({
|
||||
{ text: 'Connection', link: '/apps/appwrite/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Bluesky',
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Actions', link: '/apps/bluesky/actions' },
|
||||
{ text: 'Connection', link: '/apps/bluesky/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Carbone',
|
||||
collapsible: true,
|
||||
|
12
packages/docs/pages/apps/bluesky/actions.md
Normal file
12
packages/docs/pages/apps/bluesky/actions.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
favicon: /favicons/bluesky.svg
|
||||
items:
|
||||
- name: Create post
|
||||
desc: Creates a new post.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import CustomListing from '../../components/CustomListing.vue'
|
||||
</script>
|
||||
|
||||
<CustomListing />
|
10
packages/docs/pages/apps/bluesky/connection.md
Normal file
10
packages/docs/pages/apps/bluesky/connection.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Bluesky
|
||||
|
||||
:::info
|
||||
This page explains the steps you need to follow to set up the Bluesky connection in Automatisch. If any of the steps are outdated, please let us know!
|
||||
:::
|
||||
|
||||
1. Enter your `Bluesky Handle` from the page to the `Your Bluesky Handle` field on Automatisch.
|
||||
1. Enter your `Bluesky Password` from the page to the `Your Bluesky Password` field on Automatisch.
|
||||
1. Click **Submit** button on Automatisch.
|
||||
1. Congrats! Start using your new Bluesky connection within the flows.
|
@@ -4,6 +4,7 @@ The following integrations are currently supported by Automatisch.
|
||||
|
||||
- [Airtable](/apps/airtable/actions)
|
||||
- [Appwrite](/apps/appwrite/triggers)
|
||||
- [Bluesky](/apps/bluesky/actions)
|
||||
- [Carbone](/apps/carbone/actions)
|
||||
- [Datastore](/apps/datastore/actions)
|
||||
- [DeepL](/apps/deepl/actions)
|
||||
|
4
packages/docs/pages/public/favicons/bluesky.svg
Normal file
4
packages/docs/pages/public/favicons/bluesky.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-50 -50 430 390" fill="#1185fd" aria-hidden="true">
|
||||
<path d="M180 141.964C163.699 110.262 119.308 51.1817 78.0347 22.044C38.4971 -5.86834 23.414 -1.03207 13.526 3.43594C2.08093 8.60755 0 26.1785 0 36.5164C0 46.8542 5.66748 121.272 9.36416 133.694C21.5786 174.738 65.0603 188.607 105.104 184.156C107.151 183.852 109.227 183.572 111.329 183.312C109.267 183.642 107.19 183.924 105.104 184.156C46.4204 192.847 -5.69621 214.233 62.6582 290.33C137.848 368.18 165.705 273.637 180 225.702C194.295 273.637 210.76 364.771 295.995 290.33C360 225.702 313.58 192.85 254.896 184.158C252.81 183.926 250.733 183.645 248.671 183.315C250.773 183.574 252.849 183.855 254.896 184.158C294.94 188.61 338.421 174.74 350.636 133.697C354.333 121.275 360 46.8568 360 36.519C360 26.1811 357.919 8.61012 346.474 3.43851C336.586 -1.02949 321.503 -5.86576 281.965 22.0466C240.692 51.1843 196.301 110.262 180 141.964Z">
|
||||
</path>
|
||||
</svg>
|
After Width: | Height: | Size: 956 B |
@@ -7,7 +7,6 @@
|
||||
"@apollo/client": "^3.6.9",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@casl/react": "^3.1.0",
|
||||
"@dagrejs/dagre": "^1.1.2",
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@hookform/resolvers": "^2.8.8",
|
||||
@@ -33,7 +32,6 @@
|
||||
"react-router-dom": "^6.0.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"react-window": "^1.8.9",
|
||||
"reactflow": "^11.11.2",
|
||||
"slate": "^0.94.1",
|
||||
"slate-history": "^0.93.0",
|
||||
"slate-react": "^0.94.2",
|
||||
|
@@ -36,7 +36,7 @@ function AdminApplicationSettings(props) {
|
||||
|
||||
const handleSubmit = async (values) => {
|
||||
try {
|
||||
if (!appConfig?.data) {
|
||||
if (!appConfig.data) {
|
||||
await createAppConfig({
|
||||
variables: {
|
||||
input: { key: props.appKey, ...values },
|
||||
@@ -69,7 +69,6 @@ function AdminApplicationSettings(props) {
|
||||
}),
|
||||
[appConfig?.data],
|
||||
);
|
||||
|
||||
return (
|
||||
<Form
|
||||
defaultValues={defaultValues}
|
||||
|
@@ -8,7 +8,6 @@ import * as URLS from 'config/urls';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import { ConnectionPropType } from 'propTypes/propTypes';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import Can from 'components/Can';
|
||||
|
||||
function ContextMenu(props) {
|
||||
const {
|
||||
@@ -45,35 +44,21 @@ function ContextMenu(props) {
|
||||
hideBackdrop={false}
|
||||
anchorEl={anchorEl}
|
||||
>
|
||||
<Can I="read" a="Flow" passThrough>
|
||||
{(allowed) => (
|
||||
<MenuItem
|
||||
component={Link}
|
||||
to={URLS.APP_FLOWS_FOR_CONNECTION(appKey, connection.id)}
|
||||
onClick={createActionHandler({ type: 'viewFlows' })}
|
||||
disabled={!allowed}
|
||||
>
|
||||
{formatMessage('connection.viewFlows')}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Can>
|
||||
|
||||
<Can I="update" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<MenuItem
|
||||
onClick={createActionHandler({ type: 'test' })}
|
||||
disabled={!allowed}
|
||||
>
|
||||
<MenuItem onClick={createActionHandler({ type: 'test' })}>
|
||||
{formatMessage('connection.testConnection')}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Can>
|
||||
|
||||
<Can I="create" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<MenuItem
|
||||
component={Link}
|
||||
disabled={!allowed || disableReconnection}
|
||||
disabled={disableReconnection}
|
||||
to={URLS.APP_RECONNECT_CONNECTION(
|
||||
appKey,
|
||||
connection.id,
|
||||
@@ -83,19 +68,10 @@ function ContextMenu(props) {
|
||||
>
|
||||
{formatMessage('connection.reconnect')}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Can>
|
||||
|
||||
<Can I="delete" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<MenuItem
|
||||
onClick={createActionHandler({ type: 'delete' })}
|
||||
disabled={!allowed}
|
||||
>
|
||||
<MenuItem onClick={createActionHandler({ type: 'delete' })}>
|
||||
{formatMessage('connection.delete')}
|
||||
</MenuItem>
|
||||
)}
|
||||
</Can>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import AppConnectionRow from 'components/AppConnectionRow';
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
import Can from 'components/Can';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import * as URLS from 'config/urls';
|
||||
import useAppConnections from 'hooks/useAppConnections';
|
||||
@@ -17,15 +16,11 @@ function AppConnections(props) {
|
||||
|
||||
if (!hasConnections) {
|
||||
return (
|
||||
<Can I="create" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<NoResultFound
|
||||
to={URLS.APP_ADD_CONNECTION(appKey)}
|
||||
text={formatMessage('app.noConnections')}
|
||||
data-test="connections-no-results"
|
||||
{...(allowed && { to: URLS.APP_ADD_CONNECTION(appKey) })}
|
||||
/>
|
||||
)}
|
||||
</Can>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,6 @@ import PaginationItem from '@mui/material/PaginationItem';
|
||||
|
||||
import * as URLS from 'config/urls';
|
||||
import AppFlowRow from 'components/FlowRow';
|
||||
import Can from 'components/Can';
|
||||
import NoResultFound from 'components/NoResultFound';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import useConnectionFlows from 'hooks/useConnectionFlows';
|
||||
@@ -37,20 +36,11 @@ function AppFlows(props) {
|
||||
|
||||
if (!hasFlows) {
|
||||
return (
|
||||
<Can I="create" a="Flow" passThrough>
|
||||
{(allowed) => (
|
||||
<NoResultFound
|
||||
to={URLS.CREATE_FLOW_WITH_APP_AND_CONNECTION(appKey, connectionId)}
|
||||
text={formatMessage('app.noFlows')}
|
||||
data-test="flows-no-results"
|
||||
{...(allowed && {
|
||||
to: URLS.CREATE_FLOW_WITH_APP_AND_CONNECTION(
|
||||
appKey,
|
||||
connectionId
|
||||
),
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</Can>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -165,7 +165,6 @@ function ChooseAppAndEventSubstep(props) {
|
||||
value={getOption(appOptions, step.appKey) || null}
|
||||
onChange={onAppChange}
|
||||
data-test="choose-app-autocomplete"
|
||||
componentsProps={{ popper: { className: 'nowheel' } }}
|
||||
/>
|
||||
|
||||
{step.appKey && (
|
||||
@@ -228,7 +227,6 @@ function ChooseAppAndEventSubstep(props) {
|
||||
value={getOption(actionOrTriggerOptions, step.key) || null}
|
||||
onChange={onEventChange}
|
||||
data-test="choose-event-autocomplete"
|
||||
componentsProps={{ popper: { className: 'nowheel' } }}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
@@ -240,7 +240,6 @@ function ChooseConnectionSubstep(props) {
|
||||
onChange={handleChange}
|
||||
loading={isAppConnectionsLoading}
|
||||
data-test="choose-connection-autocomplete"
|
||||
componentsProps={{ popper: { className: 'nowheel' } }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
@@ -32,11 +32,9 @@ function ControlledAutocomplete(props) {
|
||||
...autocompleteProps
|
||||
} = props;
|
||||
let dependsOnValues = [];
|
||||
|
||||
if (dependsOn?.length) {
|
||||
dependsOnValues = watch(dependsOn);
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
const hasDependencies = dependsOnValues.length;
|
||||
const allDepsSatisfied = dependsOnValues.every(Boolean);
|
||||
@@ -46,7 +44,6 @@ function ControlledAutocomplete(props) {
|
||||
resetField(name);
|
||||
}
|
||||
}, dependsOnValues);
|
||||
|
||||
return (
|
||||
<Controller
|
||||
rules={{ required }}
|
||||
|
@@ -47,7 +47,6 @@ const CustomOptions = (props) => {
|
||||
},
|
||||
},
|
||||
]}
|
||||
className="nowheel"
|
||||
>
|
||||
<Paper elevation={5} sx={{ width: '100%' }}>
|
||||
<Tabs
|
||||
|
@@ -61,7 +61,6 @@ function ControlledCustomAutocomplete(props) {
|
||||
const [isSingleChoice, setSingleChoice] = React.useState(undefined);
|
||||
const priorStepsWithExecutions = React.useContext(StepExecutionsContext);
|
||||
const editorRef = React.useRef(null);
|
||||
const mountedRef = React.useRef(false);
|
||||
|
||||
const renderElement = React.useCallback(
|
||||
(props) => <Element {...props} disabled={disabled} />,
|
||||
@@ -95,15 +94,11 @@ function ControlledCustomAutocomplete(props) {
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (mountedRef.current) {
|
||||
const hasDependencies = dependsOnValues.length;
|
||||
if (hasDependencies) {
|
||||
// Reset the field when a dependent has been updated
|
||||
resetEditor(editor);
|
||||
}
|
||||
} else {
|
||||
mountedRef.current = true;
|
||||
}
|
||||
}, dependsOnValues);
|
||||
|
||||
React.useEffect(
|
||||
|
@@ -64,19 +64,11 @@ function DynamicField(props) {
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
spacing={{ xs: 2 }}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
}}
|
||||
sx={{ display: 'flex', flex: 1 }}
|
||||
>
|
||||
{fields.map((fieldSchema, fieldSchemaIndex) => (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flex: '1 0 0px',
|
||||
minWidth: 0,
|
||||
}}
|
||||
sx={{ display: 'flex', flex: '1 0 0px' }}
|
||||
key={`field-${field.__id}-${fieldSchemaIndex}`}
|
||||
>
|
||||
<InputCreator
|
||||
|
@@ -8,7 +8,6 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
|
||||
import Snackbar from '@mui/material/Snackbar';
|
||||
import { ReactFlowProvider } from 'reactflow';
|
||||
|
||||
import { EditorProvider } from 'contexts/Editor';
|
||||
import EditableTypography from 'components/EditableTypography';
|
||||
@@ -21,9 +20,6 @@ import * as URLS from 'config/urls';
|
||||
import { TopBar } from './style';
|
||||
import useFlow from 'hooks/useFlow';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import EditorNew from 'components/EditorNew/EditorNew';
|
||||
|
||||
const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true';
|
||||
|
||||
export default function EditorLayout() {
|
||||
const { flowId } = useParams();
|
||||
@@ -135,28 +131,15 @@ export default function EditorLayout() {
|
||||
</Button>
|
||||
</Box>
|
||||
</TopBar>
|
||||
|
||||
{useNewFlowEditor ? (
|
||||
<Stack direction="column" height="100%" flexGrow={1}>
|
||||
<Stack direction="column" flexGrow={1}>
|
||||
<EditorProvider value={{ readOnly: !!flow?.active }}>
|
||||
<ReactFlowProvider>
|
||||
{!flow && !isFlowLoading && 'not found'}
|
||||
{flow && <EditorNew flow={flow} />}
|
||||
</ReactFlowProvider>
|
||||
</EditorProvider>
|
||||
</Stack>
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack direction="column" height="100%">
|
||||
<Container maxWidth="md">
|
||||
<EditorProvider value={{ readOnly: !!flow?.active }}>
|
||||
{!flow && !isFlowLoading && 'not found'}
|
||||
|
||||
{flow && <Editor flow={flow} />}
|
||||
</EditorProvider>
|
||||
</Container>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
<Snackbar
|
||||
data-test="flow-cannot-edit-info-snackbar"
|
||||
|
@@ -1,69 +0,0 @@
|
||||
import { EdgeLabelRenderer, getStraightPath, BaseEdge } from 'reactflow';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext } from 'react';
|
||||
import { EdgesContext } from '../../EditorNew';
|
||||
import { Tooltip } from '@mui/material';
|
||||
|
||||
export default function NodeEdge({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
source,
|
||||
data: { laidOut },
|
||||
}) {
|
||||
const { stepCreationInProgress, flowActive, onAddStep } =
|
||||
useContext(EdgesContext);
|
||||
|
||||
const [edgePath, labelX, labelY] = getStraightPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
});
|
||||
|
||||
const handleAddStep = () => {
|
||||
onAddStep(source);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<BaseEdge path={edgePath} />
|
||||
<EdgeLabelRenderer>
|
||||
<Tooltip title="Add step">
|
||||
<IconButton
|
||||
onClick={handleAddStep}
|
||||
color="primary"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '#fafafa',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f3fa',
|
||||
},
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}}
|
||||
disabled={stepCreationInProgress || flowActive}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</EdgeLabelRenderer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
NodeEdge.propTypes = {
|
||||
sourceX: PropTypes.number.isRequired,
|
||||
sourceY: PropTypes.number.isRequired,
|
||||
targetX: PropTypes.number.isRequired,
|
||||
targetY: PropTypes.number.isRequired,
|
||||
source: PropTypes.string.isRequired,
|
||||
data: PropTypes.shape({
|
||||
laidOut: PropTypes.bool,
|
||||
}).isRequired,
|
||||
};
|
@@ -1,95 +0,0 @@
|
||||
import { EdgeLabelRenderer, getStraightPath, BaseEdge } from 'reactflow';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext, useState } from 'react';
|
||||
import { EdgesContext } from '../../EditorNew';
|
||||
import { Tooltip } from '@mui/material';
|
||||
|
||||
export default function NodeOrPathsEdge({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
source,
|
||||
data: { laidOut },
|
||||
}) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const { stepCreationInProgress, flowActive, onAddStep, onAddPaths } =
|
||||
useContext(EdgesContext);
|
||||
|
||||
const [edgePath, labelX, labelY] = getStraightPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
});
|
||||
|
||||
const handleAddStep = () => {
|
||||
onAddStep(source);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleAddPaths = () => {
|
||||
onAddPaths(source);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<BaseEdge path={edgePath} />
|
||||
<EdgeLabelRenderer>
|
||||
<Tooltip title="Add step or paths">
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
color="primary"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '#fafafa',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f3fa',
|
||||
},
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}}
|
||||
disabled={stepCreationInProgress || flowActive}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
>
|
||||
<MenuItem onClick={handleAddStep}>Step</MenuItem>
|
||||
<MenuItem onClick={handleAddPaths}>Paths</MenuItem>
|
||||
</Menu>
|
||||
</EdgeLabelRenderer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
NodeOrPathsEdge.propTypes = {
|
||||
sourceX: PropTypes.number.isRequired,
|
||||
sourceY: PropTypes.number.isRequired,
|
||||
targetX: PropTypes.number.isRequired,
|
||||
targetY: PropTypes.number.isRequired,
|
||||
source: PropTypes.string.isRequired,
|
||||
data: PropTypes.shape({
|
||||
laidOut: PropTypes.bool,
|
||||
}).isRequired,
|
||||
};
|
@@ -1,69 +0,0 @@
|
||||
import { EdgeLabelRenderer, getStraightPath, BaseEdge } from 'reactflow';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContext } from 'react';
|
||||
import { EdgesContext } from '../../EditorNew';
|
||||
import { Tooltip } from '@mui/material';
|
||||
|
||||
export default function PathsEdge({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
source,
|
||||
data: { laidOut },
|
||||
}) {
|
||||
const { stepCreationInProgress, flowActive, onAddPath } =
|
||||
useContext(EdgesContext);
|
||||
|
||||
const [edgePath, labelX, labelY] = getStraightPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
});
|
||||
|
||||
const handleAddPath = () => {
|
||||
onAddPath(source);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<BaseEdge path={edgePath} />
|
||||
<EdgeLabelRenderer>
|
||||
<Tooltip title="Add path">
|
||||
<IconButton
|
||||
onClick={handleAddPath}
|
||||
color="primary"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '#fafafa',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f3fa',
|
||||
},
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}}
|
||||
disabled={stepCreationInProgress || flowActive}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</EdgeLabelRenderer>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
PathsEdge.propTypes = {
|
||||
sourceX: PropTypes.number.isRequired,
|
||||
sourceY: PropTypes.number.isRequired,
|
||||
targetX: PropTypes.number.isRequired,
|
||||
targetY: PropTypes.number.isRequired,
|
||||
source: PropTypes.string.isRequired,
|
||||
data: PropTypes.shape({
|
||||
laidOut: PropTypes.bool,
|
||||
}).isRequired,
|
||||
};
|
@@ -1,184 +0,0 @@
|
||||
import { useEffect, useCallback, createContext, useRef } from 'react';
|
||||
// import { useMutation } from '@apollo/client';
|
||||
// import { useQueryClient } from '@tanstack/react-query';
|
||||
import { FlowPropType } from 'propTypes/propTypes';
|
||||
import ReactFlow, { useNodesState, useEdgesState } from 'reactflow';
|
||||
import 'reactflow/dist/style.css';
|
||||
// import { UPDATE_STEP } from 'graphql/mutations/update-step';
|
||||
// import { CREATE_STEP } from 'graphql/mutations/create-step';
|
||||
|
||||
import { useAutoLayout } from './useAutoLayout';
|
||||
import NodeOrPathsEdge from './Edges/NodeOrPathsEdge/NodeOrPathsEdge';
|
||||
import FlowStepNode from './Nodes/FlowStepNode/FlowStepNode';
|
||||
import InvisibleNode from './Nodes/InvisibleNode/InvisibleNode';
|
||||
import PathsNode from './Nodes/PathsNode/PathsNode';
|
||||
import { EditorWrapper } from './style';
|
||||
import { generateEdges, generateNodes, updatedCollapsedNodes } from './utils';
|
||||
import { EDGE_TYPES, NODE_TYPES } from './constants';
|
||||
import { useFlow } from './temp/useFlow';
|
||||
import PathNode from './Nodes/PathNode/PathNode';
|
||||
import PathsEdge from './Edges/PathsEdge/PathsEdge';
|
||||
import NodeEdge from './Edges/NodeEdge/NodeEdge';
|
||||
|
||||
export const EdgesContext = createContext();
|
||||
export const NodesContext = createContext();
|
||||
|
||||
const nodeTypes = {
|
||||
[NODE_TYPES.FLOW_STEP]: FlowStepNode,
|
||||
[NODE_TYPES.INVISIBLE]: InvisibleNode,
|
||||
[NODE_TYPES.PATHS]: PathsNode,
|
||||
[NODE_TYPES.PATH]: PathNode,
|
||||
};
|
||||
|
||||
const edgeTypes = {
|
||||
[EDGE_TYPES.ADD_NODE_OR_PATHS_EDGE]: NodeOrPathsEdge,
|
||||
[EDGE_TYPES.ADD_PATH_EDGE]: PathsEdge,
|
||||
[EDGE_TYPES.ADD_NODE_EDGE]: NodeEdge,
|
||||
};
|
||||
|
||||
const EditorNew = () =>
|
||||
// { flow }
|
||||
{
|
||||
const { flow, createStep, createPaths, createPath } = useFlow();
|
||||
// const [updateStep] = useMutation(UPDATE_STEP);
|
||||
// const queryClient = useQueryClient();
|
||||
// const [createStep, { loading: stepCreationInProgress }] =
|
||||
// useMutation(CREATE_STEP);
|
||||
const stepCreationInProgress = false;
|
||||
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||
generateNodes({ steps: flow.steps }),
|
||||
);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||
generateEdges({ steps: flow.steps }),
|
||||
);
|
||||
|
||||
useAutoLayout();
|
||||
|
||||
const createdStepIdRef = useRef(null);
|
||||
|
||||
const openNextStep = useCallback(
|
||||
(currentStepId) => {
|
||||
setNodes((nodes) => {
|
||||
const currentStepIndex = nodes.findIndex(
|
||||
(node) => node.id === currentStepId,
|
||||
);
|
||||
if (currentStepIndex >= 0) {
|
||||
const nextStep = nodes[currentStepIndex + 1];
|
||||
return updatedCollapsedNodes(nodes, nextStep.id);
|
||||
}
|
||||
return nodes;
|
||||
});
|
||||
},
|
||||
[setNodes],
|
||||
);
|
||||
|
||||
const onStepClose = useCallback(() => {
|
||||
setNodes((nodes) => updatedCollapsedNodes(nodes));
|
||||
}, [setNodes]);
|
||||
|
||||
const onStepOpen = useCallback(
|
||||
(stepId) => {
|
||||
setNodes((nodes) => updatedCollapsedNodes(nodes, stepId));
|
||||
},
|
||||
[setNodes],
|
||||
);
|
||||
|
||||
const onStepChange = useCallback(
|
||||
async (step) => {
|
||||
// const mutationInput = {
|
||||
// id: step.id,
|
||||
// key: step.key,
|
||||
// parameters: step.parameters,
|
||||
// connection: {
|
||||
// id: step.connection?.id,
|
||||
// },
|
||||
// flow: {
|
||||
// id: flow.id,
|
||||
// },
|
||||
// };
|
||||
// if (step.appKey) {
|
||||
// mutationInput.appKey = step.appKey;
|
||||
// }
|
||||
// const updated = await updateStep({
|
||||
// variables: { input: mutationInput },
|
||||
// });
|
||||
// await queryClient.invalidateQueries({
|
||||
// queryKey: ['steps', step.id, 'connection'],
|
||||
// });
|
||||
// await queryClient.invalidateQueries({ queryKey: ['flows', flow.id] });
|
||||
},
|
||||
// [flow.id, updateStep, queryClient],
|
||||
);
|
||||
|
||||
const onAddStep = async (previousStepId) => {
|
||||
const createdStepId = createStep(flow, previousStepId);
|
||||
createdStepIdRef.current = createdStepId;
|
||||
};
|
||||
|
||||
console.log({ flow });
|
||||
|
||||
useEffect(() => {
|
||||
// if (flow.steps.length + 1 !== nodes.length) {
|
||||
setNodes((nodes) =>
|
||||
generateNodes({
|
||||
prevNodes: nodes,
|
||||
steps: flow.steps,
|
||||
createdStepId: createdStepIdRef.current,
|
||||
}),
|
||||
);
|
||||
|
||||
setEdges((edges) =>
|
||||
generateEdges({ prevEdges: edges, steps: flow.steps }),
|
||||
);
|
||||
|
||||
if (createdStepIdRef.current) {
|
||||
createdStepIdRef.current = null;
|
||||
}
|
||||
// }
|
||||
}, [flow.steps]);
|
||||
|
||||
return (
|
||||
<NodesContext.Provider
|
||||
value={{
|
||||
openNextStep,
|
||||
onStepOpen,
|
||||
onStepClose,
|
||||
onStepChange,
|
||||
flowId: flow.id,
|
||||
steps: flow.steps,
|
||||
}}
|
||||
>
|
||||
<EdgesContext.Provider
|
||||
value={{
|
||||
stepCreationInProgress,
|
||||
onAddStep,
|
||||
onAddPaths: createPaths,
|
||||
onAddPath: createPath,
|
||||
flowActive: flow.active,
|
||||
}}
|
||||
>
|
||||
<EditorWrapper direction="column">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
fitView
|
||||
maxZoom={1}
|
||||
minZoom={0.001}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
/>
|
||||
</EditorWrapper>
|
||||
</EdgesContext.Provider>
|
||||
</NodesContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
EditorNew.propTypes = {
|
||||
flow: FlowPropType.isRequired,
|
||||
};
|
||||
|
||||
export default EditorNew;
|
@@ -1,69 +0,0 @@
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import FlowStep from 'components/FlowStep';
|
||||
|
||||
import { NodeWrapper, NodeInnerWrapper } from './style.js';
|
||||
import { useContext } from 'react';
|
||||
import { NodesContext } from '../../EditorNew.jsx';
|
||||
import { findStepByStepId } from 'components/EditorNew/utils.js';
|
||||
|
||||
function FlowStepNode({ data: { collapsed, laidOut }, id }) {
|
||||
const { openNextStep, onStepOpen, onStepClose, onStepChange, flowId, steps } =
|
||||
useContext(NodesContext);
|
||||
|
||||
const step = findStepByStepId({ steps }, id);
|
||||
|
||||
return (
|
||||
// <NodeWrapper
|
||||
// sx={{
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
// }}
|
||||
// >
|
||||
<NodeInnerWrapper
|
||||
sx={
|
||||
{
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}
|
||||
}
|
||||
id="flowStepId"
|
||||
className="nodrag"
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Top}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
{step && (
|
||||
<FlowStep
|
||||
step={step}
|
||||
collapsed={collapsed}
|
||||
onOpen={() => onStepOpen(step.id)}
|
||||
onClose={onStepClose}
|
||||
onChange={onStepChange}
|
||||
flowId={flowId}
|
||||
onContinue={() => openNextStep(step.id)}
|
||||
collapseAnimation={false}
|
||||
/>
|
||||
)}
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Bottom}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
</NodeInnerWrapper>
|
||||
// </NodeWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
FlowStepNode.propTypes = {
|
||||
id: PropTypes.string,
|
||||
data: PropTypes.shape({
|
||||
collapsed: PropTypes.bool.isRequired,
|
||||
laidOut: PropTypes.bool.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default FlowStepNode;
|
@@ -1,14 +0,0 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
export const NodeWrapper = styled(Box)(({ theme }) => ({
|
||||
width: '100vw',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
padding: theme.spacing(0, 2.5),
|
||||
}));
|
||||
|
||||
export const NodeInnerWrapper = styled(Box)(({ theme }) => ({
|
||||
width: 900,
|
||||
flex: 1,
|
||||
}));
|
@@ -1,19 +0,0 @@
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
// This node is used for adding an edge with add node button after the last flow step node
|
||||
function InvisibleNode() {
|
||||
return (
|
||||
<Box
|
||||
maxWidth={900}
|
||||
width="100vw"
|
||||
className="nodrag"
|
||||
sx={{ visibility: 'hidden' }}
|
||||
>
|
||||
<Handle type="target" position={Position.Top} isConnectable={false} />
|
||||
Invisible node
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default InvisibleNode;
|
@@ -1,98 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import { Box, Stack, Typography } from '@mui/material';
|
||||
import { useRef, useState } from 'react';
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import { Wrapper } from './style';
|
||||
|
||||
/* TODO
|
||||
- add delete
|
||||
- add rename
|
||||
- add translations
|
||||
- add collapsing?
|
||||
*/
|
||||
|
||||
function PathNode({ data: { laidOut } }) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const contextButtonRef = useRef(null);
|
||||
|
||||
const onContextMenuClose = (event) => {
|
||||
event.stopPropagation();
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const onContextMenuClick = (event) => {
|
||||
event.stopPropagation();
|
||||
setAnchorEl(contextButtonRef.current);
|
||||
};
|
||||
|
||||
const deletePath = () => {
|
||||
setAnchorEl(null);
|
||||
onContextMenuClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
className="nodrag"
|
||||
sx={
|
||||
{
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}
|
||||
}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Top}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
|
||||
<Wrapper>
|
||||
<Stack
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
direction="row"
|
||||
>
|
||||
<Typography sx={{ pr: 2 }}>Path</Typography>
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={onContextMenuClick}
|
||||
ref={contextButtonRef}
|
||||
>
|
||||
<MoreHorizIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Wrapper>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Bottom}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
</Box>
|
||||
{anchorEl && (
|
||||
<Menu
|
||||
open={true}
|
||||
onClose={onContextMenuClose}
|
||||
hideBackdrop={false}
|
||||
anchorEl={anchorEl}
|
||||
>
|
||||
<MenuItem onClick={deletePath}>Delete</MenuItem>
|
||||
</Menu>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
PathNode.propTypes = {
|
||||
data: PropTypes.shape({
|
||||
laidOut: PropTypes.bool,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default PathNode;
|
@@ -1,8 +0,0 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
export const Wrapper = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(1, 2),
|
||||
backgroundColor: '#0059f714',
|
||||
borderRadius: 20,
|
||||
}));
|
@@ -1,108 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { Handle, Position } from 'reactflow';
|
||||
import { Avatar, Box, Stack, Typography } from '@mui/material';
|
||||
import { useRef, useState } from 'react';
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import CallSplitIcon from '@mui/icons-material/CallSplit';
|
||||
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import { Wrapper } from './style';
|
||||
|
||||
/* TODO
|
||||
- add delete
|
||||
- add rename
|
||||
- add translations
|
||||
- add collapsing?
|
||||
*/
|
||||
|
||||
function PathsNode({ data: { laidOut } }) {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const contextButtonRef = useRef(null);
|
||||
|
||||
const onContextMenuClose = (event) => {
|
||||
event.stopPropagation();
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const onContextMenuClick = (event) => {
|
||||
event.stopPropagation();
|
||||
setAnchorEl(contextButtonRef.current);
|
||||
};
|
||||
|
||||
const deletePaths = () => {
|
||||
setAnchorEl(null);
|
||||
onContextMenuClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
width={900}
|
||||
className="nodrag"
|
||||
sx={
|
||||
{
|
||||
// visibility: laidOut ? 'visible' : 'hidden',
|
||||
}
|
||||
}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Top}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
|
||||
<Wrapper>
|
||||
<Stack justifyContent="space-between" direction="row">
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<Avatar
|
||||
sx={{ display: 'flex', width: 50, height: 50 }}
|
||||
variant="square"
|
||||
>
|
||||
<CallSplitIcon
|
||||
fontSize="large"
|
||||
sx={{ transform: 'rotate(180deg)' }}
|
||||
/>
|
||||
</Avatar>
|
||||
{/* TODO name from path data */}
|
||||
<Typography>Paths</Typography>
|
||||
</Stack>
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={onContextMenuClick}
|
||||
ref={contextButtonRef}
|
||||
>
|
||||
<MoreHorizIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
</Wrapper>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Bottom}
|
||||
isConnectable={false}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
</Box>
|
||||
{anchorEl && (
|
||||
<Menu
|
||||
open={true}
|
||||
onClose={onContextMenuClose}
|
||||
hideBackdrop={false}
|
||||
anchorEl={anchorEl}
|
||||
>
|
||||
<MenuItem onClick={deletePaths}>Delete</MenuItem>
|
||||
</Menu>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
PathsNode.propTypes = {
|
||||
data: PropTypes.shape({
|
||||
laidOut: PropTypes.bool,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default PathsNode;
|
@@ -1,7 +0,0 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Card from '@mui/material/Card';
|
||||
|
||||
export const Wrapper = styled(Card)`
|
||||
width: 100%;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
@@ -1,14 +0,0 @@
|
||||
export const INVISIBLE_NODE_ID = 'invisible-node';
|
||||
|
||||
export const NODE_TYPES = {
|
||||
FLOW_STEP: 'flowStep',
|
||||
INVISIBLE: 'invisible',
|
||||
PATHS: 'parallelPaths',
|
||||
PATH: 'path',
|
||||
};
|
||||
|
||||
export const EDGE_TYPES = {
|
||||
ADD_NODE_OR_PATHS_EDGE: 'addNodeOrPathsEdge',
|
||||
ADD_PATH_EDGE: 'addPathEdge',
|
||||
ADD_NODE_EDGE: 'addNodeEdge',
|
||||
};
|
@@ -1,13 +0,0 @@
|
||||
import { Stack } from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
export const EditorWrapper = styled(Stack)(({ theme }) => ({
|
||||
flexGrow: 1,
|
||||
'& > div': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
|
||||
// '& .react-flow__pane, & .react-flow__node': {
|
||||
// cursor: 'auto !important',
|
||||
// },
|
||||
}));
|
@@ -1,96 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { insertStep } from '../utils';
|
||||
|
||||
const initFlow = {
|
||||
id: '7c55e6ce-a84a-46e3-ba31-211ec7b5c2cb',
|
||||
name: 'Name your flow',
|
||||
active: false,
|
||||
status: 'draft',
|
||||
createdAt: 1718264916266,
|
||||
updatedAt: 1718264916266,
|
||||
steps: [
|
||||
{
|
||||
id: '82ce34ab-7aab-4e6c-9f62-db5104aa81c6',
|
||||
type: 'trigger',
|
||||
key: null,
|
||||
appKey: null,
|
||||
iconUrl: null,
|
||||
webhookUrl: 'http://localhost:3000/null',
|
||||
status: 'incomplete',
|
||||
position: 1,
|
||||
parameters: {},
|
||||
},
|
||||
{
|
||||
id: '41c60527-eb4f-4f2d-93ec-2fd37e336909',
|
||||
type: 'action',
|
||||
key: null,
|
||||
appKey: null,
|
||||
iconUrl: null,
|
||||
webhookUrl: 'http://localhost:3000/null',
|
||||
status: 'incomplete',
|
||||
position: 2,
|
||||
parameters: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const generateStep = () => {
|
||||
return {
|
||||
id: uuidv4(),
|
||||
type: 'action',
|
||||
key: null,
|
||||
appKey: null,
|
||||
parameters: {},
|
||||
iconUrl: null,
|
||||
webhookUrl: 'http://localhost:3000/null',
|
||||
status: 'incomplete',
|
||||
connection: null,
|
||||
position: null,
|
||||
};
|
||||
};
|
||||
|
||||
const generatePath = (steps) => {
|
||||
return {
|
||||
id: uuidv4(),
|
||||
type: 'path',
|
||||
steps: steps?.length > 0 ? steps : [generateStep()],
|
||||
};
|
||||
};
|
||||
|
||||
export const generatePaths = (steps) => {
|
||||
return {
|
||||
id: uuidv4(),
|
||||
type: 'parallelPaths',
|
||||
steps: [generatePath(steps), generatePath()],
|
||||
};
|
||||
};
|
||||
|
||||
export const useFlow = () => {
|
||||
const [flow, setFlow] = useState(initFlow);
|
||||
|
||||
const createStep = (flow, previousStepId) => {
|
||||
const newStep = generateStep();
|
||||
const newFlow = insertStep(flow, previousStepId, newStep);
|
||||
|
||||
setFlow(newFlow);
|
||||
return newStep.id;
|
||||
};
|
||||
|
||||
const createPaths = (previousStepId) => {
|
||||
const newFlow = insertStep(flow, previousStepId, generatePaths());
|
||||
setFlow(newFlow);
|
||||
};
|
||||
|
||||
const createPath = (previousStepId) => {
|
||||
const newFlow = insertStep(flow, previousStepId, generatePath());
|
||||
setFlow(newFlow);
|
||||
};
|
||||
|
||||
return {
|
||||
flow,
|
||||
createStep,
|
||||
createPaths,
|
||||
createPath,
|
||||
};
|
||||
};
|
@@ -1,71 +0,0 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import Dagre from '@dagrejs/dagre';
|
||||
import { usePrevious } from 'hooks/usePrevious';
|
||||
import { isEqual } from 'lodash';
|
||||
import { useNodesInitialized, useNodes, useReactFlow } from 'reactflow';
|
||||
|
||||
const getLaidOutElements = (nodes, edges) => {
|
||||
const graph = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
|
||||
graph.setGraph({
|
||||
rankdir: 'TB',
|
||||
marginy: 60,
|
||||
ranksep: 64,
|
||||
});
|
||||
edges.forEach((edge) => graph.setEdge(edge.source, edge.target));
|
||||
nodes.forEach((node) => graph.setNode(node.id, node));
|
||||
|
||||
Dagre.layout(graph);
|
||||
|
||||
return {
|
||||
nodes: nodes.map((node) => {
|
||||
const { x, y, width, height } = graph.node(node.id);
|
||||
return {
|
||||
...node,
|
||||
position: { x: x - width / 2, y: y - height / 2 },
|
||||
};
|
||||
}),
|
||||
edges,
|
||||
};
|
||||
};
|
||||
|
||||
export const useAutoLayout = () => {
|
||||
const nodes = useNodes();
|
||||
const prevNodes = usePrevious(nodes);
|
||||
const nodesInitialized = useNodesInitialized();
|
||||
const { getEdges, setNodes, setEdges, fitView } = useReactFlow();
|
||||
|
||||
const onLayout = useCallback(
|
||||
(nodes, edges) => {
|
||||
const laidOutElements = getLaidOutElements(nodes, edges);
|
||||
|
||||
setNodes([
|
||||
...laidOutElements.nodes.map((node) => ({
|
||||
...node,
|
||||
data: { ...node.data, laidOut: true },
|
||||
})),
|
||||
]);
|
||||
setEdges([
|
||||
...laidOutElements.edges.map((edge) => ({
|
||||
...edge,
|
||||
data: { ...edge.data, laidOut: true },
|
||||
})),
|
||||
]);
|
||||
},
|
||||
[setEdges, setNodes],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const shouldAutoLayout =
|
||||
nodesInitialized &&
|
||||
!isEqual(
|
||||
nodes.map(({ width, height }) => ({ width, height })),
|
||||
prevNodes.map(({ width, height }) => ({ width, height })),
|
||||
);
|
||||
|
||||
fitView();
|
||||
|
||||
if (shouldAutoLayout) {
|
||||
onLayout(nodes, getEdges());
|
||||
}
|
||||
}, [nodes]);
|
||||
};
|
@@ -1,13 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useViewport, useReactFlow } from 'reactflow';
|
||||
|
||||
export const useScrollBoundaries = () => {
|
||||
const { setViewport } = useReactFlow();
|
||||
const { x, y, zoom } = useViewport();
|
||||
|
||||
useEffect(() => {
|
||||
if (y > 0) {
|
||||
setViewport({ x, y: 0, zoom });
|
||||
}
|
||||
}, [y]);
|
||||
};
|
@@ -1,245 +0,0 @@
|
||||
import cloneDeep from 'lodash/cloneDeep.js';
|
||||
import { EDGE_TYPES, INVISIBLE_NODE_ID, NODE_TYPES } from './constants';
|
||||
|
||||
export const generateEdgeId = (sourceId, targetId) =>
|
||||
`${sourceId}--${targetId}`;
|
||||
|
||||
export const updatedCollapsedNodes = (nodes, openStepId) => {
|
||||
return nodes.map((node) => {
|
||||
if (node.type !== NODE_TYPES.FLOW_STEP) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const collapsed = node.id !== openStepId;
|
||||
return {
|
||||
...node,
|
||||
zIndex: collapsed ? 0 : 1,
|
||||
data: { ...node.data, collapsed },
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const generateNodes = ({ steps, prevNodes, createdStepId }) => {
|
||||
const newNodes = steps.map((step, index) => {
|
||||
const collapsed = index !== 0;
|
||||
|
||||
const prevNode = prevNodes?.find(({ id }) => id === step.id);
|
||||
|
||||
let newNode;
|
||||
let childSteps = [];
|
||||
|
||||
switch (step.type) {
|
||||
case 'trigger':
|
||||
case 'action': {
|
||||
if (prevNode) {
|
||||
newNode = {
|
||||
...prevNode,
|
||||
zIndex: createdStepId ? 0 : prevNode?.zIndex || 0,
|
||||
data: {
|
||||
...prevNode.data,
|
||||
collapsed: createdStepId
|
||||
? true
|
||||
: prevNode?.data?.collapsed || true,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
newNode = {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.FLOW_STEP,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
zIndex: collapsed ? 0 : 1,
|
||||
data: {
|
||||
collapsed,
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'parallelPaths': {
|
||||
if (prevNode) {
|
||||
newNode = prevNode;
|
||||
} else {
|
||||
newNode = {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.PATHS,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'path': {
|
||||
if (prevNode) {
|
||||
newNode = prevNode;
|
||||
} else {
|
||||
newNode = {
|
||||
id: step.id,
|
||||
type: NODE_TYPES.PATH,
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
if (step?.steps?.length > 0) {
|
||||
childSteps = generateNodes({
|
||||
steps: step.steps,
|
||||
prevNodes,
|
||||
createdStepId,
|
||||
});
|
||||
}
|
||||
|
||||
return [newNode, ...childSteps];
|
||||
});
|
||||
|
||||
return newNodes.flat(Infinity);
|
||||
};
|
||||
|
||||
export const generateEdges = ({ steps }) => {
|
||||
const newEdges = steps.map((step, index) => {
|
||||
switch (step.type) {
|
||||
case 'parallelPaths': {
|
||||
const edges = step.steps.map((childStep) => {
|
||||
const sourceId = step.id;
|
||||
const targetId = childStep.id;
|
||||
|
||||
const newEdge = {
|
||||
id: generateEdgeId(sourceId, targetId),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: EDGE_TYPES.ADD_PATH_EDGE,
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
|
||||
return newEdge;
|
||||
});
|
||||
|
||||
const childEdges = generateEdges({ steps: step.steps });
|
||||
|
||||
return [...edges, ...childEdges];
|
||||
}
|
||||
case 'path': {
|
||||
console.log({ step });
|
||||
|
||||
const sourceId = step.id;
|
||||
const targetId = step.steps?.[0]?.id;
|
||||
|
||||
if (targetId) {
|
||||
const newEdge = {
|
||||
id: generateEdgeId(sourceId, targetId),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: EDGE_TYPES.ADD_NODE_EDGE,
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
const childEdges = generateEdges({ steps: step.steps });
|
||||
|
||||
return [newEdge, ...childEdges];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
const sourceId = step.id;
|
||||
const targetId = steps[index + 1]?.id;
|
||||
|
||||
if (targetId) {
|
||||
return {
|
||||
id: generateEdgeId(sourceId, targetId),
|
||||
source: sourceId,
|
||||
target: targetId,
|
||||
type: EDGE_TYPES.ADD_NODE_OR_PATHS_EDGE,
|
||||
data: {
|
||||
laidOut: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return newEdges.flat(Infinity).filter((edge) => !!edge);
|
||||
};
|
||||
|
||||
export const findStepByStepId = (obj, id) => {
|
||||
if (Array.isArray(obj.steps)) {
|
||||
for (const step of obj.steps) {
|
||||
if (step.id === id) {
|
||||
return step;
|
||||
}
|
||||
const result = findStepByStepId(step, id);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export function insertStep(parentObj, id, newStep) {
|
||||
function recursiveFindAndInsert(parentObj, id, newStep) {
|
||||
if (parentObj.steps && Array.isArray(parentObj.steps)) {
|
||||
for (let index = 0; index < parentObj.steps.length; index++) {
|
||||
const step = parentObj.steps[index];
|
||||
if (step.id === id) {
|
||||
if (newStep.type === NODE_TYPES.PATHS) {
|
||||
const stepsAfter = parentObj.steps.slice(
|
||||
index + 1,
|
||||
parentObj.steps.length,
|
||||
);
|
||||
parentObj.steps.splice(index + 1);
|
||||
newStep.steps[0].steps = stepsAfter;
|
||||
parentObj.steps.splice(index + 1, 0, newStep);
|
||||
} else if (step.type === NODE_TYPES.PATHS) {
|
||||
step.steps.push(newStep);
|
||||
} else if (step.type === NODE_TYPES.PATH) {
|
||||
step.steps.unshift(newStep);
|
||||
} else {
|
||||
const originalSteps = step.steps || [];
|
||||
step.steps = [];
|
||||
|
||||
const newStepObject = {
|
||||
...newStep,
|
||||
steps: originalSteps,
|
||||
};
|
||||
|
||||
parentObj.steps.splice(index + 1, 0, newStepObject);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const found = recursiveFindAndInsert(step, id, newStep);
|
||||
if (found) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clone the input object to avoid mutating the original
|
||||
const newParentObj = cloneDeep(parentObj);
|
||||
recursiveFindAndInsert(newParentObj, id, newStep);
|
||||
return newParentObj;
|
||||
}
|
@@ -28,12 +28,9 @@ function ContextMenu(props) {
|
||||
variables: { input: { id: flowId } },
|
||||
});
|
||||
|
||||
if (appKey) {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['apps', appKey, 'flows'],
|
||||
});
|
||||
}
|
||||
|
||||
enqueueSnackbar(formatMessage('flow.successfullyDuplicated'), {
|
||||
variant: 'success',
|
||||
SnackbarProps: {
|
||||
@@ -59,12 +56,9 @@ function ContextMenu(props) {
|
||||
},
|
||||
});
|
||||
|
||||
if (appKey) {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['apps', appKey, 'flows'],
|
||||
});
|
||||
}
|
||||
|
||||
enqueueSnackbar(formatMessage('flow.successfullyDeleted'), {
|
||||
variant: 'success',
|
||||
});
|
||||
@@ -116,7 +110,7 @@ ContextMenu.propTypes = {
|
||||
]).isRequired,
|
||||
onDeleteFlow: PropTypes.func,
|
||||
onDuplicateFlow: PropTypes.func,
|
||||
appKey: PropTypes.string,
|
||||
appKey: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ContextMenu;
|
||||
|
@@ -38,24 +38,20 @@ function FlowRow(props) {
|
||||
const contextButtonRef = React.useRef(null);
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
const { flow, onDuplicateFlow, onDeleteFlow, appKey } = props;
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const onContextMenuClick = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.nativeEvent.stopImmediatePropagation();
|
||||
setAnchorEl(contextButtonRef.current);
|
||||
};
|
||||
|
||||
const createdAt = DateTime.fromMillis(parseInt(flow.createdAt, 10));
|
||||
const updatedAt = DateTime.fromMillis(parseInt(flow.updatedAt, 10));
|
||||
const isUpdated = updatedAt > createdAt;
|
||||
const relativeCreatedAt = createdAt.toRelative();
|
||||
const relativeUpdatedAt = updatedAt.toRelative();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card sx={{ mb: 1 }} data-test="flow-row">
|
||||
@@ -131,7 +127,7 @@ FlowRow.propTypes = {
|
||||
flow: FlowPropType.isRequired,
|
||||
onDeleteFlow: PropTypes.func,
|
||||
onDuplicateFlow: PropTypes.func,
|
||||
appKey: PropTypes.string,
|
||||
appKey: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default FlowRow;
|
||||
|
@@ -105,7 +105,7 @@ function generateValidationSchema(substeps) {
|
||||
}
|
||||
|
||||
function FlowStep(props) {
|
||||
const { collapsed, onChange, onContinue, flowId, collapseAnimation } = props;
|
||||
const { collapsed, onChange, onContinue, flowId } = props;
|
||||
const editorContext = React.useContext(EditorContext);
|
||||
const contextButtonRef = React.useRef(null);
|
||||
const step = props.step;
|
||||
@@ -259,11 +259,7 @@ function FlowStep(props) {
|
||||
</Stack>
|
||||
</Header>
|
||||
|
||||
<Collapse
|
||||
in={!collapsed}
|
||||
unmountOnExit
|
||||
{...(!collapseAnimation ? { timeout: 0 } : {})}
|
||||
>
|
||||
<Collapse in={!collapsed} unmountOnExit>
|
||||
<Content>
|
||||
<List>
|
||||
<StepExecutionsProvider value={stepWithTestExecutionsData}>
|
||||
@@ -364,15 +360,11 @@ function FlowStep(props) {
|
||||
FlowStep.propTypes = {
|
||||
collapsed: PropTypes.bool,
|
||||
step: StepPropType.isRequired,
|
||||
index: PropTypes.number,
|
||||
onOpen: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onContinue: PropTypes.func,
|
||||
collapseAnimation: PropTypes.bool,
|
||||
};
|
||||
|
||||
FlowStep.defaultProps = {
|
||||
collapseAnimation: true,
|
||||
};
|
||||
|
||||
export default FlowStep;
|
||||
|
@@ -80,7 +80,6 @@ export default function InputCreator(props) {
|
||||
disabled={disabled}
|
||||
showOptionValue={showOptionValue}
|
||||
shouldUnregister={shouldUnregister}
|
||||
componentsProps={{ popper: { className: 'nowheel' } }}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@@ -17,7 +17,6 @@ import { StepExecutionsContext } from 'contexts/StepExecutions';
|
||||
import Popper from './Popper';
|
||||
import { processStepWithExecutions } from './data';
|
||||
import { ChildrenWrapper, FakeInput, InputLabelWrapper } from './style';
|
||||
|
||||
const PowerInput = (props) => {
|
||||
const { control } = useFormContext();
|
||||
const {
|
||||
@@ -32,41 +31,33 @@ const PowerInput = (props) => {
|
||||
} = props;
|
||||
const priorStepsWithExecutions = React.useContext(StepExecutionsContext);
|
||||
const editorRef = React.useRef(null);
|
||||
|
||||
const renderElement = React.useCallback(
|
||||
(props) => <Element {...props} />,
|
||||
[],
|
||||
);
|
||||
|
||||
const [editor] = React.useState(() => customizeEditor(createEditor()));
|
||||
|
||||
const [showVariableSuggestions, setShowVariableSuggestions] =
|
||||
React.useState(false);
|
||||
|
||||
const disappearSuggestionsOnShift = (event) => {
|
||||
if (event.code === 'Tab') {
|
||||
setShowVariableSuggestions(false);
|
||||
}
|
||||
};
|
||||
|
||||
const stepsWithVariables = React.useMemo(() => {
|
||||
return processStepWithExecutions(priorStepsWithExecutions);
|
||||
}, [priorStepsWithExecutions]);
|
||||
|
||||
const handleBlur = React.useCallback(
|
||||
(value) => {
|
||||
onBlur?.(value);
|
||||
},
|
||||
[onBlur],
|
||||
);
|
||||
|
||||
const handleVariableSuggestionClick = React.useCallback(
|
||||
(variable) => {
|
||||
insertVariable(editor, variable, stepsWithVariables);
|
||||
},
|
||||
[stepsWithVariables],
|
||||
);
|
||||
|
||||
return (
|
||||
<Controller
|
||||
rules={{ required }}
|
||||
@@ -136,7 +127,6 @@ const PowerInput = (props) => {
|
||||
anchorEl={editorRef.current}
|
||||
data={stepsWithVariables}
|
||||
onSuggestionClick={handleVariableSuggestionClick}
|
||||
className="nowheel"
|
||||
/>
|
||||
|
||||
<FormHelperText variant="outlined">{description}</FormHelperText>
|
||||
|
@@ -1,9 +0,0 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
export const usePrevious = (value) => {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
});
|
||||
return ref.current;
|
||||
};
|
@@ -30,7 +30,6 @@ import AppIcon from 'components/AppIcon';
|
||||
import Container from 'components/Container';
|
||||
import PageTitle from 'components/PageTitle';
|
||||
import useApp from 'hooks/useApp';
|
||||
import Can from 'components/Can';
|
||||
|
||||
const ReconnectConnection = (props) => {
|
||||
const { application, onClose } = props;
|
||||
@@ -93,7 +92,7 @@ export default function Application() {
|
||||
}
|
||||
|
||||
return options;
|
||||
}, [appKey, appConfig?.data, currentUserAbility, formatMessage]);
|
||||
}, [appKey, appConfig?.data, currentUserAbility]);
|
||||
|
||||
if (loading) return null;
|
||||
|
||||
@@ -119,8 +118,6 @@ export default function Application() {
|
||||
<Route
|
||||
path={`${URLS.FLOWS}/*`}
|
||||
element={
|
||||
<Can I="create" a="Flow" passThrough>
|
||||
{(allowed) => (
|
||||
<ConditionalIconButton
|
||||
type="submit"
|
||||
variant="contained"
|
||||
@@ -133,23 +130,18 @@ export default function Application() {
|
||||
)}
|
||||
fullWidth
|
||||
icon={<AddIcon />}
|
||||
disabled={!allowed}
|
||||
disabled={!currentUserAbility.can('create', 'Flow')}
|
||||
>
|
||||
{formatMessage('app.createFlow')}
|
||||
</ConditionalIconButton>
|
||||
)}
|
||||
</Can>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path={`${URLS.CONNECTIONS}/*`}
|
||||
element={
|
||||
<Can I="create" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<SplitButton
|
||||
disabled={
|
||||
!allowed ||
|
||||
(appConfig?.data &&
|
||||
!appConfig?.data?.canConnect &&
|
||||
!appConfig?.data?.canCustomConnect) ||
|
||||
@@ -157,8 +149,6 @@ export default function Application() {
|
||||
}
|
||||
options={connectionOptions}
|
||||
/>
|
||||
)}
|
||||
</Can>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
@@ -179,20 +169,17 @@ export default function Application() {
|
||||
label={formatMessage('app.connections')}
|
||||
to={URLS.APP_CONNECTIONS(appKey)}
|
||||
value={URLS.APP_CONNECTIONS_PATTERN}
|
||||
disabled={
|
||||
!currentUserAbility.can('read', 'Connection') ||
|
||||
!app.supportsConnections
|
||||
}
|
||||
disabled={!app.supportsConnections}
|
||||
component={Link}
|
||||
data-test="connections-tab"
|
||||
/>
|
||||
|
||||
<Tab
|
||||
label={formatMessage('app.flows')}
|
||||
to={URLS.APP_FLOWS(appKey)}
|
||||
value={URLS.APP_FLOWS_PATTERN}
|
||||
component={Link}
|
||||
data-test="flows-tab"
|
||||
disabled={!currentUserAbility.can('read', 'Flow')}
|
||||
/>
|
||||
</Tabs>
|
||||
</Box>
|
||||
@@ -200,20 +187,14 @@ export default function Application() {
|
||||
<Routes>
|
||||
<Route
|
||||
path={`${URLS.FLOWS}/*`}
|
||||
element={
|
||||
<Can I="read" a="Flow">
|
||||
<AppFlows appKey={appKey} />
|
||||
</Can>
|
||||
}
|
||||
element={<AppFlows appKey={appKey} />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path={`${URLS.CONNECTIONS}/*`}
|
||||
element={
|
||||
<Can I="read" a="Connection">
|
||||
<AppConnections appKey={appKey} />
|
||||
</Can>
|
||||
}
|
||||
element={<AppConnections appKey={appKey} />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
@@ -237,24 +218,17 @@ export default function Application() {
|
||||
<Route
|
||||
path="/connections/add"
|
||||
element={
|
||||
<Can I="create" a="Connection">
|
||||
<AddAppConnection
|
||||
onClose={goToApplicationPage}
|
||||
application={app}
|
||||
/>
|
||||
</Can>
|
||||
<AddAppConnection onClose={goToApplicationPage} application={app} />
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/connections/:connectionId/reconnect"
|
||||
element={
|
||||
<Can I="create" a="Connection">
|
||||
<ReconnectConnection
|
||||
application={app}
|
||||
onClose={goToApplicationPage}
|
||||
/>
|
||||
</Can>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
|
@@ -84,15 +84,11 @@ export default function Applications() {
|
||||
)}
|
||||
|
||||
{!isLoading && !hasApps && (
|
||||
<Can I="create" a="Connection" passThrough>
|
||||
{(allowed) => (
|
||||
<NoResultFound
|
||||
text={formatMessage('apps.noConnections')}
|
||||
{...(allowed && { to: URLS.NEW_APP_CONNECTION })}
|
||||
to={URLS.NEW_APP_CONNECTION}
|
||||
/>
|
||||
)}
|
||||
</Can>
|
||||
)}
|
||||
|
||||
{!isLoading &&
|
||||
apps?.map((app) => (
|
||||
|
@@ -3,7 +3,7 @@ services:
|
||||
name: automatisch-main
|
||||
env: docker
|
||||
dockerfilePath: ./docker/Dockerfile
|
||||
dockerContext: .
|
||||
dockerContext: ./docker
|
||||
repo: https://github.com/automatisch/automatisch
|
||||
autoDeploy: false
|
||||
envVars:
|
||||
@@ -47,7 +47,7 @@ services:
|
||||
name: automatisch-worker
|
||||
env: docker
|
||||
dockerfilePath: ./docker/Dockerfile
|
||||
dockerContext: .
|
||||
dockerContext: ./docker
|
||||
repo: https://github.com/automatisch/automatisch
|
||||
autoDeploy: false
|
||||
envVars:
|
||||
|
460
yarn.lock
460
yarn.lock
@@ -170,6 +170,52 @@
|
||||
tslib "^2.3.0"
|
||||
zen-observable-ts "~1.1.0"
|
||||
|
||||
"@atproto/api@^0.12.13":
|
||||
version "0.12.13"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.13.tgz#269d6c57ea894e23f20b28bd3cbfed944bd28528"
|
||||
integrity sha512-pRSID6w8AUiZJoCxgctMPRTSGVFHq7wphAnxEbRLBP3OQ1g+BRZUcqFw+e+17Pd3wrc8VImjiD4HCWtCJvCx3w==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.3.0"
|
||||
"@atproto/lexicon" "^0.4.0"
|
||||
"@atproto/syntax" "^0.3.0"
|
||||
"@atproto/xrpc" "^0.5.0"
|
||||
multiformats "^9.9.0"
|
||||
tlds "^1.234.0"
|
||||
|
||||
"@atproto/common-web@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.3.0.tgz#36da8c2c31d8cf8a140c3c8f03223319bf4430bb"
|
||||
integrity sha512-67VnV6JJyX+ZWyjV7xFQMypAgDmjVaR9ZCuU/QW+mqlqI7fex2uL4Fv+7/jHadgzhuJHVd6OHOvNn0wR5WZYtA==
|
||||
dependencies:
|
||||
graphemer "^1.4.0"
|
||||
multiformats "^9.9.0"
|
||||
uint8arrays "3.0.0"
|
||||
zod "^3.21.4"
|
||||
|
||||
"@atproto/lexicon@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.0.tgz#63e8829945d80c25524882caa8ed27b1151cc576"
|
||||
integrity sha512-RvCBKdSI4M8qWm5uTNz1z3R2yIvIhmOsMuleOj8YR6BwRD+QbtUBy3l+xQ7iXf4M5fdfJFxaUNa6Ty0iRwdKqQ==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.3.0"
|
||||
"@atproto/syntax" "^0.3.0"
|
||||
iso-datestring-validator "^2.2.2"
|
||||
multiformats "^9.9.0"
|
||||
zod "^3.21.4"
|
||||
|
||||
"@atproto/syntax@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3"
|
||||
integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA==
|
||||
|
||||
"@atproto/xrpc@^0.5.0":
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.5.0.tgz#dacbfd8f7b13f0ab5bd56f8fdd4b460e132a6032"
|
||||
integrity sha512-swu+wyOLvYW4l3n+VAuJbHcPcES+tin2Lsrp8Bw5aIXIICiuFn1YMFlwK9JwVUzTH21Py1s1nHEjr4CJeElJog==
|
||||
dependencies:
|
||||
"@atproto/lexicon" "^0.4.0"
|
||||
zod "^3.21.4"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz"
|
||||
@@ -1455,18 +1501,6 @@
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
"@dagrejs/dagre@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@dagrejs/dagre/-/dagre-1.1.2.tgz#5ec339979447091f48d2144deed8c70dfadae374"
|
||||
integrity sha512-F09dphqvHsbe/6C2t2unbmpr5q41BNPEfJCdn8Z7aEBpVSy/zFQ/b4SWsweQjWNsYMDvE2ffNUN8X0CeFsEGNw==
|
||||
dependencies:
|
||||
"@dagrejs/graphlib" "2.2.2"
|
||||
|
||||
"@dagrejs/graphlib@2.2.2":
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.2.tgz#74154d5cb880a23b4fae71034a09b4b5aef06feb"
|
||||
integrity sha512-CbyGpCDKsiTg/wuk79S7Muoj8mghDGAESWGxcSyhHX5jD35vYMBZochYVFzlHxynpE9unpu6O+4ZuhrLxASsOg==
|
||||
|
||||
"@docsearch/css@3.2.1", "@docsearch/css@^3.2.1":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.npmjs.org/@docsearch/css/-/css-3.2.1.tgz"
|
||||
@@ -3345,72 +3379,6 @@
|
||||
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz"
|
||||
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
|
||||
|
||||
"@reactflow/background@11.3.12":
|
||||
version "11.3.12"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/background/-/background-11.3.12.tgz#9c9491cce4659bae13074fcdb48ac25664879d3f"
|
||||
integrity sha512-jBuWVb43JQy5h4WOS7G0PU8voGTEJNA+qDmx8/jyBtrjbasTesLNfQvboTGjnQYYiJco6mw5vrtQItAJDNoIqw==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.2"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/controls@11.2.12":
|
||||
version "11.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/controls/-/controls-11.2.12.tgz#85e2aa5de17e2af28a5ecf6a75bb9c828a20640b"
|
||||
integrity sha512-L9F3+avFRShoprdT+5oOijm5gVsz2rqWCXBzOAgD923L1XFGIspdiHLLf8IlPGsT+mfl0GxbptZhaEeEzl1e3g==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.2"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/core@11.11.2":
|
||||
version "11.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/core/-/core-11.11.2.tgz#c62f78297bda9d2e86a12228617ec3f91fbd4b22"
|
||||
integrity sha512-+GfgyskweL1PsgRSguUwfrT2eDotlFgaKfDLm7x0brdzzPJY2qbCzVetaxedaiJmIli3817iYbILvE9qLKwbRA==
|
||||
dependencies:
|
||||
"@types/d3" "^7.4.0"
|
||||
"@types/d3-drag" "^3.0.1"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/minimap@11.7.12":
|
||||
version "11.7.12"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/minimap/-/minimap-11.7.12.tgz#6b2fc671ee17e37ccd3bc038ae8d2121d0ce6291"
|
||||
integrity sha512-SRDU77c2PCF54PV/MQfkz7VOW46q7V1LZNOQlXAp7dkNyAOI6R+tb9qBUtUJOvILB+TCN6pRfD9fQ+2T99bW3Q==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.2"
|
||||
"@types/d3-selection" "^3.0.3"
|
||||
"@types/d3-zoom" "^3.0.1"
|
||||
classcat "^5.0.3"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-resizer@2.2.12":
|
||||
version "2.2.12"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/node-resizer/-/node-resizer-2.2.12.tgz#df82a7dfba883afea6a01a9c8210008a1ddba01f"
|
||||
integrity sha512-6LHJGuI1zHyRrZHw5gGlVLIWnvVxid9WIqw8FMFSg+oF2DuS3pAPwSoZwypy7W22/gDNl9eD1Dcl/OtFtDFQ+w==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.2"
|
||||
classcat "^5.0.4"
|
||||
d3-drag "^3.0.0"
|
||||
d3-selection "^3.0.0"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@reactflow/node-toolbar@1.3.12":
|
||||
version "1.3.12"
|
||||
resolved "https://registry.yarnpkg.com/@reactflow/node-toolbar/-/node-toolbar-1.3.12.tgz#89e7aa9d34b6213bb5e64c344d4e2e3cb7af3163"
|
||||
integrity sha512-4kJRvNna/E3y2MZW9/80wTKwkhw4pLJiz3D5eQrD13XcmojSb1rArO9CiwyrI+rMvs5gn6NlCFB4iN1F+Q+lxQ==
|
||||
dependencies:
|
||||
"@reactflow/core" "11.11.2"
|
||||
classcat "^5.0.3"
|
||||
zustand "^4.4.1"
|
||||
|
||||
"@rollup/plugin-babel@^5.2.0":
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz"
|
||||
@@ -3901,216 +3869,6 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/d3-array@*":
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5"
|
||||
integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
|
||||
|
||||
"@types/d3-axis@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795"
|
||||
integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-brush@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c"
|
||||
integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-chord@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d"
|
||||
integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==
|
||||
|
||||
"@types/d3-color@*":
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2"
|
||||
integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
|
||||
|
||||
"@types/d3-contour@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231"
|
||||
integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-delaunay@*":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1"
|
||||
integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==
|
||||
|
||||
"@types/d3-dispatch@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7"
|
||||
integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==
|
||||
|
||||
"@types/d3-drag@*", "@types/d3-drag@^3.0.1":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02"
|
||||
integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-dsv@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17"
|
||||
integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==
|
||||
|
||||
"@types/d3-ease@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b"
|
||||
integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
|
||||
|
||||
"@types/d3-fetch@*":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980"
|
||||
integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==
|
||||
dependencies:
|
||||
"@types/d3-dsv" "*"
|
||||
|
||||
"@types/d3-force@*":
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.9.tgz#dd96ccefba4386fe4ff36b8e4ee4e120c21fcf29"
|
||||
integrity sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==
|
||||
|
||||
"@types/d3-format@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90"
|
||||
integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==
|
||||
|
||||
"@types/d3-geo@*":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440"
|
||||
integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==
|
||||
dependencies:
|
||||
"@types/geojson" "*"
|
||||
|
||||
"@types/d3-hierarchy@*":
|
||||
version "3.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b"
|
||||
integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==
|
||||
|
||||
"@types/d3-interpolate@*":
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c"
|
||||
integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==
|
||||
dependencies:
|
||||
"@types/d3-color" "*"
|
||||
|
||||
"@types/d3-path@*":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a"
|
||||
integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==
|
||||
|
||||
"@types/d3-polygon@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c"
|
||||
integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==
|
||||
|
||||
"@types/d3-quadtree@*":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f"
|
||||
integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==
|
||||
|
||||
"@types/d3-random@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb"
|
||||
integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==
|
||||
|
||||
"@types/d3-scale-chromatic@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644"
|
||||
integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==
|
||||
|
||||
"@types/d3-scale@*":
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb"
|
||||
integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==
|
||||
dependencies:
|
||||
"@types/d3-time" "*"
|
||||
|
||||
"@types/d3-selection@*", "@types/d3-selection@^3.0.3":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe"
|
||||
integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==
|
||||
|
||||
"@types/d3-shape@*":
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72"
|
||||
integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==
|
||||
dependencies:
|
||||
"@types/d3-path" "*"
|
||||
|
||||
"@types/d3-time-format@*":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2"
|
||||
integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==
|
||||
|
||||
"@types/d3-time@*":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be"
|
||||
integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==
|
||||
|
||||
"@types/d3-timer@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70"
|
||||
integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
|
||||
|
||||
"@types/d3-transition@*":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f"
|
||||
integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==
|
||||
dependencies:
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3-zoom@*", "@types/d3-zoom@^3.0.1":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b"
|
||||
integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==
|
||||
dependencies:
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-selection" "*"
|
||||
|
||||
"@types/d3@^7.4.0":
|
||||
version "7.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2"
|
||||
integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==
|
||||
dependencies:
|
||||
"@types/d3-array" "*"
|
||||
"@types/d3-axis" "*"
|
||||
"@types/d3-brush" "*"
|
||||
"@types/d3-chord" "*"
|
||||
"@types/d3-color" "*"
|
||||
"@types/d3-contour" "*"
|
||||
"@types/d3-delaunay" "*"
|
||||
"@types/d3-dispatch" "*"
|
||||
"@types/d3-drag" "*"
|
||||
"@types/d3-dsv" "*"
|
||||
"@types/d3-ease" "*"
|
||||
"@types/d3-fetch" "*"
|
||||
"@types/d3-force" "*"
|
||||
"@types/d3-format" "*"
|
||||
"@types/d3-geo" "*"
|
||||
"@types/d3-hierarchy" "*"
|
||||
"@types/d3-interpolate" "*"
|
||||
"@types/d3-path" "*"
|
||||
"@types/d3-polygon" "*"
|
||||
"@types/d3-quadtree" "*"
|
||||
"@types/d3-random" "*"
|
||||
"@types/d3-scale" "*"
|
||||
"@types/d3-scale-chromatic" "*"
|
||||
"@types/d3-selection" "*"
|
||||
"@types/d3-shape" "*"
|
||||
"@types/d3-time" "*"
|
||||
"@types/d3-time-format" "*"
|
||||
"@types/d3-timer" "*"
|
||||
"@types/d3-transition" "*"
|
||||
"@types/d3-zoom" "*"
|
||||
|
||||
"@types/debug@^4.1.7":
|
||||
version "4.1.8"
|
||||
resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz"
|
||||
@@ -4201,11 +3959,6 @@
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/geojson@*":
|
||||
version "7946.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613"
|
||||
integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==
|
||||
|
||||
"@types/graceful-fs@^4.1.2":
|
||||
version "4.1.5"
|
||||
resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz"
|
||||
@@ -6337,11 +6090,6 @@ cjs-module-lexer@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz"
|
||||
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
|
||||
|
||||
classcat@^5.0.3, classcat@^5.0.4:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.5.tgz#8c209f359a93ac302404a10161b501eba9c09c77"
|
||||
integrity sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==
|
||||
|
||||
clean-css@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.npmjs.org/clean-css/-/clean-css-5.2.2.tgz"
|
||||
@@ -7127,68 +6875,6 @@ csstype@^3.1.1:
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz"
|
||||
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
|
||||
|
||||
"d3-color@1 - 3":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
|
||||
integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
|
||||
|
||||
"d3-dispatch@1 - 3":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
|
||||
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||
|
||||
"d3-drag@2 - 3", d3-drag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
|
||||
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||
dependencies:
|
||||
d3-dispatch "1 - 3"
|
||||
d3-selection "3"
|
||||
|
||||
"d3-ease@1 - 3":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
|
||||
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
|
||||
|
||||
"d3-interpolate@1 - 3":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
|
||||
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||
dependencies:
|
||||
d3-color "1 - 3"
|
||||
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
|
||||
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||
|
||||
"d3-timer@1 - 3":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
|
||||
integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
|
||||
|
||||
"d3-transition@2 - 3":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
|
||||
integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
|
||||
dependencies:
|
||||
d3-color "1 - 3"
|
||||
d3-dispatch "1 - 3"
|
||||
d3-ease "1 - 3"
|
||||
d3-interpolate "1 - 3"
|
||||
d3-timer "1 - 3"
|
||||
|
||||
d3-zoom@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
|
||||
integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
|
||||
dependencies:
|
||||
d3-dispatch "1 - 3"
|
||||
d3-drag "2 - 3"
|
||||
d3-interpolate "1 - 3"
|
||||
d3-selection "2 - 3"
|
||||
d3-transition "2 - 3"
|
||||
|
||||
damerau-levenshtein@^1.0.7:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz"
|
||||
@@ -9299,6 +8985,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
||||
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
|
||||
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
||||
|
||||
graphemer@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
|
||||
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
|
||||
|
||||
graphql-executor@0.0.18:
|
||||
version "0.0.18"
|
||||
resolved "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.18.tgz"
|
||||
@@ -10236,6 +9927,11 @@ isexe@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
|
||||
integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
|
||||
|
||||
iso-datestring-validator@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz#2daa80d2900b7a954f9f731d42f96ee0c19a6895"
|
||||
integrity sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==
|
||||
|
||||
isobject@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz"
|
||||
@@ -11952,6 +11648,11 @@ multicast-dns@^6.0.1:
|
||||
dns-packet "^1.3.1"
|
||||
thunky "^1.0.2"
|
||||
|
||||
multiformats@^9.4.2, multiformats@^9.9.0:
|
||||
version "9.9.0"
|
||||
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37"
|
||||
integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==
|
||||
|
||||
multimatch@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz"
|
||||
@@ -14169,18 +13870,6 @@ react@^18.2.0:
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
reactflow@^11.11.2:
|
||||
version "11.11.2"
|
||||
resolved "https://registry.yarnpkg.com/reactflow/-/reactflow-11.11.2.tgz#4968866a9372e6004ad1e424a2141996f0ba769a"
|
||||
integrity sha512-o1fT3stSdhzW+SedCGNSmEvZvULZygZIMLyW67NcWNZrgwx1wuJfzLg5fuQ0Nzf389wItumZX/zP3zdaPX7lEw==
|
||||
dependencies:
|
||||
"@reactflow/background" "11.3.12"
|
||||
"@reactflow/controls" "11.2.12"
|
||||
"@reactflow/core" "11.11.2"
|
||||
"@reactflow/minimap" "11.7.12"
|
||||
"@reactflow/node-resizer" "2.2.12"
|
||||
"@reactflow/node-toolbar" "1.3.12"
|
||||
|
||||
read-cmd-shim@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz"
|
||||
@@ -15946,6 +15635,11 @@ tinyspy@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.0.tgz#9dc04b072746520b432f77ea2c2d17933de5d6ce"
|
||||
integrity sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==
|
||||
|
||||
tlds@^1.234.0:
|
||||
version "1.252.0"
|
||||
resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.252.0.tgz#71d9617f4ef4cc7347843bee72428e71b8b0f419"
|
||||
integrity sha512-GA16+8HXvqtfEnw/DTcwB0UU354QE1n3+wh08oFjr6Znl7ZLAeUgYzCcK+/CCrOyE0vnHR8/pu3XXG3vDijXpQ==
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz"
|
||||
@@ -16195,6 +15889,13 @@ uid-number@0.0.6:
|
||||
resolved "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz"
|
||||
integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=
|
||||
|
||||
uint8arrays@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.0.0.tgz#260869efb8422418b6f04e3fac73a3908175c63b"
|
||||
integrity sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==
|
||||
dependencies:
|
||||
multiformats "^9.4.2"
|
||||
|
||||
umask@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz"
|
||||
@@ -16349,11 +16050,6 @@ url-parse-lax@^3.0.0:
|
||||
dependencies:
|
||||
prepend-http "^2.0.0"
|
||||
|
||||
use-sync-external-store@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
@@ -17326,9 +17022,7 @@ zen-observable@0.8.15:
|
||||
resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz"
|
||||
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
|
||||
|
||||
zustand@^4.4.1:
|
||||
version "4.5.2"
|
||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848"
|
||||
integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==
|
||||
dependencies:
|
||||
use-sync-external-store "1.2.0"
|
||||
zod@^3.21.4:
|
||||
version "3.23.8"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
|
||||
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
|
||||
|
Reference in New Issue
Block a user