Skip to content

Commit

Permalink
Merge pull request #25 from EyeSeeTea/feat/amr-aggregate-landing-pages
Browse files Browse the repository at this point in the history
Feat: add optional action description field
  • Loading branch information
ifoche authored Dec 7, 2023
2 parents 22f1696 + 523080a commit 30c900e
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 15 deletions.
10 changes: 8 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: 2023-08-15T11:06:27.074Z\n"
"PO-Revision-Date: 2023-08-15T11:06:27.074Z\n"
"POT-Creation-Date: 2023-10-24T20:42:29.340Z\n"
"PO-Revision-Date: 2023-10-24T20:42:29.340Z\n"

msgid "Field {{field}} cannot be blank"
msgstr ""
Expand Down Expand Up @@ -38,6 +38,9 @@ msgstr ""
msgid "Name *"
msgstr ""

msgid "Description"
msgstr ""

msgid "Icon"
msgstr ""

Expand Down Expand Up @@ -371,6 +374,9 @@ msgstr ""
msgid "First load can take a couple of minutes, please wait..."
msgstr ""

msgid "Loading the user configuration..."
msgstr ""

msgid "Create"
msgstr ""

Expand Down
8 changes: 7 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: 2023-08-15T11:06:27.074Z\n"
"POT-Creation-Date: 2023-10-24T20:42:29.340Z\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 @@ -38,6 +38,9 @@ msgstr ""
msgid "Name *"
msgstr ""

msgid "Description"
msgstr ""

msgid "Icon"
msgstr ""

Expand Down Expand Up @@ -370,6 +373,9 @@ msgstr ""
msgid "First load can take a couple of minutes, please wait..."
msgstr ""

msgid "Loading the user configuration..."
msgstr ""

msgid "Create"
msgstr ""

