From e9c93415354bafd70a26729712a991c8d31d5402 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Tue, 25 Feb 2025 10:41:49 -0800 Subject: [PATCH 01/11] [B] Ensure splash buttons are displayed on mobile --- .../components/layout/Splash/index.js | 28 +++++++------------ .../components/layout/Splash/styles.js | 12 +++++++- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/client/src/frontend/components/layout/Splash/index.js b/client/src/frontend/components/layout/Splash/index.js index 4501a88391..9fe22b4821 100644 --- a/client/src/frontend/components/layout/Splash/index.js +++ b/client/src/frontend/components/layout/Splash/index.js @@ -58,17 +58,13 @@ export default function Splash(props) { {linkText && linkUrl ? ( - {linkText} - + ) : null} {includeSignUp && !authenticated ? ( @@ -78,17 +74,13 @@ export default function Splash(props) { tabIndex="0" to={lh.link("frontendSignUp")} > - Sign Up - + ) : null} diff --git a/client/src/frontend/components/layout/Splash/styles.js b/client/src/frontend/components/layout/Splash/styles.js index 50a4cd49c2..63691b7f27 100644 --- a/client/src/frontend/components/layout/Splash/styles.js +++ b/client/src/frontend/components/layout/Splash/styles.js @@ -3,7 +3,8 @@ import { containerPrototype, respond, headingPrimary, - headingSecondary + headingSecondary, + defaultTransitionProps } from "theme/styles/mixins"; import { transientOptions } from "helpers/emotionHelpers"; @@ -138,6 +139,15 @@ export const Buttons = styled.div` } `; +export const Button = styled.span` + font-size: 14px; + transition: color ${defaultTransitionProps}; + + .utility-button:not(:disabled):hover & { + color: var(--color-base-neutral80); + } +`; + export const Right = styled.figure` display: none; position: relative; From 262c9205ee30ce282efc5b162226c5e04fa641fd Mon Sep 17 00:00:00 2001 From: 1aurend Date: Tue, 25 Feb 2025 10:55:29 -0800 Subject: [PATCH 02/11] [B] Prevent layout flash on resource collections list --- .../frontend/containers/ProjectResourceCollections/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/frontend/containers/ProjectResourceCollections/index.js b/client/src/frontend/containers/ProjectResourceCollections/index.js index 3326ff4971..68d424bab4 100644 --- a/client/src/frontend/containers/ProjectResourceCollections/index.js +++ b/client/src/frontend/containers/ProjectResourceCollections/index.js @@ -7,7 +7,6 @@ import { useParams } from "react-router-dom"; import CheckFrontendMode from "global/containers/CheckFrontendMode"; import { projectsAPI } from "api"; import lh from "helpers/linkHandler"; -import LoadingBlock from "global/components/loading-block"; import { RegisterBreadcrumbs } from "global/components/atomic/Breadcrumbs"; import EntityCollectionPlaceholder from "global/components/entity/CollectionPlaceholder"; import EntityHeadContent from "frontend/components/entity/HeadContent"; @@ -48,7 +47,7 @@ export default function ProjectResourceCollectionsContainer({ : [projectCrumb, collectionsCrumb].filter(Boolean); }, [journalBreadcrumbs, slug, titlePlaintext, t]); - if (!project) return ; + if (!project || !resourceCollections) return null; return ( <> From e42dfd63f50ed98fe996645266dc227ddb4a30a4 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Tue, 25 Feb 2025 13:04:48 -0800 Subject: [PATCH 03/11] [B][E] Ensure homepage content is SSR; prevent layout flash --- .../frontend/containers/Home/Collections.js | 58 ----------------- .../src/frontend/containers/Home/Content.js | 62 +++++++++++++++++++ .../src/frontend/containers/Home/Feature.js | 15 ++--- .../src/frontend/containers/Home/Projects.js | 51 --------------- .../containers/Home/__tests__/Home-test.js | 19 ------ .../__tests__/__snapshots__/Home-test.js.snap | 15 ----- client/src/frontend/containers/Home/index.js | 31 +--------- .../Home/useFetchHomepageContent.js | 62 +++++++++++++++++++ 8 files changed, 132 insertions(+), 181 deletions(-) delete mode 100644 client/src/frontend/containers/Home/Collections.js create mode 100644 client/src/frontend/containers/Home/Content.js delete mode 100644 client/src/frontend/containers/Home/Projects.js delete mode 100644 client/src/frontend/containers/Home/__tests__/Home-test.js delete mode 100644 client/src/frontend/containers/Home/__tests__/__snapshots__/Home-test.js.snap create mode 100644 client/src/frontend/containers/Home/useFetchHomepageContent.js diff --git a/client/src/frontend/containers/Home/Collections.js b/client/src/frontend/containers/Home/Collections.js deleted file mode 100644 index 676232e1f9..0000000000 --- a/client/src/frontend/containers/Home/Collections.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { useMemo } from "react"; -import { useFetch } from "hooks"; -import { projectCollectionsAPI, journalsAPI } from "api"; -import EntityCollection from "frontend/components/entity/Collection"; - -export default function HomeCollectionsContainer() { - const filters = useMemo( - () => ({ - visibleOnHomepage: true, - order: "position ASC" - }), - [] - ); - - const journalFilters = useMemo( - () => ({ - showOnHomepage: true - }), - [] - ); - - const { data: collections } = useFetch({ - request: [projectCollectionsAPI.index, filters], - withAuthDependency: true - }); - - const { data: journals } = useFetch({ - request: [journalsAPI.index, journalFilters], - withAuthDependency: true - }); - - const collectionCount = collections?.length; - - if (!collections && !journals) return null; - - return ( - <> - {collections && - collections.map((projectCollection, i) => ( - - ))} - {journals && - journals.map((journal, i) => ( - - ))} - - ); -} diff --git a/client/src/frontend/containers/Home/Content.js b/client/src/frontend/containers/Home/Content.js new file mode 100644 index 0000000000..af6cf40fe7 --- /dev/null +++ b/client/src/frontend/containers/Home/Content.js @@ -0,0 +1,62 @@ +import React from "react"; +import Feature from "./Feature"; +import CollectionNavigation from "frontend/components/CollectionNavigation"; +import { useFromStore } from "hooks"; +import useFetchHomepageContent from "./useFetchHomepageContent"; +import EntityCollection from "frontend/components/entity/Collection"; +import EntityCollectionPlaceholder from "global/components/entity/CollectionPlaceholder"; + +export default function Content() { + const settings = useFromStore("settings", "select"); + + const { hasVisibleHomeProjectCollections, hasVisibleProjects } = + settings?.attributes?.calculated ?? {}; + const showProjects = !hasVisibleHomeProjectCollections; + + const { + loaded, + projects, + collections, + journals, + features + } = useFetchHomepageContent(showProjects); + + if (!loaded) return null; + + if (!projects?.length && !collections?.length && !journals?.length) + return ; + + const renderCollections = collections?.length + ? collections.map((projectCollection, i) => ( + + )) + : null; + + const renderProjects = projects?.length ? ( + + ) : null; + + const count = showProjects ? 1 : collections?.length; + + return ( + <> + + {showProjects ? renderProjects : renderCollections} + {!!journals?.length && + journals.map((journal, i) => ( + + ))} + {hasVisibleProjects && } + + ); +} diff --git a/client/src/frontend/containers/Home/Feature.js b/client/src/frontend/containers/Home/Feature.js index 50f8dd4a28..be93080a32 100644 --- a/client/src/frontend/containers/Home/Feature.js +++ b/client/src/frontend/containers/Home/Feature.js @@ -1,21 +1,16 @@ -import React, { useMemo } from "react"; +import React from "react"; import PropTypes from "prop-types"; import Layout from "frontend/components/layout"; -import { featuresAPI } from "api"; -import { useFetch } from "hooks"; +import { useFromStore } from "hooks"; import { commonActions } from "actions/helpers"; import { useDispatch } from "react-redux"; -export default function HomeFeatureContainer({ authentication }) { - const filters = useMemo(() => ({ home: true }), []); - const { data: features } = useFetch({ - request: [featuresAPI.index, filters], - withAuthDependency: true - }); - +export default function HomeFeatureContainer({ features }) { const dispatch = useDispatch(); const actions = commonActions(dispatch); + const authentication = useFromStore("authentication"); + return features?.length ? ( ({ - standaloneModeEnforced: false, - order: "sort_title, title" - }), - [] - ); - - const journalFilters = useMemo( - () => ({ - showOnHomepage: true - }), - [] - ); - - const { data, loaded } = useFetch({ - request: [projectsAPI.index, filters, pagination] - }); - - const { data: journals } = useFetch({ - request: [journalsAPI.index, journalFilters], - withAuthDependency: true - }); - - if (!data) return null; - if (loaded && data.length === 0) - return ; - return ( - <> - - {journals && - journals.map((journal, i) => ( - - ))} - - ); -} diff --git a/client/src/frontend/containers/Home/__tests__/Home-test.js b/client/src/frontend/containers/Home/__tests__/Home-test.js deleted file mode 100644 index c8add0f465..0000000000 --- a/client/src/frontend/containers/Home/__tests__/Home-test.js +++ /dev/null @@ -1,19 +0,0 @@ -import HomeContainer from "../"; - -describe("frontend/containers/Home/Home", () => { - def("projects", () => collectionFactory("project")); - def("featuredProjects", () => collectionFactory("project")); - def("user", () => factory("user")); - def("authentication", () => - fixtures.authentication({ user: $user }) - ); - def("root", () => ( - - )); - - it("matches the snapshot", () => { - expect(render($withApp($root))).toMatchSnapshot(); - }); -}); diff --git a/client/src/frontend/containers/Home/__tests__/__snapshots__/Home-test.js.snap b/client/src/frontend/containers/Home/__tests__/__snapshots__/Home-test.js.snap deleted file mode 100644 index ec0a1c3ab4..0000000000 --- a/client/src/frontend/containers/Home/__tests__/__snapshots__/Home-test.js.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`frontend/containers/Home/Home matches the snapshot 1`] = ` -Array [ -
, -] -`; diff --git a/client/src/frontend/containers/Home/index.js b/client/src/frontend/containers/Home/index.js index a87ac78a1e..0f49aa6941 100644 --- a/client/src/frontend/containers/Home/index.js +++ b/client/src/frontend/containers/Home/index.js @@ -1,40 +1,15 @@ import React from "react"; import PropTypes from "prop-types"; -import Collections from "./Collections"; -import Projects from "./Projects"; -import Feature from "./Feature"; -import CollectionNavigation from "frontend/components/CollectionNavigation"; +import Content from "./Content"; import EventTracker, { EVENTS } from "global/components/EventTracker"; import HeadContent from "global/components/HeadContent"; -import { useFromStore } from "hooks"; -import { useLocation } from "react-router-dom"; export default function HomeContainer() { - const settings = useFromStore("settings", "select"); - - const { hasVisibleHomeProjectCollections, hasVisibleProjects } = - settings?.attributes?.calculated ?? {}; - const showProjects = !hasVisibleHomeProjectCollections; - const authentication = useFromStore("authentication"); - const location = useLocation(); - return ( <> -
- - - {showProjects ? ( - - ) : ( - - )} - {hasVisibleProjects && } -
+ + ); } diff --git a/client/src/frontend/containers/Home/useFetchHomepageContent.js b/client/src/frontend/containers/Home/useFetchHomepageContent.js new file mode 100644 index 0000000000..1b08256505 --- /dev/null +++ b/client/src/frontend/containers/Home/useFetchHomepageContent.js @@ -0,0 +1,62 @@ +import { useMemo } from "react"; +import { useFetch } from "hooks"; +import { + projectCollectionsAPI, + journalsAPI, + projectsAPI, + featuresAPI +} from "api"; + +export default function useFetchHomepageContent(fetchProjects) { + const collectionFilters = useMemo( + () => ({ + visibleOnHomepage: true, + order: "position ASC" + }), + [] + ); + + const projectFilters = useMemo( + () => ({ + standaloneModeEnforced: false, + order: "sort_title, title" + }), + [] + ); + + const journalFilters = useMemo( + () => ({ + showOnHomepage: true + }), + [] + ); + + const featuresFilters = useMemo(() => ({ home: true }), []); + + const { data: projects, loaded: projectsLoaded } = useFetch({ + request: [projectsAPI.index, projectFilters, { number: 1, size: 20 }], + condition: fetchProjects + }); + const { data: collections, loaded: collectionsLoaded } = useFetch({ + request: [projectCollectionsAPI.index, collectionFilters], + withAuthDependency: true, + condition: !fetchProjects + }); + + const { data: journals, loaded: journalsLoaded } = useFetch({ + request: [journalsAPI.index, journalFilters], + withAuthDependency: true + }); + + const { data: features, loaded: featuresLoaded } = useFetch({ + request: [featuresAPI.index, featuresFilters], + withAuthDependency: true + }); + + const loaded = + journalsLoaded && featuresLoaded && fetchProjects + ? projectsLoaded + : collectionsLoaded; + + return { loaded, journals, projects, collections, features }; +} From 2364846465087b6fd4e3139637f75e4553671c20 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Tue, 25 Feb 2025 13:15:17 -0800 Subject: [PATCH 04/11] [C] Remove unstyled LoadingBlock --- client/src/frontend/containers/ProjectResources/index.js | 3 +-- client/src/frontend/containers/ResourceDetail/index.js | 7 ++----- client/src/global/components/loading-block/index.js | 7 ------- 3 files changed, 3 insertions(+), 14 deletions(-) delete mode 100644 client/src/global/components/loading-block/index.js diff --git a/client/src/frontend/containers/ProjectResources/index.js b/client/src/frontend/containers/ProjectResources/index.js index 15c661a14b..1d627aa64e 100644 --- a/client/src/frontend/containers/ProjectResources/index.js +++ b/client/src/frontend/containers/ProjectResources/index.js @@ -3,7 +3,6 @@ import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { useDispatch } from "react-redux"; import { useParams } from "react-router-dom"; -import LoadingBlock from "global/components/loading-block"; import { uiFrontendModeActions } from "actions"; import { projectsAPI } from "api"; import lh from "helpers/linkHandler"; @@ -61,7 +60,7 @@ export default function ProjectResourcesContainer({ : [projectCrumb, resourcesCrumb].filter(Boolean); }, [journalBreadcrumbs, slug, titlePlaintext, t]); - if (!project) return ; + if (!project) return null; return ( <> diff --git a/client/src/frontend/containers/ResourceDetail/index.js b/client/src/frontend/containers/ResourceDetail/index.js index bacd3a1eb0..740c99ed58 100644 --- a/client/src/frontend/containers/ResourceDetail/index.js +++ b/client/src/frontend/containers/ResourceDetail/index.js @@ -7,7 +7,6 @@ import { entityStoreActions, fatalErrorActions } from "actions"; import { select } from "utils/entityUtils"; import { resourcesAPI, resourceCollectionsAPI, requests } from "api"; import lh from "helpers/linkHandler"; -import LoadingBlock from "global/components/loading-block"; import { RegisterBreadcrumbs } from "global/components/atomic/Breadcrumbs"; import EntityHeadContent from "frontend/components/entity/HeadContent"; import some from "lodash/some"; @@ -159,7 +158,7 @@ export class ResourceDetailContainer extends PureComponent { const { project, resource } = this.props; if (!project || !resource) { - return ; + return null; } return ( @@ -171,7 +170,7 @@ export class ResourceDetailContainer extends PureComponent { - {resource ? ( + {resource && ( - ) : ( - )} ); diff --git a/client/src/global/components/loading-block/index.js b/client/src/global/components/loading-block/index.js deleted file mode 100644 index d299ace95e..0000000000 --- a/client/src/global/components/loading-block/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import React, { Component } from "react"; - -export default class LoadingBlock extends Component { - render() { - return
 
; - } -} From f61a9f85e4da6c2578d9fc427af499ddeddbe794 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Wed, 26 Feb 2025 11:20:51 -0800 Subject: [PATCH 05/11] [B] Fix role i18n key --- .../reading-group/headings/Group/GroupSummaryBox/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/frontend/components/reading-group/headings/Group/GroupSummaryBox/index.js b/client/src/frontend/components/reading-group/headings/Group/GroupSummaryBox/index.js index ac66d60483..46e933368c 100644 --- a/client/src/frontend/components/reading-group/headings/Group/GroupSummaryBox/index.js +++ b/client/src/frontend/components/reading-group/headings/Group/GroupSummaryBox/index.js @@ -82,7 +82,7 @@ function GroupSummaryBox({ readingGroup, isBackend }) { {creatorName} ) : ( - + {currentUserRole} )} From 2b7a06880e1bd3167dd19a3c161e56f6e3db49dc Mon Sep 17 00:00:00 2001 From: 1aurend Date: Wed, 26 Feb 2025 12:03:49 -0800 Subject: [PATCH 06/11] [E] Add confirm prompt to ingestion drawer --- client/src/backend/containers/ingestion/Ingest.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/backend/containers/ingestion/Ingest.js b/client/src/backend/containers/ingestion/Ingest.js index 7d17e59b65..6768d576e5 100644 --- a/client/src/backend/containers/ingestion/Ingest.js +++ b/client/src/backend/containers/ingestion/Ingest.js @@ -13,6 +13,7 @@ import throttle from "lodash/throttle"; import { websocketActions, notificationActions } from "actions"; import lh from "helpers/linkHandler"; import config from "config"; +import { Prompt } from "react-router-dom"; const { request, flush } = entityStoreActions; @@ -263,7 +264,8 @@ export class IngestionIngest extends Component { } return ( -
+ <> +
-
+ ); } } From 96b1e9fc0f17d6ab0fe5a836f60b15577ab8f96a Mon Sep 17 00:00:00 2001 From: 1aurend Date: Wed, 26 Feb 2025 15:13:09 -0800 Subject: [PATCH 07/11] [B] Make admin link generation more resilient --- .../global/components/navigation/helpers.js | 208 +++++++++++------- 1 file changed, 134 insertions(+), 74 deletions(-) diff --git a/client/src/global/components/navigation/helpers.js b/client/src/global/components/navigation/helpers.js index 23e9e96cc0..2ca67f13d8 100644 --- a/client/src/global/components/navigation/helpers.js +++ b/client/src/global/components/navigation/helpers.js @@ -28,90 +28,150 @@ export const getAdminModeLabel = ({ currentUser, mode, t }) => { } }; -const idPattern = - "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}"; -const idRegex = new RegExp(idPattern, "g"); - -const FE_ROUTE_REGEXES = { - project: /^\/projects\/(?!(all))([A-Za-z0-9-]+)$/, - journal: /^\/journals\/(?!(all))([A-Za-z0-9-]+)$/, - resource: /^\/projects\/([A-Za-z0-9-]+)\/resource\/([A-Za-z0-9-]+)$/, - resourceCollection: /^\/projects\/([A-Za-z0-9-]+)\/resource-collection\/([A-Za-z0-9-]+)$/, - projectCollection: /^\/projects\/project-collection\/([A-Za-z0-9?=-]+)$/, - page: /^\/page\/([A-Za-z0-9-]+)$/, - readingGroup: new RegExp(`^/groups/${idPattern}`) +const FE_ROUTE_MAP = { + resource: { + regex: /^\/projects\/([A-Za-z0-9-]+)\/resource/, + link: `/backend/projects/resource` + }, + resourceCollectionResource: { + regex: /^\/projects\/([A-Za-z0-9-]+)\/resource-collection\/([A-Za-z0-9-]+)\/resource/, + link: `/backend/projects/resource` + }, + resourceCollection: { + regex: /^\/projects\/([A-Za-z0-9-]+)\/resource-collection/, + link: `/backend/projects/resource-collection` + }, + projectCollection: { + regex: /^\/projects\/project-collection/, + link: `/backend/projects/project-collections`, + hasAdminList: true + }, + project: { + regex: /^\/projects/, + link: `/backend/projects`, + hasAdminList: true + }, + journal: { + regex: /^\/journals/, + link: `/backend/journals`, + hasAdminList: true + }, + page: { regex: /^\/page/, link: `/backend/records/pages` }, + readingGroup: { + regex: /^\/groups/, + link: `/backend/groups`, + hasAdminList: true + } +}; + +const BE_ROUTE_MAP = { + resourceCollection: { + regex: /^\/backend\/projects\/resource-collection/, + link: `/projects/[pId]/resource-collection` + }, + resource: { + regex: /^\/backend\/projects\/resource/, + link: `/projects/[pId]/resource` + }, + projectCollection: { + regex: /^\/backend\/projects\/project-collections/, + link: `/projects/project-collection`, + hasList: `/projects/project-collections` + }, + project: { + regex: /^\/backend\/projects/, + link: `/projects`, + hasList: true + }, + journal: { + regex: /^\/backend\/journals/, + link: `/journals`, + hasList: true + }, + page: { regex: /^\/backend\/records\/pages/, link: `/page` }, + readingGroup: { + regex: /^\/backend\/groups/, + link: `/groups`, + hasList: true + } }; -const BE_ROUTE_REGEXES = { - project: new RegExp(`^/backend/projects/${idPattern}/`), - journal: new RegExp(`^/backend/journals/${idPattern}/`), - resource: new RegExp(`^/backend/projects/resource/${idPattern}/`), - resourceCollection: new RegExp( - `^/backend/projects/resource-collection/${idPattern}/` - ), - projectCollection: new RegExp( - `^/backend/projects/project-collections/(${idPattern}|[A-Za-z0-9-]+)` - ), - page: /^\/backend\/records\/pages\/([0-9]+)\//, - readingGroup: new RegExp(`^/backend/groups/${idPattern}/`) +const extractIdentifier = (pathname, basePath) => { + const identifier = pathname.replace(basePath, "").split("/")[1]; + return identifier === "all" ? null : identifier; }; const getAdminPath = pathname => { - if (FE_ROUTE_REGEXES.project.test(pathname)) return `/backend${pathname}`; - if (FE_ROUTE_REGEXES.journal.test(pathname)) return `/backend${pathname}`; - if (FE_ROUTE_REGEXES.readingGroup.test(pathname)) - return `/backend${pathname}`; - if (FE_ROUTE_REGEXES.projectCollection.test(pathname)) { - const noParams = pathname.split("?").filter(Boolean)[0]; - const slug = noParams.split("/").pop(); - return `/backend/projects/project-collections/${slug}`; - } - if (FE_ROUTE_REGEXES.resource.test(pathname)) { - const slug = pathname.split("/").pop(); - return `/backend/projects/resource/${slug}`; - } - if (FE_ROUTE_REGEXES.resourceCollection.test(pathname)) { - const slug = pathname.split("/").pop(); - return `/backend/projects/resource-collection/${slug}`; - } - if (FE_ROUTE_REGEXES.page.test(pathname)) { - const slug = pathname.split("/").pop(); - return `/backend/records/pages/${slug}`; - } + const routeKey = Object.keys(FE_ROUTE_MAP).find(key => { + return FE_ROUTE_MAP[key]?.regex.test(pathname); + }); + const route = FE_ROUTE_MAP[routeKey]; + + if (!route) return `/backend/dashboard`; + + const identifier = extractIdentifier(pathname, route.regex); + + if (!identifier) + return route.hasAdminList ? route.link : `/backend/dashboard`; + + return `${route.link}/${identifier}`; +}; + +const getPageSlug = (id, pages) => { + return pages?.[id]?.attributes?.slug; +}; + +const getProjectId = (id, records) => { + return records?.[id]?.relationships?.project?.data?.id; +}; + +const handlePageRoute = (id, pages) => { + if (!id) return `/`; + + const slug = getPageSlug(id, pages); + + return slug ? `${BE_ROUTE_MAP.page.link}/${slug}` : `/`; +}; + +const handleRouteWithProjectId = (id, entities, routeKey) => { + if (!id) return `/`; + + const records = + routeKey === "resourceCollection" + ? entities.resourceCollections + : entities.resources; + + const projectId = getProjectId(id, records); - return `/backend/dashboard`; + return projectId + ? `${BE_ROUTE_MAP[routeKey].link.replace("[pId]", projectId)}/${id}` + : `/`; }; const getFrontendPath = (pathname, entities) => { - const match = pathname.match(idRegex); - const id = match?.length ? match[0] : null; - - if (BE_ROUTE_REGEXES.project.test(pathname)) return `/projects/${id}`; - if (BE_ROUTE_REGEXES.journal.test(pathname)) return `/journals/${id}`; - if (BE_ROUTE_REGEXES.readingGroup.test(pathname)) return `/groups/${id}`; - if (BE_ROUTE_REGEXES.projectCollection.test(pathname)) - return id - ? `/projects/project-collection/${id}` - : `/projects/project-collection/${pathname.split("/").pop()}`; - if (BE_ROUTE_REGEXES.resource.test(pathname)) { - const projectId = entities.resources - ? entities.resources[id].relationships?.project?.data?.id - : ""; - return projectId ? `/projects/${projectId}/resource/${id}` : "/"; - } - if (BE_ROUTE_REGEXES.resourceCollection.test(pathname)) { - const projectId = entities.resourceCollections - ? entities.resourceCollections[id].relationships?.project?.data?.id - : ""; - return projectId ? `/projects/${projectId}/resource-collection/${id}` : "/"; - } - if (BE_ROUTE_REGEXES.page.test(pathname)) { - const pageId = pathname.split("/").find(part => !isNaN(parseInt(part, 10))); - const slug = entities.pages[pageId].attributes?.slug; - return `/page/${slug}`; - } + const routeKey = Object.keys(BE_ROUTE_MAP).find(key => { + return BE_ROUTE_MAP[key]?.regex.test(pathname); + }); + + const route = BE_ROUTE_MAP[routeKey]; + + if (!route) return `/`; + + const identifier = extractIdentifier(pathname, route.regex); + + if (routeKey === "page") return handlePageRoute(identifier, entities.pages); + if (routeKey === "resource" || routeKey === "resourceCollection") + return handleRouteWithProjectId(identifier, entities, routeKey); + + /* eslint-disable no-nested-ternary */ + if (!identifier) + return route.hasList + ? typeof route.hasList === "string" + ? route.hasList + : route.link + : `/`; - return "/"; + return `${route.link}/${identifier}`; }; export const getDestinationPath = ({ mode, pathname, entities }) => { From 7a4ec0b608c45124fcf677502c15220dfc714a72 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Wed, 26 Feb 2025 15:24:35 -0800 Subject: [PATCH 08/11] [B] Prevent resource from stretching across columns --- .../components/resource-list/Cards/index.js | 4 ++-- .../components/resource-list/Cards/styles.js | 16 +++------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/client/src/frontend/components/resource-list/Cards/index.js b/client/src/frontend/components/resource-list/Cards/index.js index 9eabb38555..f96d28e1cb 100644 --- a/client/src/frontend/components/resource-list/Cards/index.js +++ b/client/src/frontend/components/resource-list/Cards/index.js @@ -29,14 +29,14 @@ export default class ResourceListCards extends PureComponent { {this.props.resources.map(resource => { return ( - +
  • - +
  • ); })}
    diff --git a/client/src/frontend/components/resource-list/Cards/styles.js b/client/src/frontend/components/resource-list/Cards/styles.js index 5aae82edcb..3fe3012517 100644 --- a/client/src/frontend/components/resource-list/Cards/styles.js +++ b/client/src/frontend/components/resource-list/Cards/styles.js @@ -5,22 +5,12 @@ export const List = styled.ul` --column-gap: 30px; ${listUnstyled} - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: 1fr; column-gap: var(--column-gap); row-gap: 18px; ${respond(`--column-gap: 4.858vw;`, 85)} -`; - -export const Item = styled.li` - flex-basis: 100%; - ${respond( - ` - flex-grow: 1; - flex-basis: calc(50% - var(--column-gap)); - `, - 75 - )} + ${respond(`grid-template-columns: repeat(2, 1fr);`, 75)} `; From 951794b05d86366d60f6419e047642d984de8d38 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Wed, 26 Feb 2025 16:47:13 -0800 Subject: [PATCH 09/11] [B] Adjust collecting toggle alignment --- .../src/theme/styles/components/frontend/collecting/toggle.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/theme/styles/components/frontend/collecting/toggle.js b/client/src/theme/styles/components/frontend/collecting/toggle.js index b2ed7dca90..82cd6cb6d6 100644 --- a/client/src/theme/styles/components/frontend/collecting/toggle.js +++ b/client/src/theme/styles/components/frontend/collecting/toggle.js @@ -51,6 +51,10 @@ export default ` white-space: nowrap; cursor: pointer; + &--inline { + margin-block-start: 3px; + } + &--project-cover { --toggle-size: 28px; --text-top-padding: 7px; From 1aa0830ef44efd26978016a851eb967be3068d34 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Thu, 27 Feb 2025 09:53:52 -0800 Subject: [PATCH 10/11] [B] Fix T&C link on sign up screen --- client/src/global/components/sign-in-up/AcceptTerms/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/global/components/sign-in-up/AcceptTerms/index.js b/client/src/global/components/sign-in-up/AcceptTerms/index.js index 4843aa77fe..71ce11a0e7 100644 --- a/client/src/global/components/sign-in-up/AcceptTerms/index.js +++ b/client/src/global/components/sign-in-up/AcceptTerms/index.js @@ -44,7 +44,7 @@ export default function AcceptTerms({ handleViewChange }) { i18nKey="forms.signin_overlay.accept_checkbox_label_truncated" values={{ installationName }} components={{ - termsLink: termsPage ? # : <> + termsLink: termsPage ? # : <> }} /> ); From 62a3d92ab2ee17fb16b3a1cab4baea59b814cf92 Mon Sep 17 00:00:00 2001 From: 1aurend Date: Thu, 27 Feb 2025 13:17:31 -0800 Subject: [PATCH 11/11] [B] Fix delete user notification content --- client/src/backend/containers/user/Wrapper.js | 5 +---- .../config/app/locale/en-US/json/shared/notifications.json | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/client/src/backend/containers/user/Wrapper.js b/client/src/backend/containers/user/Wrapper.js index bc40e4a450..abc1ed5c66 100644 --- a/client/src/backend/containers/user/Wrapper.js +++ b/client/src/backend/containers/user/Wrapper.js @@ -40,10 +40,7 @@ function UserWrapper({ match, route, history, confirm, location }) { const notifyDestroy = useNotification(u => ({ level: 0, id: `USER_DESTROYED_${u.id}`, - heading: t("notifications.reading_group_delete"), - body: t("notifications.delete_entity_body", { - title: u?.name - }), + heading: t("notifications.user_delete", { name: u.attributes.fullName }), expiration: 5000 })); diff --git a/client/src/config/app/locale/en-US/json/shared/notifications.json b/client/src/config/app/locale/en-US/json/shared/notifications.json index 355d5b983f..822794bb12 100644 --- a/client/src/config/app/locale/en-US/json/shared/notifications.json +++ b/client/src/config/app/locale/en-US/json/shared/notifications.json @@ -18,6 +18,7 @@ "resource_collection_delete": "The resource collection has been destroyed.", "resource_delete": "The resource has been destroyed.", "text_delete": "The text has been destroyed.", + "user_delete": "{{name}} has been removed.", "volume_body": "Volume #{{number}} has passed into the endless night.", "volume_delete": "The volume has been destroyed." }