Skip to content

Commit

Permalink
Merge pull request #1588 from glific/feature/flow-lock
Browse files Browse the repository at this point in the history
Added functionality for Locking flows while editing
  • Loading branch information
mdshamoon authored Aug 16, 2021
2 parents 28b1d87 + 8bb4115 commit 35d05f9
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 21 deletions.
32 changes: 32 additions & 0 deletions src/components/floweditor/FlowEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getFlowWithoutKeyword,
getOrganisationServicesQuery,
publishFlow,
getFreeFlow,
} from 'mocks/Flow';
import { conversationQuery } from 'mocks/Chat';
import {
Expand All @@ -26,6 +27,8 @@ const mocks = [
simulatorGetQuery,
publishFlow,
getOrganisationServicesQuery,
getFreeFlow,
getFreeFlow,
];

const activeFlowMocks = [...mocks, getActiveFlow];
Expand Down Expand Up @@ -94,6 +97,35 @@ test('click on preview button should open simulator', async () => {
});
});

test('check if someone else is using a flow', async () => {

// onload is not defined for script element in jest so we need to trigger it manually
const mockCreateElement = document.createElement.bind(document);
let scriptElements: any = [];
document.createElement = function (tags: any, options) {
if (tags === 'script') {
const mockScriptElement = mockCreateElement('script');
scriptElements.push(mockScriptElement);
return mockScriptElement;
} else return mockCreateElement(tags, options);
};

const { getByText } = render(defaultWrapper);
await waitFor(() => {
getByText('Loading...');
});

await waitFor(() => {
scriptElements[1].onload();
});

await waitFor(() => {
expect(getByText('The flow is currently being edited by someone else.')).toBeInTheDocument();
});

fireEvent.click(getByText('Okay'));
});

test('publish flow which has error', async () => {
const { getByTestId } = render(defaultWrapper);

Expand Down
73 changes: 54 additions & 19 deletions src/components/floweditor/FlowEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Simulator } from 'components/simulator/Simulator';
import { DialogBox } from 'components/UI/DialogBox/DialogBox';
import { setNotification } from 'common/notification';
import { PUBLISH_FLOW } from 'graphql/mutations/Flow';
import { EXPORT_FLOW, GET_FLOW_DETAILS } from 'graphql/queries/Flow';
import { EXPORT_FLOW, GET_FLOW_DETAILS, GET_FREE_FLOW } from 'graphql/queries/Flow';
import { setAuthHeaders } from 'services/AuthService';
import { GET_ORGANIZATION_SERVICES } from 'graphql/queries/Organization';
import { Loading } from 'components/UI/Layout/Loading/Loading';
Expand Down Expand Up @@ -167,6 +167,7 @@ export const FlowEditor = (props: FlowEditorProps) => {
const [flowValidation, setFlowValidation] = useState<any>();
const [IsError, setIsError] = useState(false);
const [flowKeyword, setFlowKeyword] = useState('');
const [currentEditDialogBox, setCurrentEditDialogBox] = useState(false);

let modal = null;
let dialog = null;
Expand All @@ -187,6 +188,17 @@ export const FlowEditor = (props: FlowEditorProps) => {
},
});

const [getFreeFlow] = useLazyQuery(GET_FREE_FLOW, {
fetchPolicy: 'network-only',
onCompleted: ({ flowGet }) => {
if (flowGet) {
getOrganizationServices();
} else {
setCurrentEditDialogBox(true);
}
},
});

