Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 14 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: 2025-10-20T15:52:19.670Z\n"
"PO-Revision-Date: 2025-10-20T15:52:19.670Z\n"
"POT-Creation-Date: 2025-10-21T03:21:20.753Z\n"
"PO-Revision-Date: 2025-10-21T03:21:20.753Z\n"

msgid ""
"THIS NEW RELEASE INCLUDES SHARING SETTINGS PER INSTANCES. FOR THIS VERSION "
Expand Down Expand Up @@ -1986,6 +1986,18 @@ msgstr ""
msgid "Leave empty to keep all history"
msgstr ""

msgid "Metadata Sync User Settings"
msgstr ""

msgid "Default owner and sharing settings inclusion method"
msgstr ""

msgid "Default users inclusion method"
msgstr ""

msgid "Default organisation units inclusion method"
msgstr ""

msgid "Data Store"
msgstr ""

Expand Down
14 changes: 13 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: 2025-10-16T11:09:45.206Z\n"
"POT-Creation-Date: 2025-10-21T03:21:20.753Z\n"
"PO-Revision-Date: 2020-07-10T06:53:30.625Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -1988,6 +1988,18 @@ msgstr ""
msgid "Leave empty to keep all history"
msgstr ""

msgid "Metadata Sync User Settings"
msgstr ""

msgid "Default owner and sharing settings inclusion method"
msgstr ""

msgid "Default users inclusion method"
msgstr ""

msgid "Default organisation units inclusion method"
msgstr ""

msgid "Data Store"
msgstr ""

Expand Down
14 changes: 13 additions & 1 deletion i18n/fr.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: 2025-10-16T11:09:45.206Z\n"
"POT-Creation-Date: 2025-10-21T03:21:20.753Z\n"
"PO-Revision-Date: 2020-07-10T06:53:30.625Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -1988,6 +1988,18 @@ msgstr ""
msgid "Leave empty to keep all history"
msgstr ""

msgid "Metadata Sync User Settings"
msgstr ""

msgid "Default owner and sharing settings inclusion method"
msgstr ""

msgid "Default users inclusion method"
msgstr ""

msgid "Default organisation units inclusion method"
msgstr ""

msgid "Data Store"
msgstr ""

Expand Down
14 changes: 13 additions & 1 deletion i18n/pt.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: 2025-10-16T11:09:45.206Z\n"
"POT-Creation-Date: 2025-10-21T03:21:20.753Z\n"
"PO-Revision-Date: 2020-07-10T06:53:30.625Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -1988,6 +1988,18 @@ msgstr ""
msgid "Leave empty to keep all history"
msgstr ""

msgid "Metadata Sync User Settings"
msgstr ""

msgid "Default owner and sharing settings inclusion method"
msgstr ""

msgid "Default users inclusion method"
msgstr ""

msgid "Default organisation units inclusion method"
msgstr ""

msgid "Data Store"
msgstr ""

Expand Down
1 change: 1 addition & 0 deletions src/data/storage/Namespaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const Namespace = {
RESPONSIBLES: "responsibles",
MAPPINGS: "mappings",
SETTINGS: "settings",
USER_SETTINGS: "user-settings",
SCHEDULER_EXECUTIONS: "scheduler-executions",
EVENTS_USER_COLUMNS: "events-user-columns",
};
Expand Down
37 changes: 37 additions & 0 deletions src/data/user-settings/UserSettingsD2ApiRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Future, FutureData } from "../../domain/common/entities/Future";

import { Namespace } from "../storage/Namespaces";
import { Instance } from "../../domain/instance/entities/Instance";
import { StorageDataStoreClient } from "../storage/StorageDataStoreClient";
import { DEFAULT_USER_SETTINGS, UserSettings, UserSettingsProps } from "../../domain/user-settings/UserSettings";
import { UserSettingsRepository } from "../../domain/user-settings/UserSettingsRepository";

