Skip to content

Commit

Permalink
Merge branch 'upstream-development'
Browse files Browse the repository at this point in the history
* upstream-development:
  Update README.md
  feat: add phone number column to empty csv template, export csv and json
  bump release
  update translation files
  feat: add phone number column
  feat: add sortable status column
  fix: increase pageSize and get all users
  include created/updated by in userCredentials for version 236
  • Loading branch information
MiquelAdell committed Apr 30, 2024
2 parents 4beecce + a7f5ae9 commit c07a40a
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 10 deletions.
7 changes: 5 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2024-04-12T13:15:04.627Z\n"
"PO-Revision-Date: 2024-04-12T13:15:04.627Z\n"
"POT-Creation-Date: 2024-04-17T14:57:37.763Z\n"
"PO-Revision-Date: 2024-04-17T14:57:37.763Z\n"

msgid "Copy to clipboard"
msgstr ""
Expand Down Expand Up @@ -302,6 +302,9 @@ msgstr ""
msgid "First name"
msgstr ""

msgid "Phone number"
msgstr ""

msgid "Organisation units"
msgstr ""

Expand Down
5 changes: 4 additions & 1 deletion i18n/es.po
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: i18next-conv\n"
"POT-Creation-Date: 2024-04-12T13:14:30.161Z\n"
"POT-Creation-Date: 2024-04-17T14:57:37.763Z\n"
"PO-Revision-Date: 2018-10-25T09:02:35.143Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -302,6 +302,9 @@ msgstr ""
msgid "First name"
msgstr ""

msgid "Phone number"
msgstr ""

