Skip to content

Commit

Permalink
Merge pull request #472 from EyeSeeTea/feature/share-step
Browse files Browse the repository at this point in the history
add sharing step
  • Loading branch information
MiquelAdell authored Jan 13, 2025
2 parents 6fe29f3 + e39eb53 commit d6f91fa
Show file tree
Hide file tree
Showing 30 changed files with 494 additions and 91 deletions.
68 changes: 68 additions & 0 deletions src/data/repositories/ConfigD2Repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { apiToFuture } from "$/data/api-futures";
import { metadataCodes } from "$/data/repositories/D2ApiMetadata";
import { Config, UserGroup } from "$/domain/entities/Config";
import { Project } from "$/domain/entities/Project";
import { Region, extractRegionCode } from "$/domain/entities/Region";
import { Future, FutureData } from "$/domain/entities/generic/Future";
import { ConfigRepository } from "$/domain/repositories/ConfigRepository";
import { D2Api } from "$/types/d2-api";

export class ConfigD2Repository implements ConfigRepository {
constructor(private api: D2Api) {}

get(): FutureData<Config> {
return this.getOrgUnitLevelGroup().flatMap(orgUnitLevel => {
return Future.joinObj({
regions: this.getRegions(orgUnitLevel),
userGroups: this.getUserGroups(),
});
});
}

private getOrgUnitLevelGroup(): FutureData<number> {
return apiToFuture(
this.api.models.organisationUnitLevels.get({
fields: { id: true, level: true },
filter: { name: { eq: metadataCodes.orgUnitLevels.country } },
})
).flatMap(d2Response => {
const orgUnitLevel = d2Response.objects[0];
return orgUnitLevel
? Future.success(orgUnitLevel.level)
: Future.error(new Error("Country level not found"));
});
}

private getRegions(level: number): FutureData<Region[]> {
return apiToFuture(
this.api.models.organisationUnits.get({
fields: { id: true, code: true, name: true },
filter: { level: { eq: String(level) }, children: { gt: "0" } },
paging: false,
})
).map(d2Response => {
return d2Response.objects.map(region => ({
id: region.id,
name: region.name,
// org. unit code includes the region code in the first two letters before the underscore
code: Project.extractCode(region.code),
}));
});
}

private getUserGroups(): FutureData<UserGroup[]> {
return apiToFuture(
this.api.models.userGroups.get({
fields: { id: true, name: true },
paging: false,
})
).map(d2Response => {
return d2Response.objects.map(d2UserGroup => ({
id: d2UserGroup.id,
name: d2UserGroup.name,
// user group name includes the region code in the first two letters
code: extractRegionCode(d2UserGroup.name),
}));
});
}
}
15 changes: 12 additions & 3 deletions src/data/repositories/D2ApiCategoryOption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,27 @@ export class D2ApiCategoryOption {
return apiToFuture(
this.api.models.categoryOptions.get({
filter: { id: { in: categoryOptionsIds } },
fields: { id: true, displayName: true, lastUpdated: true },
fields: { id: true, code: true, displayName: true, lastUpdated: true },
paging: false,
})
).map(response => response.objects);
});
}
}

export type D2CategoryOptionType = { id: string; displayName: string; lastUpdated: ISODateString };
export type D2CategoryOptionType = {
code: string;
id: string;
displayName: string;
lastUpdated: ISODateString;
};
export type D2CategoryOptionDates = {
startDate: Maybe<ISODateString>;
endDate: Maybe<ISODateString>;
};

export type D2CategoryOptionWithDates = D2CategoryOptionType & D2CategoryOptionDates;
export type D2CategoryOptionWithDates = D2CategoryOptionType &
D2CategoryOptionDates & {
code: string;
organisationUnits: { id: string; code: string; displayName: string; path: string }[];
};
1 change: 1 addition & 0 deletions src/data/repositories/D2ApiMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const metadataCodes = {
localIndicator: "Local Indicators",
},
indicatorGroupSets: { theme: "Theme", status: "Status" },
orgUnitLevels: { country: "Country" },
};

