Skip to content

Commit

Permalink
feat: UILD-420: Compare Bib Resources | Linked
Browse files Browse the repository at this point in the history
  • Loading branch information
s3fs committed Dec 25, 2024
1 parent 61f2c27 commit 0326c73
Show file tree
Hide file tree
Showing 27 changed files with 550 additions and 171 deletions.
4 changes: 0 additions & 4 deletions src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ h6 {
line-height: 1.1;
}

h3 {
margin: 0;
}

select,
input {
&:disabled {
Expand Down
6 changes: 6 additions & 0 deletions src/assets/times-circle-12.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/assets/transfer-16.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/common/constants/search.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ export type AdvancedSearchSchema = AdvancedSearchSchemaRow[];

export const SEARCH_RESULTS_LIMIT = 10;

export const MIN_AMT_OF_INSTANCES_TO_COMPARE = 2;

export const BROWSE_PRECEDING_RECORDS_COUNT = 5;

export const SELECT_IDENTIFIERS = Object.values(SearchIdentifiers);
Expand Down
5 changes: 5 additions & 0 deletions src/common/constants/uiElements.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ export enum DropdownItemType {
customComponent = 'customComponent',
}

export enum FullDisplayType {
Basic = 'basic',
Comparison = 'comparison',
}

export enum AriaModalKind {
Basic = 'Basic',
AdvancedSearch = 'Advanced search',
Expand Down
11 changes: 10 additions & 1 deletion src/common/helpers/recordFormatting.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
NON_BF_RECORD_CONTAINERS,
NON_BF_RECORD_ELEMENTS,
} from '@common/constants/bibframeMapping.constants';
import { getRecordPropertyData } from './record.helper';
import { getEditingRecordBlocks, getRecordPropertyData, unwrapRecordValuesFromCommonContainer } from './record.helper';
import { Row } from '@components/Table';

export const formatRecord = ({
Expand Down Expand Up @@ -267,3 +267,12 @@ export const formatDependeciesTable = (deps: Record<string, unknown>[]): Row[] =
};
}) as Row[];
};

export const getReferenceIdsRaw = (record: RecordEntry) => {
if (!record) return;

const contents = unwrapRecordValuesFromCommonContainer(record);
const { block, reference } = getEditingRecordBlocks(contents);

if (block && reference) return getReferenceIds(record, block, reference?.key);
};
9 changes: 6 additions & 3 deletions src/common/hooks/useConfig.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getPrimaryEntitiesFromRecord, getRecordTitle } from '@common/helpers/re
import { useInputsState, useProfileState } from '@src/store';
import { useProcessedRecordAndSchema } from './useProcessedRecordAndSchema.hook';
import { useServicesContext } from './useServicesContext';
import { getReferenceIdsRaw } from '@common/helpers/recordFormatting.helper';

