Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
shemy-gan committed May 13, 2021
2 parents 7e6aa46 + e98f6da commit 6381862
Show file tree
Hide file tree
Showing 49 changed files with 1,289 additions and 754 deletions.
1 change: 1 addition & 0 deletions .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

yarn workspaces run lint-staged
6 changes: 5 additions & 1 deletion docs/docker_build.adoc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
= Building the app Docker images

From the top-level directory, run the docker build:
From the top-level directory, run the yarn build and then the docker build:

[source,bash]
----
yarn
yarn workspace dina-ui build
docker build -f Dockerfile -t dina-ui:tag .
----

Expand All @@ -12,5 +14,7 @@ Docker environment variables required to run:
dina-ui:

* OBJECTSTORE_API_ADDRESS: The back-end API URL and port. e.g. objectstore-api:8080
* USER_API_ADDRESS: The back-end API URL and port. e.g. user-api:8080
* COLLECTION_API_ADDRESS: The back-end API URL and port. e.g. collection-api:8080
* AGENT_API_ADDRESS: The back-end API URL and port. e.g. agent-api:8080
* SEQDB_API_ADDRESS: The back-end API URL and port. e.g. seqdb-api:8080
28 changes: 14 additions & 14 deletions docs/intl.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ You should instead reference a message key:

[source,tsx]
----
import { SeqDBMessage } from "../../intl/seqdb-intl.ts""
import { DinaMessage } from "../../intl/dina-intl.ts""
...
<h2><SeqDBMessage id="pcrPrimerListTitle" /></h2>
<h2><DinaMessage id="pcrPrimerListTitle" /></h2>
----

== formatMessage function
Expand All @@ -29,10 +29,10 @@ You can also use the "formatMessage" function if you want to reference a message

