Skip to content

Commit

Permalink
Merge branch 'master' into bug_viewer_crash
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabian Stoehr committed Jan 16, 2025
2 parents 13c7a4a + 88cc3f9 commit c095751
Show file tree
Hide file tree
Showing 51 changed files with 341 additions and 337 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Node.js CI

on:
push:
branches: [ master ]
branches: [ main ]
pull_request:
branches: [ master ]
branches: [ main ]

jobs:
build:
Expand All @@ -23,7 +23,7 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- run: npm test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Contributions to Mirador are always welcome!

It is always helpful to begin any large change by submitting an issue or engaging with the Mirador community. Mirador 3.0 and beyond adheres to [semantic versioning](https://semver.org/) so that adopters and contributors can better understand what changes can be expected in released versions of the software.

All contributions should be submitted as a [GitHub pull request](https://help.github.com/articles/about-pull-requests/) to the master branch. Pull requests must be reviewed and accepted by another Mirador maintainer and pass all continuous integration checks. Contributions should have tests for the feature or bug fix, documentation, should maintain high code coverage, and should conform to the Mirador agreed-upon coding style. Contributions should not include a “built” version of Mirador—this will help to reduce merge conflicts.
All contributions should be submitted as a [GitHub pull request](https://help.github.com/articles/about-pull-requests/) to the main branch. Pull requests must be reviewed and accepted by another Mirador maintainer and pass all continuous integration checks. Contributions should have tests for the feature or bug fix, documentation, should maintain high code coverage, and should conform to the Mirador agreed-upon coding style. Contributions should not include a “built” version of Mirador—this will help to reduce merge conflicts.

### Code of Conduct
Everyone interacting in this community is expected to follow the [Mirador Code of Conduct](https://github.com/ProjectMirador/mirador/blob/master/CODE_OF_CONDUCT.md).
Everyone interacting in this community is expected to follow the [Mirador Code of Conduct](https://github.com/ProjectMirador/mirador/blob/main/CODE_OF_CONDUCT.md).

### Accessibility
Mirador 3 aims to comply with the [Web Content Accessibility Guidelines (WCAG) 2.1 AA](https://www.w3.org/WAI/standards-guidelines/wcag/). These guidelines, authored by the W3C and legally adopted [internationally](https://www.w3.org/WAI/policies/?q=wcag-20), are comprehensive and provide the success criteria designers and developers need to build accessible web applications.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Mirador
![Node.js CI](https://github.com/ProjectMirador/mirador/workflows/Node.js%20CI/badge.svg) [![codecov](https://codecov.io/gh/ProjectMirador/mirador/branch/master/graph/badge.svg)](https://codecov.io/gh/ProjectMirador/mirador)
![Node.js CI](https://github.com/ProjectMirador/mirador/workflows/Node.js%20CI/badge.svg) [![codecov](https://codecov.io/gh/ProjectMirador/mirador/branch/main/graph/badge.svg)](https://codecov.io/gh/ProjectMirador/mirador)

## For Mirador Users
You can quickly use and configure Mirador by remixing the [mirador-start](https://mirador-start.glitch.me/) Glitch.
Expand All @@ -14,7 +14,7 @@ $ npm install mirador
$ yarn add mirador
```

If you are interested in integrating Mirador with plugins into your project, we recommend using webpack or parcel to integrate the es version of the packages. Examples are here:
If you are interested in integrating Mirador with plugins into your project, we recommend using vite to integrate the es version of the packages. Examples are here:

[https://github.com/ProjectMirador/mirador-integration](https://github.com/ProjectMirador/mirador-integration)

Expand All @@ -24,7 +24,7 @@ If you want to simply embed Mirador in an HTML page without further customizatio
<script src="https://unpkg.com/mirador@latest/dist/mirador.min.js"></script>
```

More examples of embedding Mirador can be found at [https://github.com/ProjectMirador/mirador/wiki/M3-Embedding-in-Another-Environment#in-an-html-document-with-javascript](https://github.com/ProjectMirador/mirador/wiki/M3-Embedding-in-Another-Environment#in-an-html-document-with-javascript).
More examples of embedding Mirador can be found at [https://github.com/ProjectMirador/mirador/wiki/M3-Embedding-in-Another-Environment#in-an-html-document-with-javascript](https://github.com/ProjectMirador/mirador/wiki/Embedding-in-Another-Environment).

## Adding translations to Mirador
For help with adding a translation, see [src/locales/README.md](src/locales/README.md)
Expand Down
2 changes: 1 addition & 1 deletion __tests__/src/components/AccessTokenSender.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('AccessTokenSender', () => {
it('renders properly', () => {
const { container } = createWrapper({ url: 'http://example.com' });

expect(container.querySelector('iframe')).toHaveAttribute('src', 'http://example.com?origin=http://localhost&messageId=http://example.com'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container
expect(container.querySelector('iframe')).toHaveAttribute('src', 'http://example.com/?origin=http%3A%2F%2Flocalhost&messageId=http%3A%2F%2Fexample.com'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container
});

it('triggers an action when the iframe sends a message', () => {
Expand Down
3 changes: 1 addition & 2 deletions __tests__/src/components/CanvasInfo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ describe('CanvasInfo', () => {
canvasLabel="The Canvas Label"
canvasDescription="The Canvas Description"
canvasMetadata={metadata}
id="xyz"
/>,
);
});
Expand Down Expand Up @@ -45,7 +44,7 @@ describe('CanvasInfo', () => {
describe('when metadata is not present', () => {
beforeEach(() => {
render(
<CanvasInfo id="xyz" />,
<CanvasInfo />,
);
});

Expand Down
1 change: 0 additions & 1 deletion __tests__/src/components/CollectionInfo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { CollectionInfo } from '../../../src/components/CollectionInfo';
function createWrapper(props) {
return render(
<CollectionInfo
id="test"
collectionPath={[1, 2]}
showCollectionDialog={() => {}}
{...props}
Expand Down
1 change: 1 addition & 0 deletions __tests__/src/components/GalleryViewThumbnail.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ describe('GalleryView', () => {
describe('on-demand annotation fetching', () => {
const canvas = {
getHeight: () => 50,
getLabel: () => ({ getValue: () => 'label' }),
getServices: vi.fn(),
getThumbnail: vi.fn(),
getType: vi.fn(),
Expand Down
3 changes: 1 addition & 2 deletions __tests__/src/components/ManifestInfo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ describe('ManifestInfo', () => {
beforeEach(() => {
render(
<ManifestInfo
id="xyz"
manifestLabel="The Manifest Label"
manifestDescription="The Manifest Description"
manifestMetadata={metadata}
Expand Down Expand Up @@ -42,7 +41,7 @@ describe('ManifestInfo', () => {
describe('when metadata is not present', () => {
beforeEach(() => {
render(
<ManifestInfo id="xyz" />,
<ManifestInfo />,
);
});

Expand Down
4 changes: 2 additions & 2 deletions __tests__/src/components/WindowSideBarCanvasPanel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ function createWrapper(props) {
let sequences;

if (props.multipleSequences) {
sequences = [{ id: 'a', label: 'seq1' },
{ id: 'b', label: 'seq2' }];
sequences = [{ getLabel: () => ({ getValue: () => undefined }), id: 'a', label: 'seq1' },
{ getLabel: () => ({ getValue: () => undefined }), id: 'b', label: 'seq2' }];
} else {
sequences = Utils.parseManifest(manifestJson).getSequences();
}
Expand Down
2 changes: 1 addition & 1 deletion __tests__/src/components/WindowTopMenuButton.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ describe('WindowTopMenuButton', () => {
render(<Subject />);
await user.click(screen.getByLabelText('Window views & thumbnail display'));
// when 'open' is true, aria-owns is set to the id of the window
expect(screen.getByLabelText('Window views & thumbnail display')).toHaveAttribute('aria-owns', 'window-menu_xyz'); // eslint-disable-line testing-library/no-node-access
expect(screen.getByLabelText('Window views & thumbnail display')).toHaveAttribute('aria-owns'); // eslint-disable-line testing-library/no-node-access
});
});
14 changes: 7 additions & 7 deletions __tests__/src/components/WorkspaceOptionsMenu.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ describe('WorkspaceOptionsMenu', () => {

it('renders the export dialog when export option is clicked', async () => {
render(<Subject anchorEl={screen.getByTestId('menu-trigger-button')} open />);
expect(document.querySelector('#workspace-export')).not.toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access
expect(screen.queryByRole('heading', { name: 'Export workspace' })).not.toBeInTheDocument();

await user.click(screen.getAllByRole('menuitem')[0]);
expect(document.querySelector('#workspace-export')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access
await user.click(screen.getByRole('menuitem', { name: 'Export workspace' }));
expect(screen.getByRole('heading', { name: 'Export workspace' })).toBeInTheDocument();
});

it('renders the import dialog when imporrt option is clicked', async () => {
it('renders the import dialog when import option is clicked', async () => {
render(<Subject anchorEl={screen.getByTestId('menu-trigger-button')} open />);
expect(document.querySelector('#workspace-import')).not.toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access
expect(screen.queryByRole('heading', { name: 'Import workspace' })).not.toBeInTheDocument();

await user.click(screen.getAllByRole('menuitem')[1]);
expect(document.querySelector('#workspace-import')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access
await user.click(screen.getByRole('menuitem', { name: 'Import workspace' }));
expect(screen.getByRole('heading', { name: 'Import workspace' })).toBeInTheDocument();
});

it('fires the correct callbacks on menu close', async () => {
Expand Down
14 changes: 0 additions & 14 deletions __tests__/src/selectors/manifests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,6 @@ describe('getManifestoInstance', () => {
const received = getManifestoInstance(state, { manifestId: 'x' });
expect(received.id).toEqual('http://iiif.io/api/presentation/2.1/example/fixtures/19/manifest.json');
});
it('creates a manifesto collection instance and patches getSequences', () => {
const state = { manifests: { x: { json: collection } } };

const received = getManifestoInstance(state, { manifestId: 'x' });
expect(typeof received.getSequences).toBe('function');

expect(received.getSequences()).toEqual([]);
});
it('is cached based off of input props', () => {
const state = { manifests: { x: { json: manifestFixture019 } } };
const received = getManifestoInstance(state, { manifestId: 'x' });
expect(getManifestoInstance(state, { manifestId: 'x' })).toBe(received);
expect(getManifestoInstance(state, { manifestId: 'x', windowId: 'y' })).not.toBe(received);
});
});

describe('getManifestLogo()', () => {
Expand Down
6 changes: 5 additions & 1 deletion src/components/AccessTokenSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ export function AccessTokenSender({ handleAccessTokenMessage, url = undefined })

if (!url) return null;

const src = new URL(url);
src.searchParams.append('origin', window.origin);
src.searchParams.append('messageId', url);

/**
login, clickthrough/kiosk open @id, wait for close
external, no-op
*/
return (
<IIIFIFrameCommunication
src={`${url}?origin=${window.origin}&messageId=${url}`}
src={src.toString()}
title="AccessTokenSender"
handleReceiveMessage={onReceiveAccessTokenMessage}
/>
Expand Down
21 changes: 12 additions & 9 deletions src/components/AppProviders.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import createI18nInstance from '../i18n';
import FullScreenContext from '../contexts/FullScreenContext';
import LocaleContext from '../contexts/LocaleContext';

/**
* Allow applications to opt-out of (or provide their own) drag and drop context
Expand Down Expand Up @@ -119,15 +120,17 @@ export function AppProviders({
return (
<FullScreenShim>
<StoreAwareI18nextProvider language={language} translations={translations}>
<StyledEngineProvider injectFirst>
<CacheProvider value={theme.direction === 'rtl' ? cacheRtl : cacheDefault}>
<ThemeProvider theme={createTheme((theme))}>
<MaybeDndProvider dndManager={dndManager}>
{children}
</MaybeDndProvider>
</ThemeProvider>
</CacheProvider>
</StyledEngineProvider>
<LocaleContext.Provider value={language}>
<StyledEngineProvider injectFirst>
<CacheProvider value={theme.direction === 'rtl' ? cacheRtl : cacheDefault}>
<ThemeProvider theme={createTheme((theme))}>
<MaybeDndProvider dndManager={dndManager}>
{children}
</MaybeDndProvider>
</ThemeProvider>
</CacheProvider>
</StyledEngineProvider>
</LocaleContext.Provider>
</StoreAwareI18nextProvider>
</FullScreenShim>
);
Expand Down
11 changes: 6 additions & 5 deletions src/components/CanvasInfo.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useId } from 'react';
import PropTypes from 'prop-types';
import Typography from '@mui/material/Typography';
import { useTranslation } from 'react-i18next';
Expand All @@ -13,24 +14,25 @@ export function CanvasInfo({
canvasDescription = null,
canvasLabel = null,
canvasMetadata = [],
id,
index = 1,
totalSize = 1,
}) {
const { t } = useTranslation();
const id = useId();
const titleId = useId();
const pluginProps = arguments[0]; // eslint-disable-line prefer-rest-params

return (
<CollapsibleSection
id={`${id}-currentItem-${index}`}
id={id}
label={t('currentItem', { context: `${index + 1}/${totalSize}` })}
>
{canvasLabel && (
<Typography
aria-labelledby={
`${id}-currentItem-${index} ${id}-currentItem-${index}-heading`
`${id} ${titleId}`
}
id={`${id}-currentItem-${index}-heading`}
id={titleId}
variant="h4"
component="h5"
>
Expand All @@ -56,7 +58,6 @@ CanvasInfo.propTypes = {
canvasDescription: PropTypes.string,
canvasLabel: PropTypes.string,
canvasMetadata: PropTypes.array, // eslint-disable-line react/forbid-prop-types
id: PropTypes.string.isRequired,
index: PropTypes.number,
totalSize: PropTypes.number,
};
12 changes: 2 additions & 10 deletions src/components/CanvasLayers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next';
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
import MiradorMenuButton from '../containers/MiradorMenuButton';
import IIIFThumbnail from '../containers/IIIFThumbnail';
import { IIIFResourceLabel } from './IIIFResourceLabel';

const StyledDragHandle = styled('div')(({ theme }) => ({
alignItems: 'center',
Expand All @@ -40,15 +41,6 @@ const reorder = (list, startIndex, endIndex) => {
return result;
};

/** */
function getUseableLabel(resource, index) {
return (resource
&& resource.getLabel
&& resource.getLabel().length > 0)
? resource.getLabel().getValue()
: String(index + 1);
}

/** @private */
function Layer({
resource, layerMetadata = {}, index, handleOpacityChange, setLayerVisibility, moveToTop,
Expand Down Expand Up @@ -78,7 +70,7 @@ function Layer({
component="div"
variant="body1"
>
{getUseableLabel(resource, index)}
<IIIFResourceLabel resource={resource} fallback={index + 1} />
<div>
<MiradorMenuButton aria-label={t(layer.visibility ? 'layer_hide' : 'layer_show')} edge="start" size="small" onClick={() => { setLayerVisibility(resource.id, !layer.visibility); }}>
{ layer.visibility ? <VisibilityIcon /> : <VisibilityOffIcon /> }
Expand Down
18 changes: 5 additions & 13 deletions src/components/CollectionDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import CollapsibleSection from '../containers/CollapsibleSection';
import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent';
import ManifestInfo from '../containers/ManifestInfo';
import WorkspaceContext from '../contexts/WorkspaceContext';
import { IIIFResourceLabel } from './IIIFResourceLabel';

const StyledScrollIndicatedDialogContent = styled(ScrollIndicatedDialogContent)(() => ({
padding: (theme) => theme.spacing(1),
Expand All @@ -38,15 +39,6 @@ const StyledCollectionFilter = styled('div')(() => ({
paddingTop: 0,
}));

/** */
function getUseableLabel(resource, index) {
return (resource
&& resource.getLabel
&& resource.getLabel().length > 0)
? resource.getLabel().getValue()
: String(index + 1);
}

/** */
const Placeholder = ({ onClose, container }) => (
<Dialog
Expand Down Expand Up @@ -149,7 +141,7 @@ export function CollectionDialog({
{ t(isMultipart ? 'multipartCollection' : 'collection') }
</Typography>
<Typography component="div" variant="h3">
{getUseableLabel(manifest)}
<IIIFResourceLabel resource={manifest} />
</Typography>
</DialogTitle>
<StyledScrollIndicatedDialogContent>
Expand All @@ -158,7 +150,7 @@ export function CollectionDialog({
startIcon={<ArrowBackIcon />}
onClick={() => goToPreviousCollection()}
>
{getUseableLabel(collection)}
<IIIFResourceLabel resource={collection} />
</Button>
)}

Expand Down Expand Up @@ -204,7 +196,7 @@ export function CollectionDialog({
onClick={() => { selectCollection(c); }}
variant="multiline"
>
{getUseableLabel(c)}
<IIIFResourceLabel resource={c} />
</MenuItem>
))
}
Expand All @@ -219,7 +211,7 @@ export function CollectionDialog({
onClick={() => { selectManifest(m); }}
variant="multiline"
>
{getUseableLabel(m)}
<IIIFResourceLabel resource={m} />
</MenuItem>
))
}
Expand Down
Loading

0 comments on commit c095751

Please sign in to comment.