const metadataFields = {
Expand Down
12 changes: 7 additions & 5 deletions src/data/repositories/DataSetD2Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import {
DataSet,
DataSetList,
OrgUnit,
Permissions,
} from "$/domain/entities/DataSet";
import { Paginated } from "$/domain/entities/Paginated";
import { GetDataSetOptions } from "$/domain/repositories/DataSetRepository";
import { Future, FutureData } from "$/domain/entities/generic/Future";
import { Maybe } from "$/utils/ts-utils";
import { Id } from "$/domain/entities/Ref";
import { Permission } from "$/domain/entities/Permission";
import { Permission, Permissions } from "$/domain/entities/Permission";
import _ from "$/domain/entities/generic/Collection";
import { Project } from "$/domain/entities/Project";
import { D2ApiCategoryOption } from "$/data/repositories/D2ApiCategoryOption";
import { D2ApiConfig, D2Config } from "$/data/repositories/D2ApiMetadata";
import { Pager } from "@eyeseetea/d2-api/api";
import { D2OrgUnit } from "$/data/repositories/OrgUnitD2Repository";

export class DataSetD2Api {
private d2ApiCategoryOption: D2ApiCategoryOption;
Expand Down Expand Up @@ -149,6 +149,8 @@ export class DataSetD2Api {
name: categoryOption.displayName,
lastUpdated: categoryOption.lastUpdated,
isOpen: false,
orgsUnits: [],
code: categoryOption.code,
});
});
});
Expand Down Expand Up @@ -207,6 +209,7 @@ export class DataSetD2Api {
orgUnits: d2DataSet.organisationUnits
? d2DataSet.organisationUnits.map((ou): OrgUnit => {
return {
code: ou.code,
id: ou.id,
name: ou.displayName,
path: ou.path.split("/").slice(1),
Expand Down Expand Up @@ -261,7 +264,7 @@ export class DataSetD2Api {
return ccCodeParts.join("_");
}

private buildPermission(permissions: string, permissionType: "data" | "metadata"): Permission {
buildPermission(permissions: string, permissionType: "data" | "metadata"): Permission {
if (permissionType === "metadata") {
const { canRead, canWrite } = this.buildPermissionByType(permissions, permissionType);
return Permission.create({ read: canRead, write: canWrite });
Expand Down Expand Up @@ -314,13 +317,12 @@ export const dataSetFields = {

export const dataSetFieldsWithOrgUnits = {
...dataSetFields,
organisationUnits: { id: true, displayName: true, path: true },
organisationUnits: { id: true, code: true, displayName: true, path: true },
};

type D2DataSetFields = MetadataPick<{
dataSets: { fields: typeof dataSetFields };
}>["dataSets"][number];

type D2DataSet = { organisationUnits?: D2OrgUnit[] } & D2DataSetFields;
type D2OrgUnit = { id: Id; path: string; displayName: string };
export type OctalNotationPermission = string;
10 changes: 5 additions & 5 deletions src/data/repositories/DataSetD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,12 @@ export class DataSetD2Repository implements DataSetRepository {
};
}),
userGroupAccesses: _(dataSet.access)
.compactMap(access => {
if (access.type !== "groups") return undefined;
.filter(access => access.type === "groups")
.map(groupAccess => {
return {
access: this.d2DataSetApi.generateFullPermission(access.permissions),
id: access.id,
displayName: access.name,
access: this.d2DataSetApi.generateFullPermission(groupAccess.permissions),
id: groupAccess.id,
displayName: groupAccess.name,
};
})
.value(),
Expand Down
4 changes: 2 additions & 2 deletions src/data/repositories/DataSetTestRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export class DataSetTestRepository implements DataSetRepository {
throw new Error("Method not implemented.");
}
getByIds(): FutureData<DataSet[]> {
throw new Error("Method not implemented.");
return Future.success([]);
}
save(): FutureData<void> {
throw new Error("Method not implemented.");
return Future.void();
}
delete(): FutureData<void> {
throw new Error("Method not implemented.");
Expand Down
5 changes: 3 additions & 2 deletions src/data/repositories/OrgUnitD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class OrgUnitD2Repository implements OrgUnitRepository {
const d2OrgsUnits$ = chunkRequest<D2OrgUnit>(ids, idsToFetch => {
return apiToFuture(
this.api.models.organisationUnits.get({
fields: { id: true, displayName: true, path: true },
fields: { id: true, code: true, displayName: true, path: true },
filter: { id: { in: idsToFetch } },
paging: false,
})
Expand All @@ -23,6 +23,7 @@ export class OrgUnitD2Repository implements OrgUnitRepository {
return d2OrgsUnits$.map(d2OrgUnits => {
return d2OrgUnits.map(d2OrgUnit => {
return {
code: d2OrgUnit.code,
id: d2OrgUnit.id,
name: d2OrgUnit.displayName,
path: d2OrgUnit.path.split("/").slice(1),
Expand All @@ -32,4 +33,4 @@ export class OrgUnitD2Repository implements OrgUnitRepository {
}
}

type D2OrgUnit = { id: string; displayName: string; path: string };
export type D2OrgUnit = { id: string; code: string; displayName: string; path: string };
30 changes: 28 additions & 2 deletions src/data/repositories/ProjectD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ export class ProjectD2Repository implements ProjectRepository {
return apiToFuture(
this.api.models.categoryOptions.get({
fields: {
code: true,
id: true,
displayName: true,
startDate: true,
endDate: true,
lastUpdated: true,
organisationUnits: { id: true, code: true, displayName: true, path: true },
},
filter: { "categories.code": { eq: code } },
order: "displayName:asc",
Expand All @@ -58,10 +60,17 @@ export class ProjectD2Repository implements ProjectRepository {
return categoryOptions.map(d2CategoryOption => {
return Project.build({
dataSets: [],
code: d2CategoryOption.code,
id: d2CategoryOption.id,
name: d2CategoryOption.displayName,
lastUpdated: d2CategoryOption.lastUpdated,
isOpen: this.isProjectOpen(d2CategoryOption.startDate, d2CategoryOption.endDate),
orgsUnits: d2CategoryOption.organisationUnits.map(orgUnit => ({
id: orgUnit.id,
code: orgUnit.code,
name: orgUnit.displayName,
path: orgUnit.path.split("/").slice(1),
})),
});
});
}
Expand Down Expand Up @@ -109,7 +118,13 @@ export class ProjectD2Repository implements ProjectRepository {
},
page: options.paging.page,
pageSize: options.paging.pageSize,
fields: { id: true, displayName: true, lastUpdated: true },
fields: {
id: true,
code: true,
displayName: true,
lastUpdated: true,
organisationUnits: { id: true, code: true, path: true, displayName: true },
},
order: this.buildOrderParam(options),
})
).flatMap(d2Response => {
Expand Down Expand Up @@ -153,13 +168,22 @@ export class ProjectD2Repository implements ProjectRepository {
});
}

private buildProject(d2CategoryOption: D2CategoryOptionType): Project {
private buildProject(
d2CategoryOption: D2CategoryOptionType & { organisationUnits: D2OrgUnit[] }
): Project {
return Project.build({
code: d2CategoryOption.code,
id: d2CategoryOption.id,
name: d2CategoryOption.displayName,
lastUpdated: d2CategoryOption.lastUpdated,
dataSets: [],
isOpen: false,
orgsUnits: d2CategoryOption.organisationUnits.map(orgUnit => ({
code: orgUnit.code,
id: orgUnit.id,
name: orgUnit.displayName,
path: orgUnit.path.split("/").slice(1),
})),
});
}

Expand All @@ -168,3 +192,5 @@ export class ProjectD2Repository implements ProjectRepository {
return `${options.sorting.field}:${options.sorting.order}`;
}
}

type D2OrgUnit = { id: Id; code: string; displayName: string; path: string };
6 changes: 6 additions & 0 deletions src/domain/entities/Config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { NamedCodeRef } from "$/domain/entities/Ref";
import { Region } from "$/domain/entities/Region";

export type UserGroup = NamedCodeRef;

export type Config = { regions: Region[]; userGroups: UserGroup[] };
Loading

0 comments on commit d6f91fa

Please sign in to comment.