export type PreviewParams = {
noStateUpdate?: boolean;
Expand Down Expand Up @@ -39,7 +40,7 @@ export const useConfig = () => {
setInitialSchemaKey,
setSchema,
} = useProfileState();
const { setUserValues, previewContent, setPreviewContent, setSelectedRecordBlocks, setSelectedEntries } =
const { setUserValues, setPreviewContent, setSelectedRecordBlocks, setSelectedEntries } =
useInputsState();
const { getProcessedRecordAndSchema } = useProcessedRecordAndSchema();
const isProcessingProfiles = useRef(false);
Expand Down Expand Up @@ -113,6 +114,7 @@ export const useConfig = () => {
const recordData = record?.resource || {};
const recordTitle = getRecordTitle(recordData as RecordEntry);
const entities = getPrimaryEntitiesFromRecord(record as RecordEntry);
const referenceIds = getReferenceIdsRaw(record as RecordEntry);

if (selectedProfile) {
!previewParams?.noStateUpdate && setSelectedProfile(selectedProfile);
Expand All @@ -126,15 +128,16 @@ export const useConfig = () => {
});

if (previewParams && recordId) {
setPreviewContent([
...(previewParams.singular ? [] : previewContent.filter(({ id }) => id !== recordId)),
setPreviewContent(prev => [
...(previewParams.singular ? [] : prev.filter(({ id }) => id !== recordId)),
{
id: recordId,
base: updatedSchema,
userValues: userValuesService.getAllValues(),
initKey,
title: recordTitle,
entities,
referenceIds,
},
]);
}
Expand Down
9 changes: 5 additions & 4 deletions src/common/hooks/useSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { generateSearchParamsState } from '@common/helpers/search.helper';
import { usePagination } from '@common/hooks/usePagination';
import { useSearchContext } from '@common/hooks/useSearchContext';
import { useFetchSearchData } from '@common/hooks/useFetchSearchData';
import { useInputsState, useLoadingState, useSearchState } from '@src/store';
import { useInputsState, useLoadingState, useSearchState, useUIState } from '@src/store';
import { FullDisplayType } from '@common/constants/uiElements.constants';

export const useSearch = () => {
const {
Expand Down Expand Up @@ -39,7 +40,7 @@ export const useSearch = () => {
setFacetsBySegments,
resetFacetsBySegments,
} = useSearchState();

const { fullDisplayComponentType } = useUIState();
const { fetchData } = useFetchSearchData();
const {
getCurrentPageNumber,
Expand Down Expand Up @@ -72,7 +73,7 @@ export const useSearch = () => {

const submitSearch = useCallback(() => {
clearPagination();
resetPreviewContent();
fullDisplayComponentType !== FullDisplayType.Comparison && resetPreviewContent();
updateFacetsBySegments(query, searchBy, facets);

if (hasSearchParams) {
Expand All @@ -90,7 +91,7 @@ export const useSearch = () => {
setSearchBy(defaultSearchBy);
setQuery('');
setMessage('');
resetPreviewContent();
fullDisplayComponentType !== FullDisplayType.Comparison && resetPreviewContent();
updateFacetsBySegments('', defaultSearchBy, {} as Limiters);
}, [defaultSearchBy]);

Expand Down
86 changes: 86 additions & 0 deletions src/components/Comparison/Comparison.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.comparison {
display: flex;
flex-direction: column;
width: 700px;
border-left: 1px solid rgba(0, 0, 0, 0.1);

header {
display: flex;
flex-direction: column;

h2 {
display: flex;
align-items: center;
gap: 0.2rem;
font-size: 0.875rem;
line-height: normal;
}

.heading,
.subheading {
padding: 0.5rem 0.7rem;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);

> * {
font-size: 0.875rem;
font-weight: 700;
}
}
}

&-contents {
display: flex;
flex-grow: 1;
overflow: hidden;

.entry {
width: 100%;
min-width: 50%;
overflow-x: hidden;
overflow-y: scroll;
flex: 1;
border-right: 1px solid rgba(0, 0, 0, 0.1);

&-header {
display: flex;
flex-direction: column;
gap: 0.2rem;
padding: 0.938rem;

&-controls {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
}

.preview-entity {
border-right: none;
}
}

.titled-preview {
width: 100%;
}

.insufficient-resource-amt {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
align-self: center;
width: 100%;
font-size: 1.138rem;
color: rgba(0, 0, 0, 0.62);

svg {
width: 2.5rem;
}
}
}
}
127 changes: 127 additions & 0 deletions src/components/Comparison/Comparison.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { FormattedMessage, useIntl } from 'react-intl';
import { Pagination } from '@components/Pagination';
import { useState } from 'react';
import { useInputsState, useSearchState, useUIState } from '@src/store';
import { Button, ButtonType } from '@components/Button';
import Times16 from '@src/assets/times-16.svg?react';
import TimesCircle12 from '@src/assets/times-circle-12.svg?react';
import Transfer16 from '@src/assets/transfer-16.svg?react';
import GeneralSearch from '@src/assets/general-search.svg?react';
import { Preview } from '@components/Preview';
import { PreviewActionsDropdown } from '@components/PreviewActionsDropdown';
import { ResourceType } from '@common/constants/record.constants';
import { generateEditResourceUrl } from '@common/helpers/navigation.helper';
import { useNavigateToEditPage } from '@common/hooks/useNavigateToEditPage';
import './Comparison.scss';

export const Comparison = () => {
const { formatMessage } = useIntl();
const { previewContent, setPreviewContent, resetPreviewContent } = useInputsState();
const { resetSelectedInstances } = useSearchState();
const { resetFullDisplayComponentType } = useUIState();
const { navigateToEditPage } = useNavigateToEditPage();
const [currentPage, setCurrentPage] = useState(0);

const handleCloseComparison = () => {
resetPreviewContent();
resetFullDisplayComponentType();
resetSelectedInstances();
};

const handleRemoveComparisonItem = (id: string) => {
setPreviewContent(prev => prev.filter(({ id: prevId }) => prevId !== id));
};

const handleNavigateToOwnEditPage = (id: string) => navigateToEditPage(generateEditResourceUrl(id));
const totalPages = (previewContent.length > 1 ? previewContent.length : 2) - 1;

return (
<section className="comparison">
<header>
<div className="heading">
<Button
data-testid="close-comparison-section"
type={ButtonType.Icon}
onClick={handleCloseComparison}
className="nav-close"
ariaLabel={formatMessage({ id: 'ld.aria.comparison.close' })}
>
<Times16 />
</Button>
<h2>
<Transfer16 />
<FormattedMessage id="ld.compareResources" />
</h2>
<span className="empty-block" />
</div>
<div className="subheading">
<span>
<FormattedMessage id="ld.nResourcesSelected" values={{ n: previewContent.length }} />
</span>
<Button
data-testid="clear-comparison-selections"
type={ButtonType.Icon}
onClick={resetPreviewContent}
disabled={!previewContent.length}
className="nav-close"
>
<TimesCircle12 />
<FormattedMessage id="ld.clearSelections" />
</Button>
</div>
</header>
<div className="comparison-contents">
{previewContent
.slice(currentPage, currentPage + 2)
.map(({ initKey, base, userValues, id, title, referenceIds }) => (
<section key={id} className='entry'>
<div className="entry-header">
<div className="entry-header-controls">
<Button
data-testid="remove-comparison-entry"
type={ButtonType.Icon}
onClick={() => handleRemoveComparisonItem(id)}
className="nav-close"
ariaLabel={formatMessage({ id: 'ld.aria.comparison.removeEntry' })}
>
<Times16 />
</Button>
<PreviewActionsDropdown
ownId={id}
referenceId={referenceIds?.[0]?.id as unknown as string}
entityType={ResourceType.instance}
handleNavigateToEditPage={() => handleNavigateToOwnEditPage(id)}
/>
</div>
<h3>{title}</h3>
</div>
<Preview
altInitKey={initKey}
altSchema={base}
altUserValues={userValues}
forceRenderAllTopLevelEntities
/>
</section>
))}
{previewContent.length <= 1 && (
<div className="insufficient-resource-amt">
<GeneralSearch />
<FormattedMessage
id={!previewContent.length ? 'ld.chooseTwoResourcesCompare' : 'ld.chooseOneResourceCompare'}
/>
</div>
)}
</div>
<nav aria-label={formatMessage({ id: 'ld.selectedResources' })}>
<Pagination
currentPage={currentPage}
onNextPageClick={() => setCurrentPage(prev => prev + 1)}
onPrevPageClick={() => setCurrentPage(prev => prev - 1)}
totalPages={totalPages}
totalResultsCount={totalPages}
showCount
/>
</nav>
</section>
);
};
1 change: 1 addition & 0 deletions src/components/Comparison/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Comparison } from './Comparison';
3 changes: 0 additions & 3 deletions src/components/FullDisplay/FullDisplay.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
.full-display {
&-container {
display: flex;
flex-direction: row;
gap: 0.5rem;
width: 540px;
border-left: 1px solid rgba(0, 0, 0, 0.1);

Expand Down
Loading

0 comments on commit 0326c73

Please sign in to comment.