Skip to content

Commit

Permalink
Merge pull request #35 from EyeSeeTea/feat/homepage-app-improvements
Browse files Browse the repository at this point in the history
Feat/homepage app improvements
  • Loading branch information
adrianq authored Jun 3, 2024
2 parents db5d69c + fe55823 commit 752c5e6
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 83 deletions.
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: 2024-04-30T15:58:34.129Z\n"
"PO-Revision-Date: 2024-04-30T15:58:34.129Z\n"
"POT-Creation-Date: 2024-05-27T14:20:48.393Z\n"
"PO-Revision-Date: 2024-05-27T14:20:48.393Z\n"

msgid "Field {{field}} cannot be blank"
msgstr ""
Expand Down Expand Up @@ -259,6 +259,12 @@ msgstr ""
msgid "Bottom"
msgstr ""

msgid "Icon Size"
msgstr ""

msgid "Favicon"
msgstr ""

msgid "Page Rendering"
msgstr ""

Expand Down Expand Up @@ -286,6 +292,12 @@ msgstr ""
msgid "Contents"
msgstr ""

msgid "Please ensure that your favicon has a {{aspectRatio}} aspect ratio."
msgstr ""

msgid "Please use an icon of {{max}}x{{max}} pixels or smaller."
msgstr ""

msgid "Importing landing pages(s)"
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: 2024-04-30T15:58:34.129Z\n"
"POT-Creation-Date: 2024-05-27T14:20:48.393Z\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 @@ -259,6 +259,12 @@ msgstr ""
msgid "Bottom"
msgstr ""

msgid "Icon Size"
msgstr ""

msgid "Favicon"
msgstr ""

msgid "Page Rendering"
msgstr ""

Expand Down Expand Up @@ -286,6 +292,12 @@ msgstr ""
msgid "Contents"
msgstr ""

msgid "Please ensure that your favicon has a {{aspectRatio}} aspect ratio."
msgstr ""

msgid "Please use an icon of {{max}}x{{max}} pixels or smaller."
msgstr ""

msgid "Importing landing pages(s)"
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": "home-page",
"description": "Home Page App",
"version": "1.7.1",
"version": "1.8.0",
"license": "GPL-3.0",
"author": "EyeSeeTea team",
"homepage": ".",
Expand Down
2 changes: 2 additions & 0 deletions src/data/repositories/LandingNodeDefaultRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export class LandingNodeDefaultRepository implements LandingNodeRepository {
type: "root" as const,
icon: "img/logo-eyeseetea.png",
iconLocation: "top",
iconSize: "small",
favicon: "img/logo-eyeseetea.png",
pageRendering: "multiple",
order: undefined,
name: {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/entities/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const getPageActions = (

const hasUserAccess = actionUsers.includes(user.id);
const hasUserGroupAccess = _.intersection(actionUserGroups, userGroupIds).length > 0;
const hasPublicAccess = action.publicAccess !== "--------";
const hasPublicAccess = Boolean(action.publicAccess) && action.publicAccess !== "--------";

return hasUserAccess || hasUserGroupAccess || hasPublicAccess;
})
Expand Down
63 changes: 45 additions & 18 deletions src/domain/entities/LandingNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TranslatableText, TranslatableTextModel } from "./TranslatableText";
import { LandingPagePermission } from "./Permission";
import { User } from "./User";
import { Action, getPageActions } from "./Action";
import { Maybe } from "../../types/utils";

