Skip to content

Commit

Permalink
Role has multiple apps for welcome refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Nov 27, 2023
1 parent bf679b8 commit f4a8176
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 24 deletions.
15 changes: 11 additions & 4 deletions client/src/components/RoleCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ import I18n from "../locale/I18n";
import {MoreLessText} from "./MoreLessText";
import {Button, Card, CardType, Checkbox, Chip, ChipType} from "@surfnet/sds";
import {useNavigate} from "react-router-dom";
import {isEmpty} from "../utils/Utils";
import {isEmpty, splitListSemantically} from "../utils/Utils";
import {roleName} from "../utils/Manage";
import {ReactComponent as MultipleIcon} from "../icons/multi-role.svg";

export const RoleCard = ({role, index, invitationSelected, invitationSelectCallback, isNew = false}) => {
const navigate = useNavigate();
const application = role.isUserRole ? role.role.application : role.application;
const logo = application.logo;

const applications = role.isUserRole ? role.role.applicationMaps : role.applicationMaps;
const multiApp = applications.length === 1;
const application = applications[0];
const logo = multiApp ? application.logo : <MultipleIcon/>
const name = multiApp ? splitListSemantically(applications.map(app => roleName(app)), I18n.t("forms.and")) :
roleName(application);

const children =
<div key={index} className="user-role" >
Expand All @@ -21,7 +28,7 @@ export const RoleCard = ({role, index, invitationSelected, invitationSelectCallb
}
<Logo src={logo} alt={"provider"} className={"provider"}/>
<section className={"user-role-info"}>
<p>{application[`name:${I18n.locale}`]} ({application[`OrganizationName:${I18n.locale}`]})</p>
<p>{name}</p>
<h3>{role.name}</h3>
<MoreLessText txt={role.description} cutOffNumber={80}/>
</section>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/RoleCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
}
}