export class UserSettingsD2ApiRepository implements UserSettingsRepository {
private dataStoreClient: StorageDataStoreClient;
constructor(private instance: Instance) {
this.dataStoreClient = new StorageDataStoreClient(this.instance, undefined, { storageType: "user" });
}

get(): FutureData<UserSettings> {
return this.dataStoreClient
.getObjectFuture<UserSettingsProps>(Namespace.USER_SETTINGS)
.flatMap(userSettings => {
if (!userSettings) {
return this.dataStoreClient
.saveObjectFuture<UserSettingsProps>(Namespace.USER_SETTINGS, DEFAULT_USER_SETTINGS)
.flatMap(() => {
return Future.success(UserSettings.create(DEFAULT_USER_SETTINGS));
});
} else {
return Future.success(UserSettings.create(userSettings));
}
});
}

save(userSettings: UserSettings): FutureData<void> {
return this.dataStoreClient.saveObjectFuture<UserSettingsProps>(
Namespace.USER_SETTINGS,
userSettings._getAttributes()
);
}
}
23 changes: 21 additions & 2 deletions src/domain/rules/entities/SynchronizationRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { SynchronizationType } from "../../synchronization/entities/SynchronizationType";
import { TeisSyncPeriodField } from "../../aggregated/entities/TeisSyncPeriodField";
import { EventsSyncPeriodField } from "../../aggregated/entities/EventsSyncPeriodField";
import { UserSettingsInclusionsConfig } from "../../user-settings/UserSettings";

export class SynchronizationRule {
private readonly syncRule: SynchronizationRuleData;
Expand Down Expand Up @@ -305,8 +306,26 @@ export class SynchronizationRule {
});
}

public static createOnDemand(type: SynchronizationType = "metadata"): SynchronizationRule {
return SynchronizationRule.create(type).updateName("__MANUAL__").updateOndemand(true);
public static createOnDemand(
type: SynchronizationType = "metadata",
defaultInclusions?: UserSettingsInclusionsConfig
): SynchronizationRule {
const onDemandRule = SynchronizationRule.create(type).updateName("__MANUAL__").updateOndemand(true);

if (defaultInclusions) {
const { sharing, users, organisationUnits } = defaultInclusions;
return onDemandRule.updateSyncParams({
...onDemandRule.syncParams,
includeSharingSettingsObjectsAndReferences: sharing === "includeObjectsAndReferences",
includeOnlySharingSettingsReferences: sharing === "includeOnlyReferences",
includeUsersObjectsAndReferences: users === "includeObjectsAndReferences",
includeOnlyUsersReferences: users === "includeOnlyReferences",
includeOrgUnitsObjectsAndReferences: organisationUnits === "includeObjectsAndReferences",
includeOnlyOrgUnitsReferences: organisationUnits === "includeOnlyReferences",
});
} else {
return onDemandRule;
}
}

public static build(syncRule: SynchronizationRuleData | undefined): SynchronizationRule {
Expand Down
11 changes: 11 additions & 0 deletions src/domain/user-settings/GetUserSettingsUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FutureData } from "../common/entities/Future";
import { UserSettings } from "./UserSettings";
import { UserSettingsRepository } from "./UserSettingsRepository";

export class GetUserSettingsUseCase {
constructor(private userSettingsRepository: UserSettingsRepository) {}

public execute(): FutureData<UserSettings> {
return this.userSettingsRepository.get();
}
}
11 changes: 11 additions & 0 deletions src/domain/user-settings/SaveUserSettingsUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FutureData } from "../common/entities/Future";
import { UserSettings } from "./UserSettings";
import { UserSettingsRepository } from "./UserSettingsRepository";

export class SaveUserSettingsUseCase {
constructor(private userSettingsRepository: UserSettingsRepository) {}

public execute(userSettings: UserSettings): FutureData<void> {
return this.userSettingsRepository.save(userSettings);
}
}
36 changes: 36 additions & 0 deletions src/domain/user-settings/UserSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Struct } from "../common/entities/Struct";

export const DEFAULT_INCLUSION_MODE = "includeObjectsAndReferences";
export const DEFAULT_USER_SETTINGS: UserSettingsProps = {
inclusionConfig: {
sharing: DEFAULT_INCLUSION_MODE,
users: DEFAULT_INCLUSION_MODE,
organisationUnits: DEFAULT_INCLUSION_MODE,
},
};

const inclusionModes = ["includeObjectsAndReferences", "includeOnlyReferences", "removeObjectsAndReferences"] as const;

export type InclusionMode = typeof inclusionModes[number];

export type UserSettingsProps = {
inclusionConfig: {
sharing: InclusionMode;
users: InclusionMode;
organisationUnits: InclusionMode;
};
};
export type UserSettingsInclusionsConfig = UserSettingsProps["inclusionConfig"];

