Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Create palette from JSON file (resolves #1) #2

Merged
merged 58 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
43ba41e
feat: create palette from JSON file
klown Oct 2, 2023
2485833
fix: remove extra render() call
klown Oct 2, 2023
f1ac9e0
fix: add copyright and licence comment
klown Oct 2, 2023
9542e87
lint: remove errant import of `waitFor`
klown Oct 2, 2023
808b7d8
fix: switch to `.scss` (sass) for styles
klown Oct 4, 2023
47ab98c
refactor: group styles for `paletteCell` class
klown Oct 4, 2023
3906b19
fix: suppress implicit role (graphic) of `svg` elements in a palette …
klown Oct 4, 2023
25ab172
feat: use options block in json definition of palette cells
klown Oct 4, 2023
98aecfb
chore: use string constant for svg markup
klown Oct 11, 2023
a1a318d
chore: move rendering code for palette to `index.html`
klown Oct 12, 2023
7a2c857
chore: pass `options` block from json instead of individual properties
klown Oct 12, 2023
126de89
fix: add latest bmw palette json definition file with proper layout
klown Oct 13, 2023
d3db085
fix: pass `type` of bmw cell to `PaletteCell` component
klown Oct 13, 2023
3592783
fix: spelling error
klown Oct 13, 2023
ea5e80c
fix: lint error
klown Oct 13, 2023
a0080ca
feat: define TypesScript Type for PaletteCell `props` argument
klown Oct 13, 2023
a58d0fb
feat: use `SVGBuilder` to fetch svg to render within the cell
klown Oct 16, 2023
58ed03d
feat: make use of the svg builder codes in the latest blissary-bci-id…
klown Oct 17, 2023
43eafe7
feat: replace Bliss-Blissary-BCI-ID-Map submdodule with fetch()
klown Oct 18, 2023
77c240e
feat: share-able `BlissSymbol` component that combines svg and text l…
klown Oct 19, 2023
6be1737
feat: remove extra style and classes from `PaletteCell`'s `props` arg…
klown Oct 19, 2023
fc594f6
fix: remove debug statement and temporary comment
klown Oct 20, 2023
1088f9e
feat: add blissary id map code that loads the remote map
klown Oct 20, 2023
6a32931
fix: remove tests no longer relevant due to change in `PaletteCellPro…
klown Oct 20, 2023
4b05f39
feat: renamed `PaletteCell` to `ActionBmwCodeCell`
klown Oct 20, 2023
fd3f054
feat: renamed `type` value to `ActionBmwCodeCell` in `bmw_palette.json`
klown Oct 20, 2023
0b54137
feat: add a map for retrieving the component when rendering a cell type
cindyli Oct 20, 2023
fdb3d67
fix: remove a test file
cindyli Oct 20, 2023
8b7f61d
fix: add error handling and improve docs
cindyli Oct 21, 2023
f2b4048
fix: address review comments
cindyli Oct 23, 2023
0639ece
fix: remove a duplicate "of"
cindyli Oct 23, 2023
406d52f
Merge pull request #1 from cindyli/feat/add-cellType-registry
klown Oct 23, 2023
cb4afb8
feat: install BlissSVGBuilder from npm
klown Oct 24, 2023
3cbdbee
feat: remove top-level (aka, module level) await
klown Oct 30, 2023
278a67e
feat: modify jest config to include global fetch
klown Oct 30, 2023
bc98779
feat: add fetch() back for jest by using whatwg-fetch module
klown Oct 30, 2023
106fb01
chore: upgrade to bliss-svg-builder v0.1.0-alpha.4
klown Oct 31, 2023
7900134
fix: move location of `try {` statement to handle more errors
klown Nov 2, 2023
380dd91
chore: use latest `bmw_palette.json` from the baby-bliss-bot project
klown Nov 3, 2023
b398c6b
feat: add tests for BlissSymbol component
klown Nov 17, 2023
0a97b2a
chore: split the two `BlissSymbol` tests into two separate `test(...);`s
klown Nov 24, 2023
f5e7136
chore: rework `ActionBmwCodeCell` tests
klown Nov 24, 2023
da78a8b
feat: add aria markup for the <svg> element
klown Nov 24, 2023
36f197e
fix: remove lint exclusion for Bliss-Blissary-BCI-ID-Map folder
klown Nov 27, 2023
2819b29
chore: add comment regarding rationale for using whatwg-fetch in tes…
klown Nov 27, 2023
8118cd7
fix: use `rem` instead of `em` for styling
klown Nov 28, 2023
0c73c0d
chore: add tests for the `Palette` component
klown Nov 29, 2023
d75020b
feat: move main script to `index.js` and include it within `index.html`
klown Nov 29, 2023
4c20fcd
chore: remove debugging information
klown Nov 29, 2023
eeb4e77
fix: improve documentation for how to create palettes
klown Nov 29, 2023
e252bea
fix: add test for `blissaryIdMap()` when given unknown bci-av-id
klown Nov 29, 2023
7dfdf63
fix: add type declarations for known types
klown Nov 30, 2023
184498a
fix: remove disable styles
klown Nov 30, 2023
8038d14
fix: remove debug info for async loading of the Blissary-BCI-ID-Map
klown Dec 1, 2023
dd57a24
feat: remove question-mark svg for unknown bci-av-id
klown Dec 1, 2023
d0d5237
fix: change destructuring assignment to one statement
klown Dec 1, 2023
cabf34d
feat: consolidate type definitions into one shared file
klown Dec 14, 2023
352ce6c
fix: move property type definitions, as private, to their functional …
klown Dec 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .gitmodules
Empty file.
19 changes: 19 additions & 0 deletions docs/DeveloperDoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Developer Documentation

## How to render a palette

`Palette.ts` constructs a palette based on a JSON file that contains a list
of the cells in the palette. An example is found in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"An example is found ..." -> "An example can be found ..."

Copy link
Contributor Author

@klown klown Dec 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The active voice is preferable to the passive. The use of "can be" is passive. It might be better to say, "An example is available ...".

[`src/keyboards/bmw_palette.json`](../src/keyboards/bmw_palette.json). The
`cells` object is the list of all of the cells. Each cell has a `type` key and
an `options` key. The `type` value indicates which Preact component should be
used to render this cell. The `options` contains information to be passed to the
component.

## How to add a new cell type

When a new `type` value is introduced, developers need to:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it clearer to add a h2 title "How to add a new cell type" to the section starting from this line to the end of the document?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.


1. Create a new component to render the new cell type;
2. In `GlobalData.ts`, update `cellTypeRegistry` to add the entry that maps the
new type value to the actual component.
23 changes: 14 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" />
<title>Adaptive Palette</title>
</head>
<body>
<div id="app"></div>
</body>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" />
<title>Adaptive Palette</title>
</head>
<body>
<h2>Palette Based on JSON</h1>
<div id="bmwKeyCodes">
<script type="module">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do think about the idea that moves the javascript in this <script> tag to index.js that is then loaded into this page?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the code.

import "./src/index.js";
</script>
</div>
</body>
</html>
6 changes: 5 additions & 1 deletion jest.config.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
setupFiles: ["./setupFetchForJest.ts"],
verbose: true,
preset: "ts-jest",
testEnvironment: "jsdom",
Expand All @@ -10,5 +11,8 @@ module.exports = {
},
testPathIgnorePatterns: ["/node_modules/", "<rootDir>/dist/"],
transformIgnorePatterns: ["<rootDir>/dist/"],
moduleFileExtensions: ["mjs", "js", "jsx", "ts", "tsx", "json", "node"]
moduleFileExtensions: ["mjs", "js", "jsx", "ts", "tsx", "json", "node"],
moduleNameMapper: {
"^.+\\.(css|less|scss)$": "babel-jest"
},
};
18 changes: 15 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
"test": "jest"
},
"dependencies": {
"bliss-svg-builder": "^0.1.0-alpha.4",
"htm": "^3.1.1",
"preact": "^10.13.1",
"sass": "^1.65.1"
"sass": "^1.65.1",
"whatwg-fetch": "^3.6.19"
},
"devDependencies": {
"@babel/preset-env": "^7.22.14",
Expand Down
24 changes: 24 additions & 0 deletions setupFetchForJest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2023 Inclusive Design Research Centre, OCAD University
* All rights reserved.
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/inclusive-design/adaptive-palette/blob/main/LICENSE
*/

// There is an issue requesting the additions adding the fetch API to jest-dom
// for testing with node. Node.js Core has had an implementation of the fetch
// API since v17.5. However, jest-dom removes it. This comment in the issue
// suggests using whatwg's version of fetch() instead:
// https://github.com/jsdom/jsdom/issues/1724#issuecomment-720727999

import { fetch } from "whatwg-fetch";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you happen to have the solution article about using this npm package to fix the use of fetch() in the Jest, can you add a code comment to explain what this script is for as well as including the article? Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I have added a comment/link.


module.exports = {
globals: {
fetch: fetch
}
};
24 changes: 24 additions & 0 deletions src/ActionBmwCodeCell.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2023 Inclusive Design Research Centre, OCAD University
* All rights reserved.
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/inclusive-design/adaptive-palette/blob/main/LICENSE
*/

.actionBmwCodeCell {
border: 2px solid blue;
background-color: gray;
border-radius: 5px;
padding: 1rem;
font-size: 1rem;
text-align: center;

&:hover, &:focus {
background-color: lightblue;
color: #0000aa;
}
}
65 changes: 65 additions & 0 deletions src/ActionBmwCodeCell.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2023 Inclusive Design Research Centre, OCAD University
* All rights reserved.
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/inclusive-design/adaptive-palette/blob/main/LICENSE
*/

import { render, screen } from "@testing-library/preact";
import "@testing-library/jest-dom";
import { html } from "htm/preact";

import { initAdaptivePaletteGlobals } from "./GlobalData";
import { ActionBmwCodeCell } from "./ActionBmwCodeCell";

describe("ActionBmwCodeDell render tests", () => {

const TEST_CELL_ID = "uuid-of-some-kind";
const testCell = {
options: {
"label": "Bliss Language",
"rowStart": "3",
"rowSpan": "2",
"columnStart": "2",
"columnSpan": "1",
"bciAvId": [ 12335, "/", 8499 ] // VERB+EN
}
};

beforeAll(async () => {
await initAdaptivePaletteGlobals();
});

test("Single ActionBmwCodeCell rendering", async () => {

render(html`
<${ActionBmwCodeCell}
id="${TEST_CELL_ID}"
options=${testCell.options}
/>`
);

// Check the rendered cell
const button = await screen.findByRole("button", {name: testCell.options.label});

// Check that the ActionBmwCodeCell/button is rendered and has the correct
// attributes and text.
expect(button).toBeVisible();
expect(button).toBeValid();
expect(button.id).toBe(TEST_CELL_ID);
expect(button.getAttribute("class")).toBe("actionBmwCodeCell");
expect(button.textContent).toBe(testCell.options.label);

// Check the grid cell styles.
expect(button.style["grid-column"]).toBe("2 / span 1");
expect(button.style["grid-row"]).toBe("3 / span 2");

// Check disabled state (should be enabled)
expect(button.getAttribute("disabled")).toBe(null);
});

});
42 changes: 42 additions & 0 deletions src/ActionBmwCodeCell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2023 Inclusive Design Research Centre, OCAD University
* All rights reserved.
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/inclusive-design/adaptive-palette/blob/main/LICENSE
*/

import { html } from "htm/preact";
import { OptionsType } from "./index.d";
import { BlissSymbol } from "./BlissSymbol";
import "./ActionBmwCodeCell.scss";


type ActionBmwCodeCellPropsType = {
id: string,
options: OptionsType
};

export function ActionBmwCodeCell (props: ActionBmwCodeCellPropsType) {
const {
columnStart, columnSpan, rowStart, rowSpan, bciAvId, label
} = props.options;

const gridStyles = `
grid-column: ${columnStart} / span ${columnSpan};
grid-row: ${rowStart} / span ${rowSpan};
`;

return html`
<button id="${props.id}" class="actionBmwCodeCell" style="${gridStyles}" >
<${BlissSymbol}
bciAvId=${bciAvId}
label=${label}
isPresentation=true
/>
</button>
`;
}
117 changes: 117 additions & 0 deletions src/BlissSymbol.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright 2023 Inclusive Design Research Centre, OCAD University
* All rights reserved.
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* You may obtain a copy of the License at
* https://github.com/inclusive-design/adaptive-palette/blob/main/LICENSE
*/

import { render, screen } from "@testing-library/preact";
import "@testing-library/jest-dom";
import { html } from "htm/preact";

import { initAdaptivePaletteGlobals } from "./GlobalData";
import { BlissSymbol, GRAPHIC_ROLE } from "./BlissSymbol";

describe("BlissSymbol render tests", () => {
const singleBciAvId = {
bciAvId: 12335,
label: "VERB"
};

const arrayBciAvId = {
bciAvId: [12335, "/", 8499],
label: "VERB+S"
};
Comment on lines +20 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be clearer to split this test into two sections or two tests, one for testing the number bciAvId and the other for testing the array bciAvId.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, done.


const MOCK_LABEL_ID = "mockLabelId";
const UNKNOWN_BCI_AV_ID = -1;

beforeAll(async () => {
await initAdaptivePaletteGlobals();
});

test(`BlissSymbol defined by a single BCI_AV_ID (${singleBciAvId.label})`, async () => {
render(html`
<${BlissSymbol}
bciAvId="${singleBciAvId.bciAvId}"
label="${singleBciAvId.label}"
isPresentation=true
/>`
);
const blissSymbolLabelDiv = await screen.findByText(singleBciAvId.label);
expect(blissSymbolLabelDiv).toBeVisible();
expect(blissSymbolLabelDiv).toBeValid();

// Expect an <svg ...> element as the only sibling
const parentChildren = blissSymbolLabelDiv.parentNode.childNodes;
expect(parentChildren.length).toBe(2);
expect(parentChildren[0].nodeName).toBe("svg");
});

test("BlissSymbol when the SVG is unknown", async () => {
render(html`
<${BlissSymbol}
bciAvId="${UNKNOWN_BCI_AV_ID}"
label="${arrayBciAvId.label}"
isPresentation=true
/>`
);
const blissSymbolLabelDiv = await screen.findByText(arrayBciAvId.label);
const svgElement = blissSymbolLabelDiv.parentNode.querySelector("svg");
const parentChildren = blissSymbolLabelDiv.parentNode.childNodes;
expect(parentChildren.length).toBe(1);
expect(svgElement).toBe(null);
});

test(`BlissSymbol defined by an of BCI_AV_IDs (${arrayBciAvId.label})`, async () => {
render(html`
<${BlissSymbol}
bciAvId="${arrayBciAvId.bciAvId}"
label="${arrayBciAvId.label}"
isPresentation=true
/>`
);
const blissSymbolLabelDiv = await screen.findByText(arrayBciAvId.label);
expect(blissSymbolLabelDiv).toBeVisible();
expect(blissSymbolLabelDiv).toBeValid();
const parentChildren = blissSymbolLabelDiv.parentNode.childNodes;
expect(parentChildren.length).toBe(2);
expect(parentChildren[0].nodeName).toBe("svg");
});

test("BlissSymbol aria: when svg has no role)", async () => {
render(html`
<${BlissSymbol}
bciAvId="${arrayBciAvId.bciAvId}"
label="${arrayBciAvId.label}"
isPresentation=true
/>`
);
const blissSymbolLabelDiv = await screen.findByText(arrayBciAvId.label);
const svgElement = blissSymbolLabelDiv.parentNode.querySelector("svg");
expect(svgElement.getAttribute("aria-hidden")).toBe("true");
expect(svgElement.getAttribute("role")).toBe(null);
expect(svgElement.getAttribute("aria-labelledby")).toBe(null);
});

test("BlissSymbol aria: when svg has a graphic role)", async () => {
render(html`
<${BlissSymbol}
bciAvId="${arrayBciAvId.bciAvId}"
label="${arrayBciAvId.label}"
isPresentation=false
labelledBy=${MOCK_LABEL_ID}
/>`
);
const blissSymbolLabelDiv = await screen.findByText(arrayBciAvId.label);
const svgElement = blissSymbolLabelDiv.parentNode.querySelector("svg");
expect(svgElement.getAttribute("role")).toBe(GRAPHIC_ROLE);
expect(svgElement.getAttribute("aria-labelledby")).toBe(MOCK_LABEL_ID);
expect(svgElement.getAttribute("aria-hidden")).toBe(null);
});
});

Loading
Loading