msgid "Organisation units"
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "user-extended-app",
"description": "DHIS2 Extended User app",
"version": "1.4.1",
"version": "1.4.2",
"license": "GPL-3.0",
"author": "EyeSeeTea team",
"homepage": ".",
Expand Down
3 changes: 3 additions & 0 deletions src/data/models/UserModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const UserModel: Codec<User> = Schema.object({
dataViewOrganisationUnits: Schema.array(NamedRefModel),
lastLogin: Schema.optional(Schema.date),
disabled: Schema.boolean,
status: Schema.string,
access: AccessPermissionsModel,
authorities: Schema.array(Schema.nonEmptyString),
openId: Schema.optional(Schema.string),
Expand Down Expand Up @@ -78,6 +79,8 @@ export const ApiUserModel: Codec<ApiUser> = Schema.object({
ldapId: Schema.optionalSafe(Schema.string, ""),
externalAuth: Schema.boolean,
password: Schema.string,
createdBy: Schema.object({ id: Schema.string, displayName: Schema.string }),
lastUpdatedBy: Schema.object({ id: Schema.string, displayName: Schema.string }),
// accountExpiry: Schema.string,
}),
});
46 changes: 40 additions & 6 deletions src/data/repositories/UserD2ApiRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export class UserD2ApiRepository implements UserRepository {
const otherFilters = _.mapValues(filters, items => (items ? { [items[0]]: items[1] } : undefined));
const areFiltersEnabled = _(otherFilters).values().some();

const sortingField = sorting.field === "status" ? "disabled" : sorting.field;

return apiToFuture(
this.api.models.users.get({
fields: {
Expand All @@ -78,7 +80,7 @@ export class UserD2ApiRepository implements UserRepository {
canManage: canManage === "true" ? "true" : undefined,
filter: otherFilters,
rootJunction: areFiltersEnabled ? rootJunction : undefined,
order: `${sorting.field}:${sorting.order}`,
order: `${sortingField}:${sorting.order}`,
})
).map(({ objects, pager }) => ({
pager,
Expand All @@ -103,9 +105,27 @@ export class UserD2ApiRepository implements UserRepository {
}

public getByIds(ids: string[]): FutureData<User[]> {
return apiToFuture(this.api.models.users.get({ fields, filter: { id: { in: ids } } })).flatMap(({ objects }) =>
Future.success(objects.map(user => this.toDomainUser(user)))
);
const pageSize = 250;
const $requests = _(ids)
.chunk(pageSize)
.map(ids => {
return apiToFuture(
this.api.models.users.get({
fields,
filter: { id: { in: ids } },
pageSize: pageSize,
})
);
})
.value();

return Future.sequential($requests).flatMap(result => {
return Future.success(
_(result.map(({ objects }) => objects.map(user => this.toDomainUser(user))))
.flatten()
.value()
);
});
}

private getFullUsers(options: ListOptions): FutureData<ApiUser[]> {
Expand All @@ -117,6 +137,7 @@ export class UserD2ApiRepository implements UserRepository {
fields: {
...fields,
$owner: true,
userCredentials: { ...fields.userCredentials, $all: true },
},
page,
pageSize,
Expand Down Expand Up @@ -319,6 +340,7 @@ export class UserD2ApiRepository implements UserRepository {
apiUrl: `${this.api.baseUrl}/api/users/${user.id}.json`,
userRoles: userCredentials.userRoles?.map(userRole => ({ id: userRole.id, name: userRole.name })) || [],
lastLogin: userCredentials.lastLogin ? new Date(userCredentials.lastLogin) : undefined,
status: userCredentials.disabled ? "Disabled" : "Active",
disabled: userCredentials.disabled,
organisationUnits: user.organisationUnits,
dataViewOrganisationUnits: user.dataViewOrganisationUnits,
Expand All @@ -329,8 +351,16 @@ export class UserD2ApiRepository implements UserRepository {
password: userCredentials.password,
// accountExpiry: userCredentials.accountExpiry,
authorities,
createdBy: user.createdBy ? user.createdBy.displayName : "",
lastModifiedBy: user.lastUpdatedBy ? user.lastUpdatedBy.displayName : "",
...this.getUserAuditFields(input),
};
}

private getUserAuditFields(user: ApiUserWithAudit) {
const createdBy = user.userCredentials.createdBy || user.createdBy;
const lastUpdatedBy = user.userCredentials.lastUpdatedBy || user.lastUpdatedBy;
return {
createdBy: createdBy?.displayName || "",
lastModifiedBy: lastUpdatedBy?.displayName || "",
};
}

Expand Down Expand Up @@ -363,6 +393,8 @@ export class UserD2ApiRepository implements UserRepository {
ldapId: input.ldapId ?? "",
externalAuth: input.externalAuth ?? "",
password: input.password ?? "",
createdBy: { id: "", displayName: input.createdBy },
lastUpdatedBy: { id: "", displayName: input.lastModifiedBy },
// accountExpiry: input.accountExpiry ?? "",
},
createdBy: { displayName: input.createdBy },
Expand Down Expand Up @@ -399,6 +431,8 @@ const fields = {
ldapId: true,
externalAuth: true,
password: true,
createdBy: { id: true, displayName: true },
lastUpdatedBy: { id: true, displayName: true },
// accountExpiry: true,
},
} as const;
Expand Down
2 changes: 2 additions & 0 deletions src/domain/entities/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface User {
organisationUnits: NamedRef[];
dataViewOrganisationUnits: NamedRef[];
lastLogin?: Date;
status: string;
disabled: boolean;
access: AccessPermissions;
openId?: string;
Expand Down Expand Up @@ -55,6 +56,7 @@ export const defaultUser: User = {
organisationUnits: [{ id: "", name: "" }],
dataViewOrganisationUnits: [{ id: "", name: "" }],
lastLogin: new Date(),
status: "",
disabled: false,
access: { read: true, update: true, externalize: true, delete: true, write: true, manage: true },
openId: "",
Expand Down
1 change: 1 addition & 0 deletions src/legacy/List/list.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const columns = [
{ name: "dataViewOrganisationUnits", sortable: false },
{ name: "lastLogin", sortable: false },
{ name: "disabled", sortable: false },
{ name: "phoneNumber", sortable: false },
];

export default Store.create({
Expand Down
1 change: 1 addition & 0 deletions src/legacy/models/userHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ function getPlainUser(user, { orgUnitsField }, toArray) {
dataViewOrganisationUnits: namesFromCollection(user.dataViewOrganisationUnits, orgUnitsField, toArray),
disabled: userCredentials.disabled,
openId: userCredentials.openId,
phoneNumber: user.phoneNumber,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/legacy/models/userList.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const queryFields = [
"userGroups[id,displayName,publicAccess]",
"organisationUnits[id,code,shortName,displayName]",
"dataViewOrganisationUnits[id,code,shortName,displayName]",
"phoneNumber",
];

// (maxSize - urlAndOtherParamsSize) / (uidSize + encodedCommaSize)
Expand Down
6 changes: 6 additions & 0 deletions src/webapp/components/user-list-table/UserListTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ export const columns: TableColumn<User>[] = [
{ name: "firstName", sortable: true, text: i18n.t("First name") },
{ name: "surname", sortable: true, text: i18n.t("Surname") },
{ name: "email", sortable: true, text: i18n.t("Email") },
{ name: "phoneNumber", text: i18n.t("Phone number") },
{ name: "openId", sortable: false, text: i18n.t("Open ID"), hidden: true },
{ name: "created", sortable: true, text: i18n.t("Created"), hidden: true },
{ name: "lastUpdated", sortable: true, text: i18n.t("Last updated"), hidden: true },
Expand Down Expand Up @@ -394,6 +395,11 @@ export const columns: TableColumn<User>[] = [
getValue: user => buildEllipsizedList(user.dataViewOrganisationUnits),
},
{ name: "lastLogin", sortable: false, text: i18n.t("Last login") },
{
name: "status",
sortable: true,
text: i18n.t("Status"),
},
{
name: "disabled",
sortable: false,
Expand Down

0 comments on commit c07a40a

Please sign in to comment.