Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge: update branch with latest dev #5934

Merged
merged 29 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c16337d
fix(centralServer): Handle request access without project code
alexd-bes Sep 17, 2024
a8f97ea
fix(tupaiaWeb): Fix button styling
alexd-bes Sep 17, 2024
afacbdf
fix(centralServer): Disable automatic cell conversion
hrazasalman Sep 18, 2024
88f89dd
fix(lesmis): Fix blank dashboard
hrazasalman Sep 18, 2024
22ce0a5
fix(lesmis): fix blank dashboard
hrazasalman Sep 18, 2024
40444a4
fix project detail loader
hrazasalman Sep 19, 2024
b8ff7ed
fix(adminPanel): Fix colours in admin panel filter tables
alexd-bes Sep 20, 2024
876e996
fix(adminPanel): Fix import modal in viz builder
alexd-bes Sep 20, 2024
4a737f4
fix(adminPanel): Fix entity type for measure level
alexd-bes Sep 20, 2024
abfda67
fix(datatrakWeb): Fix report survey filtering
alexd-bes Sep 20, 2024
9c6d757
fix(datatrakWeb): Fix changing search value
alexd-bes Sep 20, 2024
798e313
Update buildDeployablePackages.sh
tcaiger Sep 20, 2024
01a911a
Merge pull request #5907 from beyondessential/release-2024-38
hrazasalman Sep 22, 2024
e7ab998
Merge pull request #5915 from beyondessential/merge-release-2024-38
hrazasalman Sep 22, 2024
5c06247
feat(tupaiaWeb): RN-1413: Enable projects search by country (#5890)
alexd-bes Sep 25, 2024
3c72db9
feat(tupaiaWeb): RN-1304: Date offsets for year granularities (#5695)
alexd-bes Sep 26, 2024
5293c2a
feat(adminPanel): RN-1433: Allow archiving of survey responses (#5903)
alexd-bes Sep 26, 2024
1026e43
fix(datatrakWeb): RN-1483: Fix issue with code gen replacing saved va…
alexd-bes Sep 27, 2024
eac9381
tweak(datatrakWeb): RN-1429: Hide Waka on mobile Datatrak Web (#5914)
alexd-bes Sep 29, 2024
b7bd762
tweak(config): Add support for hot reloading on internal deps changes…
alexd-bes Sep 29, 2024
21d1e43
tweak(datatrakWeb): RN-1426: Shift activity feed upwards when less th…
alexd-bes Sep 29, 2024
db4bac2
tweak(tupaiaWeb): RN-1445: Update request access flow (#5901)
alexd-bes Sep 29, 2024
ccac2f9
fix(tests): Fix broken timezone tests after DST changes (#5927)
alexd-bes Sep 29, 2024
33a2dfe
fix(datatrakWeb): RN-1484: Fix autocomplete question not sticking (#5…
alexd-bes Sep 29, 2024
8c56499
fix(datatrakWeb): RN-1454: Don't show all entities when no value in r…
alexd-bes Sep 29, 2024
d02206f
tweak(adminPanel): RN-1456: Allow export of archived survey responses…
alexd-bes Sep 30, 2024
d046bf8
fix(adminPanel): RN-1397: Filtering by sort order result inconsistenc…
hrazasalman Sep 30, 2024
64356c1
tweak(adminPanel): RN-1427: Remove .CSV from supported file types (#5…
hrazasalman Sep 30, 2024
91fb98d
fix(adminPanel): RN-1396: Entity import wipes attributes if attribute…
hrazasalman Sep 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ The [Tupaia Contributing Guidelines](/.github/CONTRIBUTING.md) and [BES Contribu

It is set up using [Yarn workspaces](https://yarnpkg.com/features/workspaces), meaning any command you would normally run inside a package can be run from the root directory using `yarn workspace @tupaia/package-name command`. For example, `yarn workspace @tupaia/central-server start-dev`.

If you want to watch internal dependencies while running a server, run `yarn workspace @tupaia/package-name start-dev -i`. The `-i` command will listen to changes in the internal dependencies' `dist` folders and restart on changes.
You can also run `build-watch` on these internal dependencies to watch changes and rebuild the package on change. This, combined with `-i` on the server start script will mean anytime you change something in your chosen package, the servers will restart. For example, you could run `yarn workspace @tupaia/central-server start-dev` and also `yarn workspace @tupaia/utils build-watch` which would mean the `central-server` would restart anytime you make a change in `utils`. By default, `central-server`, `datatrak-web-server`, and `tupaia-web-server` have `-i` enabled, for convenience.

Use the `start-stack` command to start all servers needed to run a stack. Available for `admin-panel`, `datatrak`, `lesmis`, `psss` and `tupaia-web`. For example, `yarn start-stack tupaia-web`.

> [!TIP]
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
"test-all": "node ./scripts/node/testAll --silent",
"validate": "./scripts/bash/validate.sh",
"package:build:ts": "cd $INIT_CWD && tsc -p tsconfig-build.json",
"package:build:ts-watch": "cd $INIT_CWD && tsc -p tsconfig-build.json --watch",
"package:build:js": "cd $INIT_CWD && babel src --out-dir dist --source-maps --config-file \"../../babel.config.json\" --copy-files --no-copy-ignored --ignore \"**/__tests__\",\"**/__mocks__\"",
"package:build:js-watch": "cd $INIT_CWD && babel src --out-dir dist --source-maps --config-file \"../../babel.config.json\" --copy-files --no-copy-ignored --ignore \"**/__tests__\",\"**/__mocks__\" --watch",
"package:build:types": "cd $INIT_CWD && tsc",
"package:build:vite": "cd $INIT_CWD && vite build --config \"../../vite.config.js\"",
"package:build:lib": "cd $INIT_CWD && babel src --out-dir lib --source-maps --config-file \"../../babel.config.json\" --copy-files --no-copy-ignored --ignore \"**/__tests__\",\"**/__mocks__\"",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Tupaia
* Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd
*/

import Typography from '@material-ui/core/Typography';
import PropTypes from 'prop-types';
import React, { useCallback, useState } from 'react';
import styled from 'styled-components';

import {
SmallAlert,
Button,
OutlinedButton,
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
FileUploadField,
LoadingContainer,
} from '@tupaia/ui-components';

const STATUS = {
IDLE: 'idle',
LOADING: 'loading',
SUCCESS: 'success',
ERROR: 'error',
};

const Content = styled(DialogContent)`
text-align: left;
min-height: 220px;
`;

const Heading = styled(Typography)`
margin-bottom: 18px;
`;

export const ImportModal = ({
isOpen,
title,
subtitle,
actionText,
loadingText,
loadingHeading,
showLoadingContainer,
onSubmit,
onClose,
}) => {
const [status, setStatus] = useState(STATUS.IDLE);
const [errorMessage, setErrorMessage] = useState(null);
const [successMessage, setSuccessMessage] = useState(null);
const [file, setFile] = useState(null);

const handleSubmit = async event => {
event.preventDefault();
setErrorMessage(null);
setStatus(STATUS.LOADING);

try {
const { message } = await onSubmit(file);
if (showLoadingContainer && message) {
setStatus(STATUS.SUCCESS);
setSuccessMessage(message);
} else {
handleClose();
}
} catch (error) {
setStatus(STATUS.ERROR);
setErrorMessage(error.message);
}
};

const handleClose = async () => {
onClose();

setStatus(STATUS.IDLE);
setErrorMessage(null);
setSuccessMessage(null);
setFile(null);
};

const handleDismiss = () => {
setStatus(STATUS.IDLE);
setErrorMessage(null);
setSuccessMessage(null);
// Deselect file when dismissing an error, this avoids an error when editing selected files
// @see https://github.com/beyondessential/tupaia-backlog/issues/1211
setFile(null);
};

const ContentContainer = showLoadingContainer
? ({ children }) => (
<LoadingContainer heading={loadingHeading} isLoading={status === STATUS.LOADING}>
{children}
</LoadingContainer>
)
: React.Fragment;

const renderContent = useCallback(() => {
switch (status) {
case STATUS.SUCCESS:
return <p>{successMessage}</p>;
case STATUS.ERROR:
return (
<>
<Heading variant="h6">An error has occurred.</Heading>
<SmallAlert severity="error" variant="standard">
{errorMessage}
</SmallAlert>
</>
);
default:
return (
<>
<p>{subtitle}</p>
<form>
<FileUploadField onChange={files => setFile(files[0])} name="file-upload" />
</form>
</>
);
}
}, [status, successMessage, errorMessage, subtitle]);

const renderButtons = useCallback(() => {
switch (status) {
case STATUS.SUCCESS:
return <Button onClick={handleClose}>Done</Button>;
case STATUS.ERROR:
return (
<>
<OutlinedButton onClick={handleDismiss}>Dismiss</OutlinedButton>
<Button disabled>{actionText}</Button>
</>
);
default:
return (
<>
<Button onClick={handleClose} variant="outlined">
Cancel
</Button>
<Button
type="submit"
disabled={!file}
isLoading={status === STATUS.LOADING}
loadingText={loadingText}
onClick={handleSubmit}
>
{actionText}
</Button>
</>
);
}
}, [status, file, handleDismiss, handleClose, handleSubmit]);

return (
<Dialog onClose={handleClose} open={isOpen}>
<DialogHeader
onClose={handleClose}
title={errorMessage ? 'Error' : title}
color={errorMessage ? 'error' : 'textPrimary'}
/>
<ContentContainer>
<Content>{renderContent()}</Content>
</ContentContainer>
<DialogFooter>{renderButtons()}</DialogFooter>
</Dialog>
);
};

ImportModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
title: PropTypes.string,
subtitle: PropTypes.string,
actionText: PropTypes.string,
loadingText: PropTypes.string,
loadingHeading: PropTypes.string,
showLoadingContainer: PropTypes.bool,
onSubmit: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};

ImportModal.defaultProps = {
title: 'Import',
subtitle: '',
actionText: 'Import',
loadingText: 'Importing',
loadingHeading: 'Importing data',
showLoadingContainer: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useUploadTestData } from '../../api';
import { ProjectField } from './ProjectField';
import { LocationField } from './LocationField';
import { DateRangeField } from './DateRangeField';
import { ImportModal } from '../../../importExport';
import { ImportModal } from './ImportModal';

const Container = styled(FlexSpaceBetween)`
padding: 24px 0;
Expand Down Expand Up @@ -58,6 +58,7 @@ const UploadDataModal = ({ isOpen, onSubmit, onClose }) => (
actionText="Upload"
loadingText="Uploading"
showLoadingContainer={false}
hasCustomButton={true}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useApiContext } from '../../utilities/ApiProvider';

export const useEditSurveyResponse = (surveyResponseId, updatedSurveyResponse) => {
export const useEditSurveyResponse = (surveyResponseId, updatedSurveyResponse, onSuccess) => {
const queryClient = useQueryClient();
const api = useApiContext();
return useMutation(
Expand All @@ -19,7 +19,10 @@ export const useEditSurveyResponse = (surveyResponseId, updatedSurveyResponse) =
onSuccess: async () => {
// invalidate the survey response data
await queryClient.invalidateQueries(['surveyResubmitData', surveyResponseId]);
return 'completed';
if (onSuccess) {
onSuccess();
}
return true;
},
},
);
Expand Down
29 changes: 29 additions & 0 deletions packages/admin-panel/src/icons/ArchiveIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Tupaia
* Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd
*/
import React from 'react';
import { SvgIcon } from '@material-ui/core';

export const ArchiveIcon = props => {
return (
<SvgIcon
{...props}
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
id="Icon"
d="M15.1875 5.625L14.7184 13.5991C14.666 14.491 13.9273 15.1875 13.0338 15.1875H4.96615C4.07266 15.1875 3.33403 14.491 3.28156 13.5991L2.8125 5.625M7.49982 8.4375H10.4998M2.53125 5.625H15.4688C15.9347 5.625 16.3125 5.24724 16.3125 4.78125V3.65625C16.3125 3.19026 15.9347 2.8125 15.4688 2.8125H2.53125C2.06526 2.8125 1.6875 3.19026 1.6875 3.65625V4.78125C1.6875 5.24724 2.06526 5.625 2.53125 5.625Z"
stroke="#328DE5"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
fill="none"
/>
</SvgIcon>
);
};
1 change: 1 addition & 0 deletions packages/admin-panel/src/icons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { VizIcon } from './VizIcon';
export { ImportIcon } from './ImportIcon';
export { ExportIcon } from './ExportIcon';
export { CaretLeftIcon } from './CaretLeftIcon';
export { ArchiveIcon } from './ArchiveIcon';
6 changes: 6 additions & 0 deletions packages/admin-panel/src/importExport/ExportModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const ExportModal = React.memo(
exportButtonText,
cancelButtonText,
isExportingMessage,
onCloseModal,
}) => {
const api = useApiContext();
const [status, setStatus] = useState(STATUS.IDLE);
Expand All @@ -44,6 +45,9 @@ export const ExportModal = React.memo(
setStatus(STATUS.IDLE);
setError(null);
setIsOpen(false);
if (onCloseModal) {
onCloseModal();
}
};

const handleSubmit = async event => {
Expand Down Expand Up @@ -152,6 +156,7 @@ ExportModal.propTypes = {
exportButtonText: PropTypes.string,
cancelButtonText: PropTypes.string,
isExportingMessage: PropTypes.string,
onCloseModal: PropTypes.func,
};

ExportModal.defaultProps = {
Expand All @@ -162,4 +167,5 @@ ExportModal.defaultProps = {
isExportingMessage:
'Export is taking a while, and will continue in the background. You will be emailed the exported file when the process completes.',
values: {},
onCloseModal: null,
};
1 change: 1 addition & 0 deletions packages/admin-panel/src/importExport/ImportModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export const ImportModalComponent = React.memo(
onChange={newFiles => setFiles(newFiles ?? [])}
name="file-upload"
multiple={actionConfig.multiple}
accept={actionConfig.accept}
/>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { stripTimezoneFromDate } from '@tupaia/utils';
import { ReduxAutocomplete } from '../autocomplete';
import { ExportModal } from './ExportModal';
import { EntityOptionLabel } from '../widgets';
import { Checkbox, FormControlLabel } from '@material-ui/core';

const MODES = {
COUNTRY: { value: 'country', formInput: 'countryCode' },
Expand Down Expand Up @@ -40,8 +41,20 @@ export const SurveyResponsesExportModal = () => {
}));
};

const clearValues = () => {
setValues({});
onChangeMode(MODES.COUNTRY.value);
setCountryCode(undefined);
setEntityIds(undefined);
};

return (
<ExportModal title="Download survey responses" values={values} exportEndpoint="surveyResponses">
<ExportModal
title="Download survey responses"
values={values}
exportEndpoint="surveyResponses"
onCloseModal={clearValues}
>
<ReduxAutocomplete
label="Surveys to include"
helperText="Please enter the names of the surveys to be exported."
Expand All @@ -54,7 +67,7 @@ export const SurveyResponsesExportModal = () => {
/>
<RadioGroup
name="survey responses mode"
label="Mode"
label="Level"
onChange={event => onChangeMode(event.currentTarget.value)}
options={[
{
Expand Down Expand Up @@ -126,6 +139,17 @@ export const SurveyResponsesExportModal = () => {
}
}}
/>
<FormControlLabel
control={
<Checkbox
checked={values.includeArchived}
onChange={event => handleValueChange('includeArchived', event.target.checked)}
name="include-archived"
color="primary"
/>
}
label="Include archived survey responses"
/>
</ExportModal>
);
};
4 changes: 4 additions & 0 deletions packages/admin-panel/src/pages/StrivePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const importConfig = {
title: 'Import lab results or vector data',
actionConfig: {
importEndpoint: 'striveLabResults',
accept: {
'application/vnd.ms-excel': ['.xls'],
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
},
},
};

Expand Down
Loading
Loading