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

Release 2023 17 #4487

Merged
merged 19 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
13c803c
WAITP-1145 create commands for reloading on dev (#4420)
alexd-bes Apr 4, 2023
cf1fc03
Merge pull request #4448 from beyondessential/master
biaoli0 Apr 13, 2023
09a25c6
WAITP-1146 Delete report alongside map overlay (#4444)
EMcQ-BES Apr 13, 2023
df0baa3
[no-issue]: Update the test database schema file (#4450)
rohan-bes Apr 14, 2023
c80737b
RN-864: Add 'Delete' button to Data-Tables page in the Admin Panel (#…
rohan-bes Apr 17, 2023
71d6174
RN-832: Raw data exports treat numbers as text (#4424)
chris-pollard Apr 17, 2023
aeda9fe
RN-828: Fix error in Admin Panel when viewing User Permissions (#4404)
rohan-bes Apr 17, 2023
43ef502
RN-855: Allow using non-explore enitites for organisationUnit param d…
rohan-bes Apr 17, 2023
859935e
Merge branch 'master' into dev
rohan-bes Apr 18, 2023
b82abcb
Merge pull request #4472 from beyondessential/resolve-master-to-dev
rohan-bes Apr 18, 2023
db2c22c
WAITP-1144 verify email view also loads explore (#4428)
alexd-bes Apr 19, 2023
6e4cfb4
Waitp 1121 loading indicator not visible (#4422)
alexd-bes Apr 19, 2023
765bf9d
WAITM-1120: Bar chart alignment is not as expected (#4416)
alexd-bes Apr 19, 2023
c26fd6c
WAITP-1123 Fix table sorting on columns with dates (#4417)
alexd-bes Apr 19, 2023
ec43d39
WAITP-1186 add example.http to dhis-api (#4480)
alexd-bes Apr 21, 2023
8bbc84c
Update watchAttemptTokenLogin.js (#4449)
tcaiger Apr 21, 2023
46c250d
WAITP-1176 Re-enable bulk access request editor (#4467)
EMcQ-BES Apr 23, 2023
074e553
WAITP-1122: Update users import (#4459)
tcaiger Apr 23, 2023
f524151
Avoid parsing percentage string (#4496)
chris-pollard Apr 27, 2023
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
7 changes: 5 additions & 2 deletions packages/admin-panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
"lint:fix": "yarn lint --fix",
"start": "yarn package:start:react-scripts",
"start-dev": "yarn start",
"start-fullstack": "npm-run-all -c -l -p start-central-server start-entity-server start-report-server start-admin-panel-server start-dev",
"start-fullstack": "npm-run-all -c -l -p start-servers start-frontend",
"start-central-server": "yarn workspace @tupaia/central-server start-dev",
"start-entity-server": "yarn workspace @tupaia/entity-server start-dev",
"start-report-server": "yarn workspace @tupaia/report-server start-dev",
"start-admin-panel-server": "yarn workspace @tupaia/admin-panel-server start-dev",
"test": "echo No tests"
"test": "echo No tests",
"start-ui-components": "yarn workspace @tupaia/ui-components build-dev:watch",
"start-frontend": "npm-run-all -c -l -p start-ui-components start-dev",
"start-servers": "npm-run-all -c -l -p start-central-server start-entity-server start-report-server start-admin-panel-server"
},
"browserslist": [
"defaults"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export * from './useUser';
export * from './useDashboardVisualisation';
export * from './useMapOverlays';
export * from './useCountries';
export * from './useEntities';
export * from './useSearchPermissionGroups';
export * from './useSearchTransformSchemas';
25 changes: 25 additions & 0 deletions packages/admin-panel/src/VizBuilderApp/api/queries/useEntities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Tupaia
* Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd
*/
import { useQuery } from 'react-query';
import { stringifyQuery } from '@tupaia/utils';
import { get } from '../api';
import { DEFAULT_REACT_QUERY_OPTIONS } from '../constants';

export const useEntities = search =>
useQuery(
['entities', search],
async () => {
const endpoint = stringifyQuery(undefined, `entities`, {
columns: JSON.stringify(['name', 'code']),
filter: JSON.stringify({
name: { comparator: 'ilike', comparisonValue: `%${search}%`, castAs: 'text' },
}),
});
return get(endpoint);
},
{
...DEFAULT_REACT_QUERY_OPTIONS,
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const PreviewFilters = ({ params, onChange, runtimeParams }) => {
<Grid key={p.id}>
<FilterComponent
{...p}
runtimeParams={runtimeParams} // organisationUnitCodes parameter needs hierarachy as input
value={runtimeParams[p.name]}
onChange={newValue => {
onChange(p.name, newValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,22 @@
* Copyright (c) 2017 - 2023 Beyond Essential Systems Pty Ltd
*/

import React, { useEffect, useState } from 'react';
import React, { useState } from 'react';

import PropTypes from 'prop-types';

import { ParameterType } from '../../editing';
import { useLocations } from '../../../../VizBuilderApp/api';
import { useEntities } from '../../../../VizBuilderApp/api';
import { Autocomplete } from '../../../../autocomplete';
import { useDebounce } from '../../../../utilities';
import { getArrayFieldValue } from './utils';

export const OrganisationUnitCodesField = ({ name, onChange, runtimeParams }) => {
const { hierarchy = 'explore' } = runtimeParams;
export const OrganisationUnitCodesField = ({ name, onChange }) => {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 100);
const [selectedOptions, setSelectedOptions] = useState([]); // [{code:"DL", name:"Demo Land"}]
const { data: locations = [], isLoading } = useLocations(hierarchy, searchTerm);
const limitedLocations = locations.slice(0, 20); // limit the options to 20 to stop the ui jamming

useEffect(() => {
setSelectedOptions([]);
onChange([]);
}, [hierarchy]); // hierarchy determines entity relation visibility
const { data: entities = [], isLoading } = useEntities(debouncedSearchTerm);
const limitedLocations = entities.slice(0, 20); // limit the options to 20 to stop the ui jamming

return (
<Autocomplete
Expand Down Expand Up @@ -50,9 +46,4 @@ export const OrganisationUnitCodesField = ({ name, onChange, runtimeParams }) =>
OrganisationUnitCodesField.propTypes = {
...ParameterType,
onChange: PropTypes.func.isRequired,
runtimeParams: PropTypes.object,
};

OrganisationUnitCodesField.defaultProps = {
runtimeParams: {},
};
6 changes: 6 additions & 0 deletions packages/admin-panel/src/editor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ export const openBulkEditModal = (
type: EDITOR_DATA_FETCH_SUCCESS,
recordData: response.body,
});
dispatch({
type: EDITOR_OPEN,
fields,
recordData: response.body,
endpoint: bulkUpdateEndpoint,
});
} catch (error) {
dispatch({
type: EDITOR_ERROR,
Expand Down
8 changes: 8 additions & 0 deletions packages/admin-panel/src/pages/resources/DataTablesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ const COLUMNS = [
},
},
},
{
Header: 'Delete',
source: 'id',
type: 'delete',
actionConfig: {
endpoint: DATA_TABLES_ENDPOINT,
},
},
];

const CREATE_CONFIG = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { hasBESAdminAccess, BES_ADMIN_PERMISSION_GROUP } from '../../permissions';
import {
getAdminPanelAllowedEntityIds,
getAdminPanelAllowedCountryIds,
getAdminPanelAllowedCountryCodes,
mergeFilter,
} from '../utilities';
Expand Down Expand Up @@ -76,7 +76,7 @@ export const createAccessRequestDBFilter = async (accessPolicy, models, criteria
// If we don't have BES Admin access, add a filter to the SQL query
const dbConditions = { ...criteria };
dbConditions['access_request.entity_id'] = mergeFilter(
await getAdminPanelAllowedEntityIds(accessPolicy, models),
await getAdminPanelAllowedCountryIds(accessPolicy, models),
dbConditions['access_request.entity_id'],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@

import { QUERY_CONJUNCTIONS } from '@tupaia/database';
import { hasBESAdminAccess } from '../../permissions';
import { getPermissionListWithWildcard } from '../utilities';

const { RAW } = QUERY_CONJUNCTIONS;

const getPermissionListWithWildcard = async accessPolicy => {
const userPermissionGroups = accessPolicy.getPermissionGroups();
return ['*', ...userPermissionGroups];
};

export const assertDataGroupGETPermissions = async (accessPolicy, models, dataGroupId) => {
if (await assertDataGroupPermissions(accessPolicy, models, dataGroupId, 'some')) {
return true;
Expand Down
26 changes: 0 additions & 26 deletions packages/central-server/src/apiV2/dataTables/CreateDataTables.js

This file was deleted.

4 changes: 2 additions & 2 deletions packages/central-server/src/apiV2/dataTables/GETDataTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export class GETDataTables extends GETHandler {
permissionsFilteredInternally = true;

async findSingleRecord(dataTableId, options) {
const dataGroupPermissionChecker = accessPolicy =>
const dataTablePermissionChecker = accessPolicy =>
assertDataTableGETPermissions(accessPolicy, this.models, dataTableId);
await this.assertPermissions(
assertAnyPermissions([assertBESAdminAccess, dataGroupPermissionChecker]),
assertAnyPermissions([assertBESAdminAccess, dataTablePermissionChecker]),
);

return super.findSingleRecord(dataTableId, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
*/

import { hasBESAdminAccess } from '../../permissions';

const getPermissionListWithWildcard = async accessPolicy => {
const userPermissionGroups = accessPolicy.getPermissionGroups();
return ['*', ...userPermissionGroups];
};
import { getPermissionListWithWildcard } from '../utilities';

export const assertDataTableGETPermissions = async (accessPolicy, models, dataTableId) => {
// User requires access to any permission group
Expand All @@ -18,16 +14,6 @@ export const assertDataTableGETPermissions = async (accessPolicy, models, dataTa
throw new Error('You do not have permission to view this data-table');
};

export const assertDataTableEditPermissions = async (accessPolicy, models, dataTableId) => {
// User requires access to all permission groups
if (await assertDataTablePermissions(accessPolicy, models, dataTableId, 'every')) {
return true;
}
throw new Error(
'You require access to all of a data-tables permission groups to perform this action',
);
};

const assertDataTablePermissions = async (accessPolicy, models, dataTableId, test) => {
const dataTable = await models.dataTable.findById(dataTableId);
if (!dataTable) {
Expand Down
1 change: 0 additions & 1 deletion packages/central-server/src/apiV2/dataTables/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
*/

export { GETDataTables } from './GETDataTables';
export { CreateDataTables } from './CreateDataTables';
5 changes: 4 additions & 1 deletion packages/central-server/src/apiV2/import/importUsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import {
ObjectValidator,
hasContent,
constructIsOneOf,
constructIsEmptyOr,
} from '@tupaia/utils';
import { hashAndSaltPassword } from '@tupaia/auth';
import { VerifiedEmail } from '@tupaia/types';
import { assertBESAdminAccess } from '../../permissions';

export async function importUsers(req, res) {
Expand Down Expand Up @@ -90,10 +92,11 @@ const FIELD_VALIDATORS = {
first_name: [hasContent],
last_name: [],
email: [hasContent],
gender: [hasContent, constructIsOneOf(['f', 'm'])],
gender: [constructIsEmptyOr(constructIsOneOf(['f', 'm', 'unknown']))],
employer: [hasContent],
position: [hasContent],
mobile_number: [],
password: [hasContent],
permission_group: [hasContent],
verified_email: [constructIsEmptyOr(constructIsOneOf(Object.values(VerifiedEmail)))],
};
5 changes: 3 additions & 2 deletions packages/central-server/src/apiV2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { GETClinics } from './GETClinics';
import { GETDisasters } from './GETDisasters';
import { GETDataElements, EditDataElements, DeleteDataElements } from './dataElements';
import { GETDataGroups, EditDataGroups, DeleteDataGroups } from './dataGroups';
import { CreateDataTables, GETDataTables } from './dataTables';
import { GETDataTables } from './dataTables';
import { GETFeedItems } from './GETFeedItems';
import { GETGeographicalAreas } from './GETGeographicalAreas';
import { GETSurveyGroups } from './GETSurveyGroups';
Expand Down Expand Up @@ -264,7 +264,7 @@ apiV2.post('/surveyResponses', catchAsyncErrors(surveyResponse));
apiV2.post('/countries', useRouteHandler(BESAdminCreateHandler));
apiV2.post('/dataElements', useRouteHandler(BESAdminCreateHandler));
apiV2.post('/dataGroups', useRouteHandler(BESAdminCreateHandler));
apiV2.post('/dataTables', useRouteHandler(CreateDataTables));
apiV2.post('/dataTables', useRouteHandler(BESAdminCreateHandler));
apiV2.post('/dashboards', useRouteHandler(CreateDashboard));
apiV2.post('/mapOverlayGroups', useRouteHandler(CreateMapOverlayGroups));
apiV2.post('/disasters', useRouteHandler(BESAdminCreateHandler));
Expand Down Expand Up @@ -330,6 +330,7 @@ apiV2.delete('/answers/:recordId', useRouteHandler(DeleteAnswers));
apiV2.delete('/surveyResponses/:parentRecordId/answers/:recordId', useRouteHandler(DeleteAnswers));
apiV2.delete('/dataElements/:recordId', useRouteHandler(DeleteDataElements));
apiV2.delete('/dataGroups/:recordId', useRouteHandler(DeleteDataGroups));
apiV2.delete('/dataTables/:recordId', useRouteHandler(BESAdminDeleteHandler));
apiV2.delete('/disasters/:recordId', useRouteHandler(BESAdminDeleteHandler));
apiV2.delete('/entities/:recordId', useRouteHandler(DeleteEntity));
apiV2.delete('/feedItems/:recordId', useRouteHandler(BESAdminDeleteHandler));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ export class DeleteMapOverlays extends DeleteHandler {
async assertUserHasAccess() {
await this.assertPermissions(assertBESAdminAccess);
}

async deleteRecord() {
const mapOverlay = await this.resourceModel.findById(this.recordId);
const reportModel = mapOverlay.legacy ? this.models.legacyReport : this.models.report;
await reportModel.delete({ code: mapOverlay.report_code });
return super.deleteRecord();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
BES_ADMIN_PERMISSION_GROUP,
TUPAIA_ADMIN_PANEL_PERMISSION_GROUP,
} from '../../permissions';
import { getAdminPanelAllowedEntityIds, getAdminPanelAllowedCountryCodes } from '../utilities';
import { getAdminPanelAllowedCountryIds, getAdminPanelAllowedCountryCodes } from '../utilities';

export const assertUserEntityPermissionPermissions = async (
accessPolicy,
Expand Down Expand Up @@ -78,7 +78,7 @@ export const createUserEntityPermissionDBFilter = async (accessPolicy, models, c
}
// If we don't have BES Admin access, add a filter to the SQL query
const dbConditions = {
'user_entity_permission.entity_id': await getAdminPanelAllowedEntityIds(accessPolicy, models),
'user_entity_permission.entity_id': await getAdminPanelAllowedCountryIds(accessPolicy, models),
...criteria,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ export const getAdminPanelAllowedCountryCodes = accessPolicy => {
};

/*
* Get a list of entity ids this user has tupaia admin panel access to, or throw an error if they have none
* Get a list of country ids this user has tupaia admin panel access to, or throw an error if they have none
*
* @param {AccessPolicy} accessPolicy
* @param {ModelRegistry} models
*
* @returns string[] The entity ids
*/

export const getAdminPanelAllowedEntityIds = async (accessPolicy, models) => {
export const getAdminPanelAllowedCountryIds = async (accessPolicy, models) => {
const accessibleCountryCodes = getAdminPanelAllowedCountryCodes(accessPolicy);
const entities = await models.entity.find({
country_code: accessibleCountryCodes,
code: accessibleCountryCodes,
});

return entities.map(e => e.id);
Expand Down
4 changes: 2 additions & 2 deletions packages/central-server/src/apiV2/utilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export {
} from './fetchCountriesByPermissionGroup';
export { fetchRequestingMeditrakDevice } from './fetchRequestingMeditrakDevice';
export {
getAdminPanelAllowedEntityIds,
getAdminPanelAllowedCountryIds,
getAdminPanelAllowedCountryCodes,
} from './getAdminPanelAllowedEntityIds';
} from './getAdminPanelAllowedCountries';
export { getArrayQueryParameter } from './getArrayQueryParameter';
export { getColumnsForMeditrakApp } from './getColumnsForMeditrakApp';
export { hasAccessToEntityForVisualisation } from './hasAccessToEntityForVisualisation';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ const DASHBOARD_ITEMS = [
config: { name: 'Modern Dashboard Item', type: 'view', viewType: 'singleValue' },
report_code: 'Modern_Report',
legacy: false,
permissionGroupIds: [],
},
{
id: generateTestId(),
code: 'Legacy_Dashboard_Item',
config: { name: 'Legacy Dashboard Item', type: 'chart', chartType: 'bar' },
report_code: 'Legacy_Report',
legacy: true,
permissionGroupIds: [],
},
{
id: generateTestId(),
Expand Down
2 changes: 1 addition & 1 deletion packages/database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"refresh-database": "node ./scripts/refreshDatabase.js",
"test": "yarn package:test:withdb --runInBand",
"test:coverage": "yarn test --coverage",
"update-test-data": "bash -c 'source .env && pg_dump -s -U $DB_USER -O $DB_NAME > src/__tests__/testData/testDataDump.sql && pg_dump -t migrations -c -U $DB_USER -O $DB_NAME >> src/__tests__/testData/testDataDump.sql'",
"update-test-data": "bash -c 'source .env && pg_dump -s -h $DB_URL -U $DB_USER -O $DB_NAME > src/__tests__/testData/testDataDump.sql && pg_dump -t migrations -c -h $DB_URL -U $DB_USER -O $DB_NAME >> src/__tests__/testData/testDataDump.sql'",
"setup-test-database": "DB_NAME=tupaia_test scripts/setupTestDatabase.sh",
"check-test-database-exists": "DB_NAME=tupaia_test scripts/checkTestDatabaseExists.sh"
},
Expand Down
Loading