Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianq committed Mar 2, 2021
2 parents 43549da + dc797d5 commit 6096623
Show file tree
Hide file tree
Showing 77 changed files with 3,400 additions and 195 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ User App is a Dhis2 Web Application that provides an easy and integrated way to

## Features

- Landing page: it displays a list of users with some attributes information. The list allows sorting by some fields (click the column header) and single/multiple selections. You can also filter by name, role, groups and see only users you can manage.
- Show details: it behaves as the regular show details in any Dhis2 instance. It shows a right side panel with some information about the user. This is also the action by default when clicking a row.
- Assign to organisation units: Implemented for single and multiple selections* allows setting Data capture and maintenance organisation units.
- Assign to organisation units output: Implemented for single and multiple selections* allows setting Data output and analysis organisation units.
- Assign roles: Implemented for single and multiple selections* allows assigning the roles to a user/s.
- Assign to groups: Implemented for single and multiple selections* allows assigning the user groups for a user/s.
- Shortcut to regular dhis2 user management app
- Replicate user: Implemented for single mode allows creating multiple users using a single users as starting point. Currently, two modes are available: 'From Template' and 'From table'.
- Landing page: it displays a list of users with some attributes information. The list allows sorting by some fields (click the column header) and single/multiple selections. You can also filter by name, role, groups and see only users you can manage.
- Show details: it behaves as the regular show details in any Dhis2 instance. It shows a right side panel with some information about the user. This is also the action by default when clicking a row.
- Assign to organisation units capture: Implemented for single and multiple selections\* allows setting Data capture and maintenance organisation units.
- Assign to organisation units output: Implemented for single and multiple selections\* allows setting Data output and analysis organisation units.
- Assign roles: Implemented for single and multiple selections\* allows assigning the roles to a user/s.
- Assign to groups: Implemented for single and multiple selections\* allows assigning the user groups for a user/s.
- Shortcut to regular dhis2 user management app
- Replicate user: Implemented for single mode allows creating multiple users using a single users as starting point. Currently, two modes are available: 'From Template' and 'From table'.

\*In single mode, it works as the regular Dhis2 vanilla feature. For multiple selections, the changes can be saved using one of two strategies: merge or replace. The merge strategy will add the selected entities (organisation units, roles, etc) to the current values each user had, no values will be removed. Replace on the other hand overwrites any previous values and keep only those selected in this dialog.

Expand Down
4 changes: 4 additions & 0 deletions css/font-awesome/css/font-awesome.min.css

Large diffs are not rendered by default.