export const LandingPageNodeTypeModel = Schema.oneOf([
Schema.exact("root"),
Expand All @@ -24,6 +25,8 @@ export interface LandingNode {
type: LandingNodeType;
icon: string;
iconLocation: string;
iconSize: string;
favicon: string;
pageRendering: LandingNodePageRendering | undefined;
order: number | undefined;
name: TranslatableText;
Expand All @@ -42,6 +45,8 @@ export const LandingNodeModel: Codec<LandingNode> = Schema.object({
type: LandingPageNodeTypeModel,
icon: Schema.optionalSafe(Schema.string, ""),
iconLocation: Schema.optionalSafe(Schema.string, ""),
iconSize: Schema.optionalSafe(Schema.string, ""),
favicon: Schema.optionalSafe(Schema.string, ""),
pageRendering: Schema.optional(LandingPageNodePageRenderingModel),
order: Schema.optional(Schema.integer),
name: TranslatableTextModel,
Expand All @@ -66,12 +71,8 @@ export const buildOrderedLandingNodes = (nodes: LandingNode[]): OrderedLandingNo
}));
};

export const updateLandingNodes = (
nodes: LandingNode[],
permissions: LandingPagePermission[],
user: User
): LandingNode[] => {
return _(nodes)
function updateNodesPermissions(nodes: LandingNode[], permissions: LandingPagePermission[], user: User): LandingNode[] {
const updatedNodes = _(nodes)
.map(node => {
const pagePermission = permissions?.find(permission => permission.id === node.id);

Expand All @@ -87,49 +88,75 @@ export const updateLandingNodes = (

return {
...node,
children: updateLandingNodes(node.children, permissions, user),
children: updateNodesPermissions(node.children, permissions, user),
};
})
.compact()
.value();
};

/* Return a redirect URL if there is only one visible action on primary nodes */
export function getPrimaryRedirectUrl(
return updatedNodes;
}

function spreadFavicon(node: LandingNode, favicon: string): LandingNode {
return {
...node,
favicon: favicon,
children: node.children.map(child => spreadFavicon(child, favicon)),
};
}

export function updateLandings(
landings: LandingNode[],
permissions: LandingPagePermission[],
user: User
): LandingNode[] {
const landingsWithPermissions = updateNodesPermissions(landings, permissions, user);

return landingsWithPermissions.map(landing => spreadFavicon(landing, landing.favicon));
}

// Return
// a redirect URL if there is only one visible action on primary nodes
// a redirect page id when there is only one visible action on primary nodes
export function getPrimaryRedirectNodes(
landingNode: LandingNode,
options: { actions: Action[]; user: User }
): Url | undefined {
): { redirectUrl: Maybe<Url>; redirectPageId: Maybe<string> } {
const { actions, user } = options;

const actionsById = _.keyBy(actions, action => action.id);
const showAllActions = false;
const isRoot = true;

const primaryUrls = _(landingNode.children)
const pageActions = _(landingNode.children)
.reject(node => Boolean(node.secondary))
.flatMap((node): Url[] => {
.flatMap((node): Action[] => {
const nodeActions = actions.filter(action => node.actions.includes(action.id));
const actionIds = user && getPageActions(isRoot, showAllActions, actions, user, nodeActions);

return _(actionIds)
.map(actionId => actionsById[actionId])
.compact()
.map(action => action.dhisLaunchUrl)
.compact()
.value();
})
.value();

const redirectUrl = primaryUrls.length === 1 ? primaryUrls[0] : undefined;
const launchUrls = _.map(pageActions, action => action.dhisLaunchUrl);
const launchPageIds = _.map(pageActions, action => action.launchPageId);

const redirectUrl = launchUrls.length === 1 ? launchUrls[0] : undefined;
const redirectPageId = launchPageIds.length === 1 ? launchPageIds[0] : undefined;

const message = [
`Primary URLs [${primaryUrls.length}]: ${primaryUrls.join(", ")}`,
`Primary URLs [${launchUrls.length}]: ${launchUrls.join(", ")}`,
`Redirect URL: ${redirectUrl || "-"}`,
`Primary Page IDs [${launchPageIds.length}]: ${launchPageIds.join(", ")}`,
`Redirect Page ID: ${redirectPageId || "-"}`,
].join("\n");

console.debug(message);

return redirectUrl;
return { redirectUrl, redirectPageId };
}

export function flattenLandingNodes(nodes: LandingNode[]): LandingNode[] {
Expand Down
18 changes: 18 additions & 0 deletions src/domain/usecases/__tests__/landingNodeFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export const sectionNode: LandingNode = {
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "XusobLebMel",
name: {
key: "XusobLebMel-name",
Expand All @@ -55,6 +57,8 @@ export const sectionNode: LandingNode = {
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "ycAtL2slUDJ",
name: {
key: "ycAtL2slUDJ-name",
Expand Down Expand Up @@ -90,6 +94,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "img/logo-eyeseetea.png",
iconLocation: "top",
iconSize: "small",
favicon: "img/logo-eyeseetea.png",
id: "pAfyLmQmCU6",
name: {
key: "pAfyLmQmCU6-name",
Expand Down Expand Up @@ -118,6 +124,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "XusobLebMel",
name: {
key: "XusobLebMel-name",
Expand All @@ -141,6 +149,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "ycAtL2slUDJ",
name: {
key: "ycAtL2slUDJ-name",
Expand Down Expand Up @@ -173,6 +183,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "SEuEePxkvE7",
name: {
key: "SEuEePxkvE7-name",
Expand Down Expand Up @@ -201,6 +213,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "MmG1BCLXE1Q",
name: {
key: "MmG1BCLXE1Q-name",
Expand Down Expand Up @@ -229,6 +243,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "Jqdtr2lTgNP",
name: {
key: "Jqdtr2lTgNP-name",
Expand Down Expand Up @@ -257,6 +273,8 @@ export const validLandingPagesTree: PersistedLandingPage[] = [
executeOnInit: true,
icon: "",
iconLocation: "",
iconSize: "",
favicon: "",
id: "jFYOc9eUhVd",
name: {
key: "jFYOc9eUhVd-name",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export const AdditionalComponents: React.FC<{
disabled={action?.disabled}
icon={action?.icon ? <img src={action.icon} alt={`Icon for ${name}`} /> : undefined}
iconLocation={action?.iconLocation}
iconSize={currentPage.iconSize}
description={description}
backgroundColor={action?.backgroundColor}
fontColor={action?.fontColor}
Expand Down
25 changes: 8 additions & 17 deletions src/webapp/components/card-board/BigCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React, { ReactNode } from "react";
import styled from "styled-components";
import { CardTitleIcon } from "./CardTitleIcon";
import { CardProgress, CardProgressText } from "./CardProgress";
import { BigCardIcon } from "./BigCardIcon";

const BaseCard: React.FC<BigCardProps> = ({
className,
label,
description,
icon,
iconLocation,
iconSize,
backgroundColor,
fontColor,
textAlignment,
Expand All @@ -31,9 +33,11 @@ const BaseCard: React.FC<BigCardProps> = ({
onContextMenu={onContextMenu}
>
{progress && progress >= 100 ? <CardTitleIcon>done</CardTitleIcon> : null}
{icon && iconLocation === "top" ? <BigCardIcon>{icon}</BigCardIcon> : null}
{icon && iconLocation === "top" ? <BigCardIcon iconSize={iconSize}>{icon}</BigCardIcon> : null}
<BigCardTitle>{label}</BigCardTitle>
{icon && (!iconLocation || iconLocation === "bottom") ? <BigCardIcon>{icon}</BigCardIcon> : null}
{icon && (!iconLocation || iconLocation === "bottom") ? (
<BigCardIcon iconSize={iconSize}>{icon}</BigCardIcon>
) : null}
{description ? <p>{description}</p> : null}
{progress !== undefined ? <CardProgressText>{`${normalizedProgress}%`}</CardProgressText> : null}
{progress !== undefined ? <CardProgress value={normalizedProgress} max="100"></CardProgress> : null}
Expand All @@ -47,6 +51,7 @@ export const BigCard = styled(BaseCard)`
text-align: left;
margin: 10px 10px 10px;
user-select: none;
max-height: 305px;
cursor: ${({ onClick, disabled }) => (onClick && !disabled ? "pointer" : "inherit")};
`;

Expand All @@ -65,6 +70,7 @@ export interface BigCardProps {
description?: string;
icon?: ReactNode;
iconLocation?: string;
iconSize?: string;
backgroundColor?: string;
fontColor?: string;
textAlignment?: any;
Expand All @@ -77,18 +83,3 @@ const BigCardTitle = styled.span`
font-weight: 700;
display: block;
`;

const BigCardIcon = styled.span`
display: flex;
place-content: center;
margin: 20px 0px;
img,
svg {
height: 72px;
max-height: 10vw;
// max-width: 18vh;
margin: 0;
user-drag: none;
}
`;
Loading

0 comments on commit 752c5e6

Please sign in to comment.