[source,tsx]
----
import { useSeqdbIntl } from "../../seqdb-intl.ts""
import { useDinaIntl } from "../../dina-intl.ts""
function MyComponent() {
const { formatMessage } = useSeqdbIntl();
const { formatMessage } = useDinaIntl();
useEffect(() => {
alert(formatMessage("greeting"));
Expand All @@ -46,31 +46,31 @@ function MyComponent() {

== Defining messages

The actual text for these messages needs to be defined in a messages file, like seqdb-en.ts. Each UI app
( seqdb-ui, dina-ui, etc. ) should have its own messages files. common-ui has its own messages files
for shared messages used by multiple apps.
The actual text for these messages needs to be defined in a messages file, like dina-en.ts. Each UI app
( dina-ui is the only UI app at the moment ) should have its own messages files. common-ui has its
own messages files for shared messages used by multiple apps.

seqdb-en.ts:
dina-en.ts:

[source,tsx]
----
export const SEQDB_MESSAGES_ENGLISH = {
export const DINA_MESSAGES_ENGLISH = {
...
greeting: "Hello!"
...
}
----

Type-checking is enabled so the message ID passed into "SeqDBMessage" or "formatMessage" MUST be a key
Type-checking is enabled so the message ID passed into "DinaMessage" or "formatMessage" MUST be a key
in at least the English messages file. To add a French (or other language) translation
for a message, the English version of the message must already be defined. The UI uses the English
translation as a fallback if the message has no translation for the user's locale.

Example from seqdb-fr.ts:
Example from dina-fr.ts:

[source,tsx]
----
export const SEQDB_MESSAGES_FRENCH: Partial<typeof SEQDB_MESSAGES_ENGLISH> = {
export const DINA_MESSAGES_FRENCH: Partial<typeof DINA_MESSAGES_ENGLISH> = {
...
greeting: "Bonjour!", // If the key exists in the english messages file, Typescript allows it.
otherKey: "C'est un autre message." // If "otherKey" isn't a key in the English messages, this should show an error in your IDE.
Expand All @@ -89,7 +89,7 @@ Example:

[source,tsx]
----
export const SEQDB_MESSAGES_ENGLISH = {
export const DINA_MESSAGES_ENGLISH = {
...
field_name: "Name",
"field_group.groupName": "Group Name",
Expand All @@ -99,7 +99,7 @@ export const SEQDB_MESSAGES_ENGLISH = {

[source,tsx]
----
export const SEQDB_MESSAGES_FRENCH: Partial<typeof SEQDB_MESSAGES_ENGLISH> = {
export const DINA_MESSAGES_FRENCH: Partial<typeof DINA_MESSAGES_ENGLISH> = {
...
field_name: "Nom",
"field_group.groupName": "Nom de Groupe"
Expand Down
2 changes: 1 addition & 1 deletion docs/resource_select_field.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Example usage for selecting a Group from a list:
[source,tsx]
----
import { DinaForm, ResourceSelectField } from "common-ui";
import { Group } from "../types/seqdb-api/resources/Group";
import { Group } from "../types/user-api/resources/Group";

/**
* This page shows a dropdown for selecting a Group. You can type the name of a Group you're
Expand Down
20 changes: 20 additions & 0 deletions docs/useQuery_hook_function.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,23 @@ function ExampleComponent() {
}
}
----
Using the "withResponse" helper function to render generic loading and error components with minimal code,
instead of writing if/else blocks for each state:
[source,tsx]
----
import { useQuery, withResponse } from "../components";
import { PcrPrimer } from "../types/seqdb-api/resources/PcrPrimer";

function ExampleComponent() {
const primerQuery = useQuery<PcrPrimer[]>({ path: "pcrPrimer" });

return withResponse(primerQuery, ({ data: primers }) => (
<div>
{primers.map(primer => (
<PcrPrimerInfo key={primer.id} primer={primer} />
))}
</div>
));
}
----
42 changes: 42 additions & 0 deletions docs/write_operations.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
= Performing write operations

This application uses React's hooks and context API to provide a "save" function which allows
you to perform write operations against the back-end API. "save" accepts an array of
operations to perform, so you can submit multiple resource operations in a single transaction
in a single HTTP request.

If one operation fails, the entire transaction is cancelled, and "save" throws an Error,
which provides an aggregation message of all of the error messages. This function relies on the back-end to
support JSONAPI's jsonpatch extension (implemented by crnk-operations).

Here is a simple example of a component that uses the "save" function from the context to
provide a button that creates a new Region with a random name and symbol:

[source,tsx]
----
import React from "react";
import { useApiClient } from "common-ui";
export funcion NewRegionButton() {
const { save } = useApiClient();
async function createRegion() {
await save(
[
{
resource: {
name: `new-region-${Math.random()}`,
seq: "",
symbol: `${Math.random()}`,
type: "PRIMER"
},
type: "region"
}
],
{ apiBaseUrl: "/seqdb-api" }
);
};
return <button onClick={this.createRegion}>Create Region</button>;
}
----
20 changes: 6 additions & 14 deletions docs/yarn_package_scripts.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,17 @@ Generates the production build.

=== `yarn dev`

Runs the UI application at localhost:8000 in dev mode using https://github.com/zeit/next.js[Next.js].
If you edit and save a source file, the running application will reload itself.

This command also sets up an HTTP proxy that redirects requests for localhost:8000/api/* endpoints to
localhost:8080/api/. This lets developers test the app locally with a working backend API. Note that
you must have https://github.com/AAFC-BICoE/seqdb-api[seqdb-api] running at localhost:8080 for the UI
to connect to the API, and you must log into the API by browsing to localhost:8080 and logging in so
the UI can authenticate with the API.
Runs the UI application at localhost:3000 in dev mode using https://github.com/zeit/next.js[Next.js].
When you save a file, you can refresh the page to see your changes without restarting the app.
Note that this does not let the UI connect to the backend because there is no HTTP proxy set up. See
"https://github.com/poffm/dina-dev" for the full dev mode with a proxy.

=== `yarn next`

Runs the UI application at localhost:3000 in dev mode using https://github.com/zeit/next.js[Next.js].
When you save a file, you can refresh the page to see your changes without restarting the app.
Note that this does not let the UI connect to the backend because there is no HTTP proxy set up. See
the "yarn dev" section for the full dev mode with a proxy.

=== `yarn start`

Runs the application in production mode. Requires a build first, which you can generate using
`yarn build`.
"https://github.com/poffm/dina-dev" for the full dev mode with a proxy.

=== `yarn test`

Expand Down
23 changes: 11 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,45 @@
"lint": "yarn workspaces run lint",
"lint:fix": "yarn workspaces run lint:fix",
"test": "yarn workspaces run test",
"test:coverage": "yarn workspaces run test:coverage"
"test:coverage": "yarn workspaces run test:coverage",
"prepare": "husky install"
},
"devDependencies": {
"@babel/runtime-corejs2": "^7.10.4",
"@phenomnomnominal/tsquery": "^4.1.1",
"@types/enzyme": "^3.10.8",
"@types/enzyme-to-json": "^1.5.4",
"@types/jest": "^26.0.20",
"@types/jest": "^26.0.23",
"@types/node": "^14.0.14",
"@types/react-test-renderer": "^16.0.3",
"@wojtekmaj/enzyme-adapter-react-17": "^0.4.1",
"asciidoctor": "^2.0.3",
"babel-jest": "^26.6.3",
"babel-plugin-react-require": "^3.1.3",
"enzyme": "^3.11.0",
"enzyme-to-json": "^3.6.1",
"husky": "^3.0.9",
"husky": "^6.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"jsonapi-typescript": "^0.1.3",
"lint-staged": "^10.2.11",
"npm-run-all": "^4.1.5",
"pa11y-ci": "^2.3.0",
"prettier": "^2.0.5",
"react-test-renderer": "^16.8.6",
"ts-jest": "^26.4.4",
"ts-jest": "^26.5.6",
"ts-node": "^9.0.0",
"tslint": "^6.1.2",
"tslint-config-prettier": "^1.18.0",
"tslint-plugin-prettier": "^2.3.0",
"tslint-react": "^5.0.0",
"typescript": "^4.1.3",
"typescript": "^4.2.4",
"xlsx": "^0.16.7"
},
"resolutions": {
"**/kitsu/axios": "^0.21.1",
"**/lodash": "^4.17.21",
"**/react-file-viewer/**/three": "^0.125.0",
"**/react-file-viewer/**/underscore": "^1.13.1",
"**/react-file-viewer/**/lodash": "^4.17.21",
"**/type-fest": "^1.0.2"
},
"husky": {
"hooks": {
"pre-commit": "yarn workspaces run lint-staged"
}
}
}
19 changes: 17 additions & 2 deletions packages/common-ui/lib/bulk-data-editor/BulkDataEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export function BulkDataEditor<TRow>({
const newWorkingData = cloneDeep(loadedData);
await applyCustomDefaultValues?.(newWorkingData);
setWorkingTableData(newWorkingData);

setLoading(false);
});

Expand Down Expand Up @@ -129,12 +128,28 @@ export function BulkDataEditor<TRow>({
.handsontableEditor.autocompleteEditor, .handsontableEditor.autocompleteEditor .ht_master .wtHolder {
min-height: 138px;
}
/* Fix the place holder color contrast */
.htPlaceholder.htAutocomplete {
color: rgb(51,51,51);
}
/* Fix need to review issue (critical): .htDimmed:nth-child(2) need sufficient color contrast */
.handsontable .htDimmed {
color: rgb(108,117,125);
}
/* Fix need to review issue : ..htAutocompleteArrow need sufficient color contrast */
.htAutocomplete .htAutocompleteArrow {
color: rgb(108,117,125);
}
`}</style>
{validationAlertJsx}
<div
className="form-group"
// Setting the width/height and overflowX:hidden here is detected by Handsontable and enables horizontal scrolling:
style={{ height: "100%", width: "100%", overflowX: "hidden" }}
style={{
height: "100%",
width: "100%",
overflowX: "hidden"
}}
>
<DynamicHotTable
afterValidate={afterValidate}
Expand Down
20 changes: 20 additions & 0 deletions packages/common-ui/lib/bulk-data-editor/useHeaderWidthFix.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ export function useHeaderWidthFix({ columns }: HeaderWidthFixParams) {
setImmediate(() => {
const wrapper = tableWrapperRef.current;

const makeHotTableContenHolderFocusable = () => {
// Fix Ensure that scrollable region has keyboard access (making the scrollable region focusable)
const htHolder = wrapper?.querySelector<HTMLDivElement>(
".ht_master .wtHolder"
);
if (htHolder) {
htHolder.style.overflowY = "auto";
htHolder.tabIndex = 0;
}
// Fix text area within hot table sometimes has the "Ensure scrollable region has keyboard access" issue
const textArea = wrapper?.querySelector<HTMLDivElement>(
".handsontableInputHolder .handsontableInput"
);
if (textArea) {
textArea.style.height = "auto";
textArea.tabIndex = 0;
}
};
if (wrapper) {
const header = wrapper.querySelector<HTMLDivElement>(
".ht_clone_top .wtHider"
Expand All @@ -29,6 +47,8 @@ export function useHeaderWidthFix({ columns }: HeaderWidthFixParams) {
const requiredHeaderWidth = `${htCore.clientWidth}px`;
header.style.width = requiredHeaderWidth;
}

makeHotTableContenHolderFocusable();
}
});
}, []);
Expand Down
20 changes: 2 additions & 18 deletions packages/common-ui/lib/formik-connected/FieldView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,9 @@ export function FieldView(props: LabelWrapperParams) {
export interface ReadOnlyValueProps {
value: any;
link?: string;
arrayItemLink?: string;
}

export function ReadOnlyValue({
value,
link,
arrayItemLink
}: ReadOnlyValueProps) {
export function ReadOnlyValue({ value, link }: ReadOnlyValueProps) {
return (
<div
className="field-view"
Expand All @@ -43,18 +38,7 @@ export function ReadOnlyValue({

return (
<Fragment key={idx}>
{arrayItemLink ? (
<>
<Link href={arrayItemLink + val.id} key={val.id}>
<a>{displayString}</a>
</Link>
{idx <= value.length - 2 && <span>, </span>}
</>
) : idx <= value.length - 2 ? (
displayString + ", "
) : (
displayString
)}
{idx <= value.length - 2 ? displayString + ", " : displayString}
</Fragment>
);
})
Expand Down
Loading

0 comments on commit 6381862

Please sign in to comment.