Binary file added css/font-awesome/fonts/FontAwesome.otf
Binary file not shown.
Binary file added css/font-awesome/fonts/fontawesome-webfont.eot
Binary file not shown.
520 changes: 520 additions & 0 deletions css/font-awesome/fonts/fontawesome-webfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/font-awesome/fonts/fontawesome-webfont.ttf
Binary file not shown.
Binary file added css/font-awesome/fonts/fontawesome-webfont.woff
Binary file not shown.
Binary file added css/fonts/LiberationSans-Bold-webfont.eot
Binary file not shown.
154 changes: 154 additions & 0 deletions css/fonts/LiberationSans-Bold-webfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/fonts/LiberationSans-Bold-webfont.ttf
Binary file not shown.
Binary file added css/fonts/LiberationSans-Bold-webfont.woff
Binary file not shown.
Binary file added css/fonts/LiberationSans-Regular-webfont.eot
Binary file not shown.
262 changes: 262 additions & 0 deletions css/fonts/LiberationSans-Regular-webfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/fonts/LiberationSans-Regular-webfont.ttf
Binary file not shown.
Binary file added css/fonts/LiberationSans-Regular-webfont.woff
Binary file not shown.
Binary file added css/fonts/padauk-bold-webfont.eot
Binary file not shown.
134 changes: 134 additions & 0 deletions css/fonts/padauk-bold-webfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/fonts/padauk-bold-webfont.ttf
Binary file not shown.
Binary file added css/fonts/padauk-bold-webfont.woff
Binary file not shown.
Binary file added css/fonts/padauk-webfont.eot
Binary file not shown.
134 changes: 134 additions & 0 deletions css/fonts/padauk-webfont.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/fonts/padauk-webfont.ttf
Binary file not shown.
Binary file added css/fonts/padauk-webfont.woff
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
72 changes: 72 additions & 0 deletions css/fonts/roboto.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.eot');
src: local('Roboto Thin'), local('Roboto-Thin'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-100.svg#Roboto') format('svg');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.eot');
src: local('Roboto Light'), local('Roboto-Light'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-300.svg#Roboto') format('svg');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.eot');
src: local('Roboto'), local('Roboto-Regular'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-regular.svg#Roboto') format('svg');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.eot');
src: local('Roboto Medium'), local('Roboto-Medium'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-500.svg#Roboto') format('svg');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.eot');
src: local('Roboto Bold'), local('Roboto-Bold'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-700.svg#Roboto') format('svg');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
src: url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.eot');
src: local('Roboto Black'), local('Roboto-Black'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.eot?#iefix') format('embedded-opentype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.woff2') format('woff2'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.woff') format('woff'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.ttf') format('truetype'),
url('roboto-v15-latin-ext_latin/roboto-v15-latin-ext_latin-900.svg#Roboto') format('svg');
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
38 changes: 38 additions & 0 deletions css/material-design-icons/material-icons.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(MaterialIcons-Regular.eot); /* For IE6-8 */
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(MaterialIcons-Regular.woff2) format('woff2'),
url(MaterialIcons-Regular.woff) format('woff'),
url(MaterialIcons-Regular.ttf) format('truetype');
}

.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
width: 1em;
height: 1em;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;

/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;

/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;

/* Support for IE. */
font-feature-settings: 'liga';
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "d2-user-extended-app",
"version": "0.5.0",
"version": "0.6.0",
"description": "DHIS2 Extended User app",
"main": "src/index.html",
"license": "GPL-3.0",
Expand All @@ -17,7 +17,7 @@
"lint": "eslint src && eslint --env node,mocha --global expect,sinon --rule 'no-unused-expressions: 0' test && scss-lint",
"__prebuild": "npm test && npm run lint",
"build": "rm -rf build && webpack && npm run manifest",
"postbuild": "cp -rv app-config.json src/i18n includes icon.png app-favicon.ico node_modules/babel-polyfill/dist/polyfill.min.js node_modules/jquery/dist/jquery.min.js ./build/",
"postbuild": "cp -rv app-config.json src/i18n css includes icon.png app-favicon.ico node_modules/babel-polyfill/dist/polyfill.min.js node_modules/jquery/dist/jquery.min.js ./build/",
"build-webapp": "yarn build && rm -f User-Extended-App.zip && cd build && zip -r ../User-Extended-App.zip *",
"prettify": "prettier \"{src,scss}/**/*.{js,jsx,ts,tsx,json,css,scss}\" --write",
"validate": "npm ls",
Expand Down
6 changes: 4 additions & 2 deletions src/List/Filters.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ export default class Filters extends React.Component {
const inFilter = field => (_(field).isEmpty() ? null : ["in", field]);

return {
query: searchString,
...(showOnlyManagedUsers ? { canManage: "true" } : {}),
...(searchString ? { query: searchString } : {}),
filters: {
"userCredentials.disabled": showOnlyActiveUsers ? ["eq", false] : undefined,
"userCredentials.userRoles.id": inFilter(userRoles),
Expand Down Expand Up @@ -265,7 +265,9 @@ export default class Filters extends React.Component {
<div className="control-row">
<div className="user-management-control select-organisation-unit">
<OrgUnitsFilter
title={this.getTranslation("filter_by_organisation_units")}
title={this.getTranslation(
"filter_by_organisation_units_capture"
)}
selected={this.state.orgUnits}
onChange={this.setFilter("orgUnits")}
styles={styles.filterStyles}
Expand Down
8 changes: 5 additions & 3 deletions src/List/List.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,15 +308,18 @@ const List = React.createClass({

_orgUnitAssignmentSaved() {
snackActions.show({
message: "organisation_unit_assignment_saved",
message: "organisation_unit_capture_assignment_saved",
action: "ok",
translate: true,
});
},

_orgUnitAssignmentError(errorMessage) {
log.error(errorMessage);
snackActions.show({ message: "organisation_unit_assignment_save_error", translate: true });
snackActions.show({
message: "organisation_unit_capture_assignment_save_error",
translate: true,
});
},

filterList({ page = 1 } = {}) {
Expand Down Expand Up @@ -425,7 +428,6 @@ const List = React.createClass({

async _importUsers(users) {
const response = await saveUsers(this.context.d2, users);

if (response.success) {
const message = this.getTranslation("import_successful", { n: users.length });
snackActions.show({ message });
Expand Down
4 changes: 2 additions & 2 deletions src/List/context.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ const contextActions = [
allowed: checkAccess(["update"]),
},
{
name: "assignToOrgUnits",
name: "assignToOrgUnitsCapture",
multiple: true,
icon: "business",
onClick: users => assignToOrgUnits(users, "organisationUnits", "assignToOrgUnits"),
onClick: users => assignToOrgUnits(users, "organisationUnits", "assignToOrgUnitsCapture"),
allowed: checkAccess(["update"]),
},
{
Expand Down
4 changes: 2 additions & 2 deletions src/components/MultipleSelector.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class MultipleSelector extends React.Component {
titleByField = {
userGroups: "assignGroups",
userRoles: "assignRoles",
organisationUnits: "assignToOrgUnits",
organisationUnitsCapture: "assignToOrgUnitsCapture",
dataViewOrganisationUnits: "assignToOrgUnitsOutput",
};

Expand All @@ -102,7 +102,7 @@ class MultipleSelector extends React.Component {
onChange={this.onMultiSelectChange}
/>
);
case "organisationUnits":
case "organisationUnitsCapture":
case "dataViewOrganisationUnits":
return (
<OrgUnitForm
Expand Down
4 changes: 2 additions & 2 deletions src/components/OrgUnitForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class OrgUnitForm extends React.Component {
<TextField
onChange={event => this._searchOrganisationUnits(event.target.value)}
floatingLabelText={this.context.d2.i18n.getTranslation(
"filter_organisation_units_by_name"
"filter_organisation_units_capture_by_name"
)}
fullWidth
/>
Expand All @@ -201,7 +201,7 @@ class OrgUnitForm extends React.Component {
</div>
<div className="organisation-unit-tree__selected">
{`${this.props.selected.length} ${this.getTranslation(
"organisation_units_selected"
"organisation_units_capture_selected"
)}`}
</div>
{this.renderRoots()}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReplicateUserFromTable.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ReplicateUserFromTable extends React.Component {
"firstName",
"surname",
"email",
"organisationUnits",
"organisationUnitsCapture",
"dataViewOrganisationUnits",
];

Expand Down
2 changes: 1 addition & 1 deletion src/components/UserRolesDialog.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function UserRolesDialog(props, context) {

const modelOptions = {
parentModel: d2.models.users,
parentFields: ":owner,userCredentials[id,username,userRoles[id,name],lastLogin]",
parentFields: ":owner,userCredentials[id,username,userRoles[id,name],lastLogin, disabled]",
childrenModel: d2.models.userRoles,
getChildren: user => user.userCredentials.userRoles,
getPayload: getPayload,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,17 @@ export default class BatchModelsMultiSelectModel {
};
return this.parentModel.list(options).then(collection => collection.toArray());
}

save(parents, allChildren, selectedIds, updateStrategy) {
async save(parents, allChildren, selectedIds, updateStrategy) {
const api = this.d2.Api.getApi();
const selectedChildren = _(allChildren)
.keyBy("id")
.at(...selectedIds)
.compact()
.value();

const childrenForParents = this.getNewChildren(parents, selectedChildren, updateStrategy);
const payload = this.getPayload(allChildren, _.zip(parents, childrenForParents));
const metadataUrl = "metadata?importStrategy=UPDATE&mergeMode=REPLACE";

return api.post(metadataUrl, payload).then(response => {
if (response.status !== "OK") {
console.error("Response error", response);
Expand Down
Loading

0 comments on commit 6096623

Please sign in to comment.