const [exportFlowMutation] = useLazyQuery(EXPORT_FLOW, {
fetchPolicy: 'network-only',
onCompleted: async ({ exportFlow }) => {
Expand Down Expand Up @@ -266,26 +278,34 @@ export const FlowEditor = (props: FlowEditorProps) => {
}, [flowName]);

useEffect(() => {
const { fetch, xmlSend } = setAuthHeaders();
const files = loadfiles(() => {
getOrganizationServices();
});
if (flowId) {
const { fetch, xmlSend } = setAuthHeaders();
const files = loadfiles(() => {
getFreeFlow({ variables: { id: flowId } });
});

return () => {
Object.keys(files).forEach((node: any) => {
if (files[node]) {
document.body.removeChild(files[node]);
// when switching tabs we need to check if the flow is still active for the user
window.onfocus = () => {
getFreeFlow({ variables: { id: flowId } });
};

return () => {
Object.keys(files).forEach((node: any) => {
if (files[node]) {
document.body.removeChild(files[node]);
}
});
// clearing all timeouts when component unmounts
const highestTimeoutId: any = setTimeout(() => {});
for (let timeoutId = 0; timeoutId < highestTimeoutId; timeoutId += 1) {
clearTimeout(timeoutId);
}
});
// clearing all timeouts when component unmounts
const highestTimeoutId: any = setTimeout(() => {});
for (let timeoutId = 0; timeoutId < highestTimeoutId; timeoutId += 1) {
clearTimeout(timeoutId);
}
XMLHttpRequest.prototype.send = xmlSend;
window.fetch = fetch;
};
}, []);
XMLHttpRequest.prototype.send = xmlSend;
window.fetch = fetch;
};
}
return () => {};
}, [flowId]);

const handlePublishFlow = () => {
publishFlow({ variables: { uuid: props.match.params.uuid } });
Expand All @@ -311,6 +331,21 @@ export const FlowEditor = (props: FlowEditorProps) => {
</div>
);

if (currentEditDialogBox) {
dialog = (
<DialogBox
title="The flow is currently being edited by someone else."
alignButtons="center"
skipCancel
buttonOk="Okay"
handleOk={() => {
setConfirmedNavigation(true);
history.push('/flow');
}}
/>
);
}

if (publishDialog) {
dialog = (
<DialogBox
Expand Down
2 changes: 2 additions & 0 deletions src/containers/Flow/FlowList/FlowList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
getFlowQuery,
importFlow,
exportFlow,
releaseFlow,
} from 'mocks/Flow';
import testJSON from 'mocks/ImportFlow.json';
import { setUserSession } from 'services/AuthService';
Expand All @@ -24,6 +25,7 @@ const mocks = [
getFlowCountNewQuery,
getFlowQuery,
importFlow,
releaseFlow,
exportFlow,
];

Expand Down
16 changes: 14 additions & 2 deletions src/containers/Flow/FlowList/FlowList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useRef } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
import moment from 'moment';
import { useTranslation } from 'react-i18next';
Expand All @@ -11,7 +11,13 @@ import { ReactComponent as ImportIcon } from 'assets/images/icons/Flow/Import.sv
import { ReactComponent as ConfigureIcon } from 'assets/images/icons/Configure/UnselectedDark.svg';
import { ReactComponent as ContactVariable } from 'assets/images/icons/ContactVariable.svg';
import { ReactComponent as WebhookLogsIcon } from 'assets/images/icons/Webhook/WebhookLight.svg';
import { FILTER_FLOW, GET_FLOWS, GET_FLOW_COUNT, EXPORT_FLOW } from 'graphql/queries/Flow';
import {
FILTER_FLOW,
GET_FLOWS,
GET_FLOW_COUNT,
EXPORT_FLOW,
RELEASE_FLOW,
} from 'graphql/queries/Flow';
import { DELETE_FLOW, IMPORT_FLOW } from 'graphql/mutations/Flow';
import { List } from 'containers/List/List';
import Loading from 'components/UI/Layout/Loading/Loading';
Expand Down Expand Up @@ -68,6 +74,12 @@ export const FlowList: React.SFC<FlowListProps> = () => {
const [flowName, setFlowName] = useState('');
const [importing, setImporting] = useState(false);

const [releaseFlow] = useLazyQuery(RELEASE_FLOW);

useEffect(() => {
releaseFlow();
}, []);

const [importFlow] = useMutation(IMPORT_FLOW, {
onCompleted: (result: any) => {
const { success } = result.importFlow;
Expand Down
18 changes: 18 additions & 0 deletions src/graphql/queries/Flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,21 @@ export const EXPORT_FLOW = gql`
}
}
`;

export const GET_FREE_FLOW = gql`
query flowGet($id: ID!) {
flowGet(id: $id) {
id
uuid
}
}
`;

export const RELEASE_FLOW = gql`
query flowRelease {
flowRelease {
id
uuid
}
}
`;
28 changes: 28 additions & 0 deletions src/mocks/Flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
GET_FLOW_DETAILS,
FILTER_FLOW,
EXPORT_FLOW,
RELEASE_FLOW,
GET_FREE_FLOW,
} from 'graphql/queries/Flow';
import {
ADD_FLOW_TO_CONTACT,
Expand Down Expand Up @@ -282,3 +284,29 @@ export const exportFlow = {
},
},
};

export const releaseFlow = {
request: {
query: RELEASE_FLOW,
},
result: {
data: {
flowRelease: {
id: '1',
uuid: '3fa22108-f464-41e5-81d9-d8a298854429',
},
},
},
};

export const getFreeFlow = {
request: {
query: GET_FREE_FLOW,
variables: { id: '1' },
},
result: {
data: {
flowGet: null,
},
},
};

0 comments on commit 35d05f9

Please sign in to comment.