Expand Down
1 change: 1 addition & 0 deletions src/data/entities/JSONAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface JSONAction {
_version: number;
id: string;
name: TranslatableText;
description: TranslatableText;
icon: string;
iconLocation: string;
backgroundColor: string;
Expand Down
8 changes: 5 additions & 3 deletions src/data/repositories/ActionDefaultRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import FileSaver from "file-saver";
import JSZip from "jszip";
import _ from "lodash";
import { defaultAction, isValidActionType, Action } from "../../domain/entities/Action";
import { defaultAction, isValidActionType, Action, defaultTranslatableModel } from "../../domain/entities/Action";
import { TranslatableText } from "../../domain/entities/TranslatableText";
import { validateUserPermission } from "../../domain/entities/User";
import { ActionRepository } from "../../domain/repositories/ActionRepository";
Expand Down Expand Up @@ -60,8 +60,8 @@ export class ActionDefaultRepository implements ActionRepository {
}

public async get(key: string): Promise<Action | undefined> {
const dataStoreModel = await this.storageClient.getObjectInCollection<PersistedAction>(Namespaces.ACTIONS, key);

const actions = (await this.storageClient.getObject<PersistedAction[]>(Namespaces.ACTIONS)) ?? [];
const dataStoreModel = _(actions).find(action => action.id === key);
if (!dataStoreModel) return undefined;

const domainModel = await this.buildDomainModel(dataStoreModel);
Expand Down Expand Up @@ -168,6 +168,7 @@ export class ActionDefaultRepository implements ActionRepository {
_version: model._version,
id: model.id,
name: model.name,
description: model.description,
icon: model.icon,
iconLocation: model.iconLocation,
backgroundColor: model.backgroundColor,
Expand Down Expand Up @@ -202,6 +203,7 @@ export class ActionDefaultRepository implements ActionRepository {

return {
...rest,
description: model.description ?? defaultTranslatableModel("description"),
installed: await this.instanceRepository.isAppInstalledByUrl(model.dhisLaunchUrl),
editable: validateUserPermission(model, "write", currentUser),
compatible: validateDhisVersion(model, instanceVersion),
Expand Down
16 changes: 12 additions & 4 deletions src/domain/entities/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ export const ActionTypeModel = Schema.oneOf([
// Schema.exact("widget"),
]);

export const defaultTranslatableModel = (type: string) => ({
key: `action-${type}`,
referenceValue: "",
translations: {},
});

export const ActionModel = Schema.extend(
BaseMetadataModel,
Schema.object({
id: Schema.string,
name: TranslatableTextModel,
description: Schema.optionalSafe(TranslatableTextModel, defaultTranslatableModel("description")),
icon: Schema.string,
iconLocation: Schema.optionalSafe(Schema.string, ""),
backgroundColor: Schema.optionalSafe(Schema.string, ""),
Expand Down Expand Up @@ -76,7 +83,8 @@ export const actionValidations: ModelValidation[] = [

export const defaultAction: PartialAction = {
id: "",
name: { key: "action-name", referenceValue: "", translations: {} },
name: defaultTranslatableModel("name"),
description: defaultTranslatableModel("description"),
icon: "",
iconLocation: "",
backgroundColor: "#276696",
Expand All @@ -102,9 +110,9 @@ export const getPageActions = (
} else if (user) {
return currentPageActions
.filter(action => {
const actionUsers = action.userAccesses?.map(userAccess => userAccess.id);
const actionUserGroups = action.userGroupAccesses?.map(userGroupAccess => userGroupAccess.id);
const userGroupIds = user.userGroups?.map(userGroup => userGroup.id);
const actionUsers = action.userAccesses?.map(userAccess => userAccess.id) ?? [];
const actionUserGroups = action.userGroupAccesses?.map(userGroupAccess => userGroupAccess.id) ?? [];
const userGroupIds = user.userGroups.map(userGroup => userGroup.id);

const hasUserAccess = actionUsers.includes(user.id);
const hasUserGroupAccess = _.intersection(actionUserGroups, userGroupIds).length > 0;
Expand Down
4 changes: 3 additions & 1 deletion src/domain/helpers/ActionHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const updateTranslation = (
action: PartialAction,
key: string,
value: string,
modelType: "name" | "description",
language?: string
): PartialAction => {
const translate = (text: TranslatableText): TranslatableText => {
Expand All @@ -17,6 +18,7 @@ export const updateTranslation = (

return {
...action,
name: translate(action.name),
name: modelType === "name" ? translate(action.name) : action.name,
description: modelType === "description" ? translate(action.description) : action.description,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export const GeneralInfoStep: React.FC<ActionCreationWizardStepProps> = ({ actio
);

const onChangeTranslation = useCallback(
(text: TranslatableText, value: string) => {
onChange(action => updateTranslation(action, text.key, value));
(text: TranslatableText, value: string, type: "name" | "description") => {
onChange(action => updateTranslation(action, text.key, value, type));
},
[onChange]
);
Expand Down Expand Up @@ -94,12 +94,23 @@ export const GeneralInfoStep: React.FC<ActionCreationWizardStepProps> = ({ actio
fullWidth={true}
label={i18n.t("Name *")}
value={action.name.referenceValue}
onChange={event => onChangeTranslation(action.name, event.target.value)}
onChange={event => onChangeTranslation(action.name, event.target.value, "name")}
error={!!errors["name"]}
helperText={errors["name"]}
/>
</Row>

<Row>
<TextFieldOnBlur
fullWidth={true}
label={i18n.t("Description")}
value={action.description.referenceValue}
onChange={event => onChangeTranslation(action.description, event.target.value, "description")}
error={!!errors["description"]}
helperText={errors["description"]}
/>
</Row>

<Row style={{ marginBottom: 40 }}>
<h3>{i18n.t("Icon")}</h3>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const AdditionalComponents: React.FC<{
};

const name = translate(action.name);
const description = translate(action.description);

return (
<BigCard
Expand All @@ -53,6 +54,7 @@ export const AdditionalComponents: React.FC<{
disabled={action?.disabled}
icon={action?.icon ? <img src={action.icon} alt={`Icon for ${name}`} /> : undefined}
iconLocation={action?.iconLocation}
description={description}
backgroundColor={action?.backgroundColor}
fontColor={action?.fontColor}
textAlignment={action?.textAlignment}
Expand Down
6 changes: 5 additions & 1 deletion src/webapp/components/card-board/BigCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CardProgress, CardProgressText } from "./CardProgress";
const BaseCard: React.FC<BigCardProps> = ({
className,
label,
description,
icon,
iconLocation,
backgroundColor,
Expand Down Expand Up @@ -33,6 +34,7 @@ const BaseCard: React.FC<BigCardProps> = ({
{icon && iconLocation === "top" ? <BigCardIcon>{icon}</BigCardIcon> : null}
<BigCardTitle>{label}</BigCardTitle>
{icon && (!iconLocation || iconLocation === "bottom") ? <BigCardIcon>{icon}</BigCardIcon> : null}
{description ? <p>{description}</p> : null}
{progress !== undefined ? <CardProgressText>{`${normalizedProgress}%`}</CardProgressText> : null}
{progress !== undefined ? <CardProgress value={normalizedProgress} max="100"></CardProgress> : null}
</div>
Expand Down Expand Up @@ -60,6 +62,7 @@ export interface BigCardProps {
onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
onContextMenu?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
disabled?: boolean;
description?: string;
icon?: ReactNode;
iconLocation?: string;
backgroundColor?: string;
Expand All @@ -82,8 +85,9 @@ const BigCardIcon = styled.span`
img,
svg {
height: 72px;
max-height: 10vw;
max-width: 18vh;
// max-width: 18vh;
margin: 0;
user-drag: none;
}
Expand Down

0 comments on commit 30c900e

Please sign in to comment.