img.provider, svg.provider {
img.provider, svg.provider, svg.multi-role {
height: 90px;
width: auto;
margin: 0 35px auto 0;
Expand Down
7 changes: 6 additions & 1 deletion client/src/pages/Invitation.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ export const Invitation = ({authenticated}) => {
}

const organisationName = role => {
return ` (${role.application["OrganizationName:en"]})`;
if (role.applicationMaps.length === 1) {
const name = role.applicationMaps[0][`OrganizationName:${I18n.locale}`] || role.applicationMaps[0]["OrganizationName:en"];
return ` (${name})`;
}
const set = new Set(role.applicationMaps.map(app => app[`OrganizationName:${I18n.locale}`] || app["OrganizationName:en"]));
return ` (${splitListSemantically([...set], I18n.t("forms.and"))})`
}

const renderLoginStep = () => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/Role.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const Role = () => {
}
Promise.all([roleByID(id, false), userRolesByRoleId(id), invitationsByRoleId(id)])
.then(res => {
deriveApplicationAttributes(res[0], I18n.locale, I18n.t("roles.multiple"))
deriveApplicationAttributes(res[0], I18n.locale, I18n.t("roles.multiple"), I18n.t("forms.and"))
setRole(res[0]);
setUserRole(res[1].find(userRole => userRole.role.id === res[0].id && userRole.userInfo.id === user.id));
const newTabs = [
Expand Down
2 changes: 1 addition & 1 deletion client/src/tabs/Applications.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const Applications = () => {
searchAttributes={["name", "provider", "provisioning"]}
rowLinkMapper={isUserAllowed(AUTHORITIES.INVITER, user) ? openRole : null}
inputFocus={true}
rowClassNameResolver={entity => entity.applications.length > 1 ? "multi-role" : ""}>
rowClassNameResolver={entity => (entity.applications || []).length > 1 ? "multi-role" : ""}>
</Entities>

</div>
Expand Down
2 changes: 1 addition & 1 deletion client/src/tabs/Roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export const Roles = () => {
filters={filter(filterOptions, filterValue)}
customSearch={roleSearchRequired && isSuperUser ? search : null}
rowLinkMapper={isUserAllowed(AUTHORITIES.INVITER, user) ? openRole : null}
rowClassNameResolver={entity => entity.applications.length > 1 ? "multi-role" : ""}
rowClassNameResolver={entity => (entity.applications || []) .length > 1 ? "multi-role" : ""}
busy={searching}/>
</div>
);
Expand Down
17 changes: 12 additions & 5 deletions client/src/utils/Manage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {isEmpty} from "./Utils";
import {isEmpty, splitListSemantically} from "./Utils";
import {ReactComponent as MultipleIcon} from "../icons/multi-role.svg";
import I18n from "../locale/I18n";

export const singleProviderToOption = provider => {
const organisation = provider["OrganizationName:en"];
Expand All @@ -15,11 +16,17 @@ export const singleProviderToOption = provider => {
};
}

export const roleName = app => {
const name = app[`name:${I18n.locale}`] || app["name:en"]
const orgName = app[`OrganizationName:${I18n.locale}`] || app["OrganizationName:en"]
return `${name} (${orgName})`;
}

export const providersToOptions = providers => {
return providers.map(provider => singleProviderToOption(provider));
}

export const deriveApplicationAttributes = (role, locale, multiple) => {
export const deriveApplicationAttributes = (role, locale, multiple, separator) => {
const applications = role.applicationMaps;
if (!isEmpty(applications)) {
if (applications.length === 1) {
Expand All @@ -28,9 +35,9 @@ export const deriveApplicationAttributes = (role, locale, multiple) => {
role.logo = applications[0].logo;
} else {
role.applicationName = multiple;
role.applicationOrganizationName = applications
.map(app => app[`OrganizationName:${locale}`] || app["OrganizationName:en"])
.join(", ")
const orgNames = new Set(applications
.map(app => app[`OrganizationName:${locale}`] || app["OrganizationName:en"]));
role.applicationOrganizationName = splitListSemantically([...orgNames], separator);
role.logo = <MultipleIcon/>;
}
}
Expand Down
5 changes: 3 additions & 2 deletions client/src/utils/UserRole.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {isEmpty} from "./Utils";
import {deriveApplicationAttributes} from "./Manage";
import I18n from "../locale/I18n";

export const INVITATION_STATUS = {
OPEN: "OPEN",
Expand Down Expand Up @@ -104,13 +105,13 @@ export const markAndFilterRoles = (user, allRoles, locale, multiple) => {
role.isUserRole = false;
role.label = role.name;
role.value = role.id;
deriveApplicationAttributes(role, locale, multiple);
deriveApplicationAttributes(role, locale, multiple, I18n.t("forms.and"));
});
const userRoles = user.userRoles;
userRoles.forEach(userRole => {
userRole.isUserRole = true;
const role = userRole.role;
deriveApplicationAttributes(role, locale, multiple);
deriveApplicationAttributes(role, locale, multiple, I18n.t("forms.and"));
userRole.name = role.name;
userRole.label = role.name;
userRole.value = role.id;
Expand Down
17 changes: 12 additions & 5 deletions welcome/src/components/RoleCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ import Logo from "./Logo";
import I18n from "../locale/I18n";
import {MoreLessText} from "./MoreLessText";
import {Button, Card, CardType, Chip, ChipType} from "@surfnet/sds";
import {isEmpty, sanitizeURL} from "../utils/Utils";

import {isEmpty, sanitizeURL, splitListSemantically} from "../utils/Utils";
import {ReactComponent as MultipleIcon} from "../icons/multi-role.svg";
import {roleName} from "../utils/Manage";

export const RoleCard = ({role, index, isNew = false, skipLaunch= false}) => {

const application = role.application;
const applications = role.applicationMaps;
const multiApp = applications.length === 1;
const application = applications[0];
const logo = multiApp ? application.logo : <MultipleIcon/>
const name = multiApp ? splitListSemantically(applications.map(app => roleName(app)), I18n.t("forms.and")) :
roleName(application);

const children =
<div key={index} className="user-role">
<Logo src={application.logo} alt={"provider"} className={"provider"}/>
<Logo src={logo} alt={"provider"} className={"provider"}/>
<section className={"user-role-info"}>
<p>{application[`name:${I18n.locale}`]} ({application[`OrganizationName:${I18n.locale}`]})</p>
<p>{name}</p>
<h3>{role.name}</h3>
<MoreLessText txt={role.description} cutOffNumber={120}/>
</section>
Expand Down
5 changes: 5 additions & 0 deletions welcome/src/icons/multi-role.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions welcome/src/locale/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const en = {
rolesInfo: "You have access to the following applications.",
expiryDays: "Expiry days"
},
roles: {
multiple: "Multiple applications",
},
forms: {
ok: "Ok",
and: "and",
Expand Down
3 changes: 3 additions & 0 deletions welcome/src/locale/nl.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const nl = {
rolesInfo: "Je bezit de volgende rollen.",
expiryDays: "Verloopdagen"
},
roles: {
multiple: "Meedere applicaties",
},
forms: {
ok: "Ok",
and: "en",
Expand Down
3 changes: 2 additions & 1 deletion welcome/src/pages/Invitation.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ export const Invitation = ({authenticated}) => {
const renderLoginStep = () => {
let html = DOMPurify.sanitize(I18n.t("invitationAccept.invited", {
type: I18n.t("invitationAccept.role"),
roles: splitListSemantically(invitation.roles.map(invitationRole => `<strong>${invitationRole.role.name}</strong>${organisationName(invitationRole)}`), I18n.t("forms.and")),
roles: splitListSemantically(invitation.roles
.map(invitationRole => `<strong>${invitationRole.role.name}</strong>${organisationName(invitationRole.role.applicationMaps)}`), I18n.t("forms.and")),
inviter: invitation.inviter.name,
plural: invitation.roles.length === 1 ? I18n.t("invitationAccept.role") : I18n.t("invitationAccept.roles"),
email: invitation.inviter.email
Expand Down
18 changes: 16 additions & 2 deletions welcome/src/utils/Manage.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
export const organisationName = invitationRole => {
return ` (${invitationRole.role.application["OrganizationName:en"]})`;
import I18n from "../locale/I18n";
import {splitListSemantically} from "./Utils";

export const organisationName = apps => {
if (apps.length === 1) {
return ` (${apps[0]["OrganizationName:en"]})`;
} else {
const set = new Set(apps.map(app => app["OrganizationName:en"]).sort());
return splitListSemantically([...set], I18n.t("forms.and"));
}
}

export const roleName = app => {
const name = app[`name:${I18n.locale}`] || app["name:en"]
const orgName = app[`OrganizationName:${I18n.locale}`] || app["OrganizationName:en"]
return `${name} (${orgName})`;
}

0 comments on commit f4a8176

Please sign in to comment.