export class UserSettings extends Struct<UserSettingsProps>() {
updateInclusionConfig<K extends keyof UserSettings["inclusionConfig"]>(
key: K,
value: UserSettings["inclusionConfig"][K]
): UserSettings {
return this._update({ inclusionConfig: { ...this.inclusionConfig, [key]: value } });
}

static default(): UserSettings {
return UserSettings.create(DEFAULT_USER_SETTINGS);
}
}
7 changes: 7 additions & 0 deletions src/domain/user-settings/UserSettingsRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { FutureData } from "../common/entities/Future";
import { UserSettings } from "./UserSettings";

export interface UserSettingsRepository {
get(): FutureData<UserSettings>;
save(userSettings: UserSettings): FutureData<void>;
}
11 changes: 11 additions & 0 deletions src/presentation/NewCompositionRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { SettingsRepository } from "../domain/settings/SettingsRepository";
import { GetSettingsUseCase } from "../domain/settings/GetSettingsUseCase";
import { SaveSettingsUseCase } from "../domain/settings/SaveSettingsUseCase";
import { SettingsD2ApiRepository } from "../data/settings/SettingsD2ApiRepository";
import { UserSettingsRepository } from "../domain/user-settings/UserSettingsRepository";
import { UserSettingsD2ApiRepository } from "../data/user-settings/UserSettingsD2ApiRepository";
import { GetUserSettingsUseCase } from "../domain/user-settings/GetUserSettingsUseCase";
import { SaveUserSettingsUseCase } from "../domain/user-settings/SaveUserSettingsUseCase";

/**
* @description This file is refactored
Expand All @@ -17,6 +21,7 @@ export type NewCompositionRoot = ReturnType<typeof getCompositionRoot>;
type Repositories = {
storageClientRepository: StorageClientRepository;
settingsRepository: SettingsRepository;
userSettingsRepository: UserSettingsRepository;
};

function getCompositionRoot(repositories: Repositories) {
Expand All @@ -30,6 +35,11 @@ function getCompositionRoot(repositories: Repositories) {
get: new GetSettingsUseCase(repositories.settingsRepository),
save: new SaveSettingsUseCase(repositories.settingsRepository),
},

userSettings: {
get: new GetUserSettingsUseCase(repositories.userSettingsRepository),
save: new SaveUserSettingsUseCase(repositories.userSettingsRepository),
},
};
}

Expand All @@ -38,6 +48,7 @@ export function getWebappCompositionRoot(instance: Instance) {
const repositories: Repositories = {
storageClientRepository: new StorageClientD2Repository(instance),
settingsRepository: new SettingsD2ApiRepository(storageClientRepository),
userSettingsRepository: new UserSettingsD2ApiRepository(instance),
};

return getCompositionRoot(repositories);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from "react";
import Dropdown from "../../dropdown/Dropdown";
import styled from "styled-components";
import i18n from "../../../../../../utils/i18n";
import { InclusionMode } from "../../../../../../domain/user-settings/UserSettings";

export type InclusionFieldsProps = {
sharingSettings: {
value: InclusionMode;
options: { id: InclusionMode; name: string }[];
onValueChange: (value: InclusionMode) => void;
label?: string;
};
users: {
value: InclusionMode;
options: { id: InclusionMode; name: string }[];
onValueChange: (value: InclusionMode) => void;
label?: string;
};
orgUnits: {
value: InclusionMode;
options: { id: InclusionMode; name: string }[];
onValueChange: (value: InclusionMode) => void;
label?: string;
};
};

export const InclusionFields: React.FC<InclusionFieldsProps> = ({ sharingSettings, users, orgUnits }) => (
<>
<DropdownContainer>
<Dropdown<InclusionMode>
value={sharingSettings.value}
items={sharingSettings.options}
label={sharingSettings.label ?? i18n.t("Include owner and sharing settings")}
onValueChange={sharingSettings.onValueChange}
hideEmpty
/>
</DropdownContainer>
<DropdownContainer>
<Dropdown<InclusionMode>
value={users.value}
items={users.options}
label={users.label ?? i18n.t("Include users")}
onValueChange={users.onValueChange}
hideEmpty
/>
</DropdownContainer>
<DropdownContainer>
<Dropdown<InclusionMode>
value={orgUnits.value}
items={orgUnits.options}
label={orgUnits.label ?? i18n.t("Include organisation units")}
onValueChange={orgUnits.onValueChange}
hideEmpty
/>
</DropdownContainer>
</>
);

const DropdownContainer = styled.div`
margin-block-end: 16px;

& > div {
width: 100%;
margin-block-start: 20px;
margin-block-end: 20px;
margin-inline-start: -10px;
}
`;
Loading