Skip to content

Commit

Permalink
Merge pull request #376 from visdesignlab/373-text-sidebar
Browse files Browse the repository at this point in the history
Updates to Text Descriptions Sidebar
  • Loading branch information
NateLanza authored Sep 3, 2024
2 parents b602dad + d5ee030 commit 1f9e396
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 247 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ module.exports = {
'import/no-cycle': 'off',
'no-underscore-dangle': 'off',
'no-nested-ternary': 'off',
'jsx-a11y/tabindex-no-positive': 'off',
'no-bitwise': 'warn',
},
};
48 changes: 20 additions & 28 deletions e2e-tests/alttext.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,10 @@ test.beforeEach(async ({ page }) => {
test('Alt Text', async ({ page }) => {
await page.goto('http://localhost:3000/?workspace=Upset+Examples&table=simpsons&sessionId=193');

const altTextSidebarButton = await page.getByLabel('Alt Text Sidebar', { exact: true });
await expect(altTextSidebarButton).toBeVisible();
await altTextSidebarButton.click();

const altTextSidebar = await page.getByLabel('Accessibility Sidebar', { exact: true });
const altTextSidebar = await page.getByLabel('Alt Text and Plot Information Sidebar', { exact: true });
await expect(altTextSidebar).toBeVisible();

const altTextHeading = await page.getByRole('heading', { name: 'Accessibility Sidebar' });
const altTextHeading = await page.getByRole('heading', { name: 'Text Description' });
await expect(altTextHeading).toBeVisible();

/// /////////////////
Expand Down Expand Up @@ -76,7 +72,7 @@ test('Alt Text', async ({ page }) => {
// Plot Information
/// /////////////////
// Editing
const editPlotInformationButton = await page.getByLabel('Plot Information');
const editPlotInformationButton = await page.getByRole('button', { name: 'Add Plot Information' });
await expect(editPlotInformationButton).toBeVisible();
await editPlotInformationButton.click();

Expand Down Expand Up @@ -114,23 +110,23 @@ test('Alt Text', async ({ page }) => {
await expect(plotInformationOutput).toBeVisible();
await expect(plotInformationOutput).toHaveText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');

await expect(page.getByLabel('Accessibility Sidebar')).toContainText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');
await page.getByRole('button', { name: 'Save' }).click();

// Display
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('upset plot');
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('upset plot caption');
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('upset plot');
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('upset plot caption');
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');

/// /////////////////
// Short Description
/// /////////////////
await expect(page.getByText('This is an UpSet plot'))
.toContainText('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');
await page.getByLabel("Display Long Description").click();
await page.getByLabel("Display Long Description").click();
await page.getByRole('button', { name: 'Show More' }).click();
await page.getByRole('button', { name: 'Show Less' }).click();
await expect(page.getByText('This is an UpSet plot which')).toBeVisible();
await page.getByLabel("Display Long Description").click();
await page.getByRole('button', { name: 'Show More' }).click();

/// /////////////////
// Alt Text Output
Expand Down Expand Up @@ -187,31 +183,27 @@ test('Alt Text', async ({ page }) => {
/// /////////////////
// User Description Test
/// /////////////////
await page.getByLabel('View User Description(s)').check();
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('No user-generated description available.');
await page.getByLabel('Display Long Description').uncheck();
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('No user-generated description available.');

// User short
await page.getByRole('button', { name: 'Edit Text Description' }).click();
await page.getByRole('button', { name: 'Show Less' }).click();
await page.getByLabel('Alt Text Description Editor').click();
await page.getByText('This is an UpSet plot which').click();
await page.getByText('This is an UpSet plot which').fill('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the abcdefg largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the abcdefg largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the abcdefg largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');

// User long, switching while editing
await page.getByRole('button', { name: 'Edit Text Description' }).click();
await page.getByLabel('Display Long Description').check();
await page.getByLabel('Alt Text Description Editor').click();
await page.getByRole('button', { name: 'Show More' }).click();
await page.getByText('# UpSet Introduction This is').click();
await page.getByText('# UpSet Introduction This is').fill('# UpSet Introduction\nThis is an UpSet plot that visualizes set intersection. To learn about UpSet plots, visit https://upset.app.\n\n# Dataset Properties\nThe dataset contains 6 sets and 44 elements, of which 6 sets are shown in the plot.\n\n# Set Properties\nThe set sizes are diverging a lot, ranging from 3 to 18. The largest set is Male with 18 elements, followed by School with 6, Duff Fan with 6, Evil with 6, Power Plant with 5, and Blue Hair with 3.\n\n# Intersection Properties afdegb\nThe plot is sorted by size in ascending order. There are 12 non-empty intersections, all of which are shown in the plot. The largest 5 intersections are School, and Male (3), the empty intersection (3), Just Male (3), Duff Fan, Male, and Power Plant (3), and Evil, and Male (2).\n\n# Statistical Information\nThe average intersection size is 2, and the median is 2. The 90th percentile is 3, and the 10th percentile is 1. The largest set, Male, is present in 75.0% of all non-empty intersections. The smallest set, Blue Hair, is present in 16.7% of all non-empty intersections.\n\n# Trend Analysis\n The intersection sizes start from a value of 1 and then drastically rise up to 3. The empty intersection is present with a size of 3. An all set intersection is not present. The individual set intersections are large in size. The low degree set intersections lie in medium and largest sized intersections. The medium degree set intersections can be seen among small sized intersections. No high order intersections are present.\n\n');
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[id="Intersection\\ Properties\\ afdegb"]')).toContainText('Intersection Properties afdegb');

// Resetting descriptions
await page.getByRole('button', { name: 'Edit Text Description' }).click();
await page.getByLabel('Alt Text Description Editor').click();
await page.getByRole('button', { name: 'Reset Descriptions' }).click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[id="Intersection\\ Properties"]')).toContainText('Intersection Properties');
await page.getByLabel('Display Long Description').uncheck();
await expect(page.getByLabel('Accessibility Sidebar')).toContainText('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');
await page.getByRole('button', { name: 'Show Less' }).click();
await expect(page.getByLabel('Alt Text and Plot Information Sidebar')).toContainText('This is an UpSet plot which shows set intersection of 6 sets out of 6 sets and the largest intersection is School, and Male (3). The plot is sorted by size and 12 non-empty intersections are shown.');
});
2 changes: 1 addition & 1 deletion packages/app/src/atoms/altTextSidebarAtom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { atom } from 'recoil';

export const altTextSidebarAtom = atom<boolean>({
key: 'alt-text-sidebar-state',
default: false,
default: true,
});
6 changes: 3 additions & 3 deletions packages/app/src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const Header = ({ data }: { data: any }) => {
* "Tab indicies" refers to the number of tabIndex properties on elements in the sidebar
* @see AltTextSidebar to count the number of tab indices used
*/
const ALTTEXT_SIDEBAR_TABS = (isAltTextSidebarOpen ? 17 : 0);
const ALTTEXT_SIDEBAR_TABS = (isAltTextSidebarOpen ? 18 : 0);

const handleImportModalClose = () => {
setShowImportModal(false);
Expand Down Expand Up @@ -187,10 +187,10 @@ const Header = ({ data }: { data: any }) => {
setIsAltTextSidebarOpen(true);
}
}}
aria-label='Alt Text Sidebar'
aria-label='Text Descriptions (Alt Text) Sidebar'
tabIndex={2}
>
Text Description
Text Descriptions
</Button>
<Link
to={`/datatable${getQueryParam()}`}
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { UpsetConfig } from './types';
export const DefaultConfig: UpsetConfig = {
// Calls to the alttext API may error if these are not set
plotInformation: {
description: '',
sets: '',
items: '',
caption: '[Caption]',
title: '[Title]',
description: null,
sets: null,
items: null,
caption: null,
title: null,
},
horizontal: false,
firstAggregateBy: 'None',
Expand Down
43 changes: 17 additions & 26 deletions packages/core/src/typecheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,21 @@ export function isBookmarkedSelection(b: unknown): b is BookmarkedSelection {
&& isElementSelection((b as BookmarkedSelection).selection);
}

/**
* Type guard for PlotInformation
* @param p variable to check
* @returns {boolean}
*/
export function isPlotInformation(p: unknown): p is PlotInformation {
return isObject(p)
&& Object.hasOwn(p, 'description')
&& Object.hasOwn(p, 'sets')
&& Object.hasOwn(p, 'items')
&& (typeof (p as PlotInformation).description === 'string' || (p as PlotInformation).description === null)
&& (typeof (p as PlotInformation).sets === 'string' || (p as PlotInformation).sets === null)
&& (typeof (p as PlotInformation).items === 'string' || (p as PlotInformation).items === null);
}

/**
* Determines if the given object is a valid UpsetConfig using the CURRENT version.
* @privateRemarks
Expand Down Expand Up @@ -305,32 +320,8 @@ export function isUpsetConfig(config: unknown): config is UpsetConfig {

// Check that the fields are of the correct type
// Start with plot info
if (typeof plotInformation !== 'object') {
console.warn('Upset config error: Plot information is not an object');
return false;
}
if (!Object.hasOwn(plotInformation, 'description')) {
console.warn('Upset config error: Plot information missing description');
return false;
}
if (!Object.hasOwn(plotInformation, 'sets')) {
console.warn('Upset config error: Plot information missing sets');
return false;
}
if (!Object.hasOwn(plotInformation, 'items')) {
console.warn('Upset config error: Plot information missing items');
return false;
}
if (typeof (plotInformation as PlotInformation).description !== 'string') {
console.warn('Upset config error: Plot description is not a string');
return false;
}
if (typeof (plotInformation as PlotInformation).sets !== 'string') {
console.warn('Upset config error: Plot sets is not a string');
return false;
}
if (typeof (plotInformation as PlotInformation).items !== 'string') {
console.warn('Upset config error: Plot items is not a string');
if (!isPlotInformation(plotInformation)) {
console.warn('Upset config error: Invalid plot information');
return false;
}

Expand Down
16 changes: 8 additions & 8 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ export type Meta = {

/**
* Textual information about the plot; included in the UpsetConfig
* @privateRemarks This is typechecked in isUpsetConfig; changes here must be reflected there
* @privateRemarks This is typechecked by isPlotinformation in typecheck.ts; changes here must be reflected there
*/
export type PlotInformation = {
/** User-generated plot description */
description?: string;
description: string | null;
/** User-generated name to use for sets in the plot (ie "genres") */
sets?: string;
sets: string | null;
/** User-generated name for items in the dataset (ie "movies") */
items?: string;
items: string | null;
/** User-defined plot title */
title?: string;
title: string | null;
/** User-defined plot caption (for sighted users) */
caption?: string;
caption: string | null;
};

/**
Expand Down Expand Up @@ -355,12 +355,12 @@ export type AltText = {
/**
* The long description for the Upset plot.
*/
longDescription: string;
longDescription: string | null;

/**
* The short description for the Upset plot.
*/
shortDescription: string;
shortDescription: string | null;

/**
* The technique description for the Upset plot.
Expand Down
Loading

0 comments on commit 1f9e396

Please sign in to comment.