chore: Clean up unused files, imports, and work on getting end-to-end tests and unit tests running (#2272)
This commit is contained in:
1 parent
414ebc6850
commit
0db81b30f3
374 files changed
+14138
-21288
No files matched your search
@@ -0,0 +1,119 @@
|
||||
# Viewer: Configuration
|
||||
|
||||
We maintain a number of common viewer application configurations at
|
||||
[`<root>/platform/viewer/public/configs`][config-dir]. How these values are
|
||||
passed to the viewer depend on how it's deployed, but the two most common paths
|
||||
are:
|
||||
|
||||
- `index.html` looks for `https://your-website.com/app-config.js` OR
|
||||
- `index.html` passes the values to `OHIF.installViewer()`
|
||||
|
||||
```js
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
/**
|
||||
* "White Labeling" is used to change the branding, look, and feel of the OHIF
|
||||
* Viewer. These settings, and the color variables that are used by our components,
|
||||
* are the easiest way to rebrand the application.
|
||||
*
|
||||
* More extensive changes are made possible through swapping out the UI library,
|
||||
* Viewer project, or extensions.
|
||||
*/
|
||||
whiteLabeling: {
|
||||
/* Optional: Should return a React component to be rendered in the "Logo" section of the application's Top Navigation bar */
|
||||
createLogoComponentFn: function(React) {
|
||||
return React.createElement('a', {
|
||||
target: '_self',
|
||||
rel: 'noopener noreferrer',
|
||||
className: 'header-brand',
|
||||
href: '/',
|
||||
style: {
|
||||
display: 'block',
|
||||
textIndent: '-9999px',
|
||||
background: 'url(/svg-file-hosted-at-domain-root.svg)',
|
||||
backgroundSize: 'contain',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
width: '200px',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Internally, the OHIF Viewer fetches data primarily with the
|
||||
* `cornerstoneWADOImageLoader` and the `DICOMWebClient`. If either of these
|
||||
* receive a non-200 response, this method allows you to handle that error.
|
||||
*
|
||||
* Common use cases include:
|
||||
* - Showing a notification with the UINotificationService
|
||||
* - Redirecting the user
|
||||
* - Refreshing an auth token
|
||||
*
|
||||
* @param {Object} error - JS new Error()
|
||||
* @param {XMLHttpRequest} error.request - The XHR request that's onreadystate change triggered this callback
|
||||
* @param {string} error.response - The XHR's response property
|
||||
* @param {number} error.status - The XHR's status property
|
||||
*/
|
||||
httpErrorHandler: error => {
|
||||
const { request: xhr, response, status } = err;
|
||||
const { responseType, statusText } = xhr;
|
||||
|
||||
// In local files, status is 0 upon success in Firefox
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
console.log(statusText, response, responseType);
|
||||
} else {
|
||||
console.warn('Likely CORS error');
|
||||
}
|
||||
},
|
||||
extensions: [],
|
||||
showStudyList: true,
|
||||
filterQueryParam: false,
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
qidoSupportsIncludeField: true,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
enableStudyLazyLoad: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
// Supported Keys: https://craig.is/killing/mice
|
||||
hotkeys: [
|
||||
{ commandName: 'rotateViewportCW', label: 'Rotate Right', keys: ['r'] },
|
||||
{ commandName: 'rotateViewportCCW', label: 'Rotate Left', keys: ['l'] },
|
||||
{ commandName: 'invertViewport', label: 'Invert', keys: ['i'] },
|
||||
{
|
||||
commandName: 'flipViewportVertical',
|
||||
label: 'Flip Horizontally',
|
||||
keys: ['h'],
|
||||
},
|
||||
{
|
||||
commandName: 'flipViewportHorizontal',
|
||||
label: 'Flip Vertically',
|
||||
keys: ['v'],
|
||||
},
|
||||
],
|
||||
/* Configuration passed to the bundled cornerstone extension
|
||||
*
|
||||
* The cornerstone extension is currently tightly coupled to the platform.
|
||||
* Until we're able to decouple it, this key will serve as a workaround to
|
||||
* pass it configuration.
|
||||
*/
|
||||
cornerstoneExtensionConfig: {
|
||||
/* Whether to show/hide annotation "handles" */
|
||||
hideHandles: true,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[config-dir]: https://github.com/OHIF/Viewers/tree/master/platform/viewer/public/config
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -0,0 +1,23 @@
|
||||
# Environment Variables
|
||||
|
||||
There are a number of environment variables we use at build time to influence the output application's behavior.
|
||||
|
||||
```bash
|
||||
# Application
|
||||
NODE_ENV=< production | development >
|
||||
DEBUG=< true | false >
|
||||
APP_CONFIG=< relative path to application configuration file >
|
||||
PUBLIC_URL=<>
|
||||
VERSION_NUMBER=<Set by CircleCI>
|
||||
BUILD_NUM=<Set by CircleCI>
|
||||
# i18n
|
||||
USE_LOCIZE=<false>
|
||||
LOCIZE_PROJECTID=<ProjectID to pull translations for>
|
||||
LOCIZE_API_KEY=<To enable Locize live editing of translations>
|
||||
```
|
||||
|
||||
## Setting Environment Variables
|
||||
|
||||
- `npx cross-env`
|
||||
- `.env` files
|
||||
- env variables on build machine, or for terminal session
|
||||
@@ -0,0 +1,3 @@
|
||||
# Hotkeys
|
||||
|
||||
...
|
||||
@@ -0,0 +1,9 @@
|
||||
# Viewer
|
||||
|
||||
The OHIF Viewing Platform strives to be highly configurable and extensible. This
|
||||
makes it easier for our community members to keep their "secret sauce" private,
|
||||
and incentivises contributions back to the platform. The `@ohif/viewer` project
|
||||
of the platform is the lynchpin that combines everything to create our
|
||||
application.
|
||||
|
||||
- When configuration and themeing aren't enough
|
||||
@@ -0,0 +1,317 @@
|
||||
# Viewer: Internationalization
|
||||
|
||||
OHIF supports internationalization using [i18next](https://www.i18next.com/)
|
||||
through the npm package [@ohif/i18n](https://www.npmjs.com/package/@ohif/i18n),
|
||||
where is the main instance of i18n containing several languages and tools.
|
||||
|
||||
<div class='row'>
|
||||
<div class='column'>
|
||||
<p>Our translation management is powered by <a href="https://locize.com/" target="_blank" rel="noopener noreferrer">Locize</a> through their generous support of open source.</p>
|
||||
</div>
|
||||
<div class='column'>
|
||||
<a href="https://locize.com/" target="_blank" rel="noopener noreferrer" style='padding: 20px'>
|
||||
<img src="../assets/img/locizeSponsor.svg" alt="Locize Translation Management Logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
## Installing
|
||||
|
||||
```bash
|
||||
yarn add @ohif/i18n
|
||||
|
||||
# OR
|
||||
|
||||
npm install --save @ohif/i18n
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
After installing `@ohif/i18n` npm package, the translation function
|
||||
[t](https://www.i18next.com/overview/api#t) can be used [with](#with-react) or
|
||||
[without](#without-react) React.
|
||||
|
||||
A translation will occur every time a text match happens in a
|
||||
[t](https://www.i18next.com/overview/api#t) function.
|
||||
|
||||
The [t](https://www.i18next.com/overview/api#t) function is responsible for
|
||||
getting translations using all the power of i18next.
|
||||
|
||||
E.g.
|
||||
|
||||
Before:
|
||||
|
||||
```html
|
||||
<div>my translated text</div>
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```html
|
||||
<div>{t('my translated text')}</div>
|
||||
```
|
||||
|
||||
If the translation.json file contains a key that matches the HTML content e.g.
|
||||
`my translated text`, it will be replaced automatically by the
|
||||
[t](https://www.i18next.com/overview/api#t) function.
|
||||
|
||||
---
|
||||
|
||||
### With React
|
||||
|
||||
This section will introduce you to [react-i18next](https://react.i18next.com/)
|
||||
basics and show how to implement the [t](https://www.i18next.com/overview/api#t)
|
||||
function easily.
|
||||
|
||||
#### Using HOCs
|
||||
|
||||
In most cases we used
|
||||
[High Order Components](https://react.i18next.com/latest/withtranslation-hoc) to
|
||||
share the `t` function among OHIF's components.
|
||||
|
||||
E.g.
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { withTranslation } from '@ohif/i18n';
|
||||
|
||||
function MyComponent({ t, i18n }) {
|
||||
return <p>{t('my translated text')}</p>;
|
||||
}
|
||||
|
||||
export default withTranslation('MyNameSpace')(MyComponent);
|
||||
```
|
||||
|
||||
> Important: if you are using React outside the OHIF Viewer, check the
|
||||
> [I18nextProvider](#using-outside-of-ohif-viewer) section, `withTranslation`
|
||||
> HOC doesnt works without a I18nextProvider
|
||||
|
||||
#### Using Hooks
|
||||
|
||||
Also, it's possible to get the `t` tool using
|
||||
[React Hooks](https://react.i18next.com/latest/usetranslation-hook), but it
|
||||
requires at least React > 16.8 😉
|
||||
|
||||
### Using outside of OHIF viewer
|
||||
|
||||
OHIF Viewer already sets a main
|
||||
[I18nextProvider](https://react.i18next.com/latest/i18nextprovider) connected to
|
||||
the shared i18n instance from `@ohif/i18n`, all extensions inside OHIF Viewer
|
||||
will share this same provider at the end, you don't need to set new providers at
|
||||
all.
|
||||
|
||||
But, if you need to use it completely outside of OHIF viewer, you can set the
|
||||
I18nextProvider this way:
|
||||
|
||||
```js
|
||||
import i18n from '@ohif/i18n';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import App from './App';
|
||||
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<App />
|
||||
</I18nextProvider>;
|
||||
```
|
||||
|
||||
After setting `I18nextProvider` in your React App, all translations from
|
||||
`@ohif/i18n` should be available following the basic [With React](#with-react)
|
||||
usage.
|
||||
|
||||
---
|
||||
|
||||
### Without React
|
||||
|
||||
When needed, you can also use available translations _without React_.
|
||||
|
||||
E.g.
|
||||
|
||||
```js
|
||||
import { T } from '@ohif/i18n';
|
||||
console.log(T('my translated text'));
|
||||
console.log(T('$t(Common:Play) my translated text'));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Main Concepts While Translating
|
||||
|
||||
## Namespaces
|
||||
|
||||
Namespaces are being used to organize translations in smaller portions, combined
|
||||
semantically or by use. Each `.json` file inside `@ohif/i18n` npm package
|
||||
becomes a new namespace automatically.
|
||||
|
||||
- Buttons: All buttons translations
|
||||
- CineDialog: Translations for the toll tips inside the Cine Player Dialog
|
||||
- Common: all common jargons that can be reused like `t('$t(common:image)')`
|
||||
- Header: translations related to OHIF's Header Top Bar
|
||||
- MeasurementTable - Translations for the `@ohif/ui` Measurement Table
|
||||
- UserPreferencesModal - Translations for the `@ohif/ui` Preferences Modal
|
||||
|
||||
### How to use another NameSpace inside the current NameSpace?
|
||||
|
||||
i18next provides a parsing feature able to get translations strings from any
|
||||
NameSpace, like this following example getting data from `Common` NameSpace:
|
||||
|
||||
```
|
||||
$t(Common:Reset)
|
||||
```
|
||||
|
||||
## Extending Languages in @ohif/i18n
|
||||
|
||||
Sometimes, even using the same language, some nouns or jargons can change
|
||||
according to the country, states or even from Hospital to Hospital.
|
||||
|
||||
In this cases, you don't need to set an entire language again, you can extend
|
||||
languages creating a new folder inside a pre existent language folder and
|
||||
@ohif/i18n will do the hard work.
|
||||
|
||||
This new folder must to be called with a double character name, like the `UK` in
|
||||
the following file tree:
|
||||
|
||||
```bash
|
||||
|-- src
|
||||
|-- locales
|
||||
index.js
|
||||
|-- en
|
||||
|-- Buttons.json
|
||||
index.js
|
||||
| UK
|
||||
|-- Buttons.js
|
||||
indes.js
|
||||
| US
|
||||
|-- Buttons.js
|
||||
index.js
|
||||
...
|
||||
```
|
||||
|
||||
All properties inside a Namespace will be merged in the new sub language, e.g
|
||||
`en-US` and `en-UK` will merge the props with `en`, using i18next's fallback
|
||||
languages tool.
|
||||
|
||||
You will need to export all Json files in your `index.js` file, mounting an
|
||||
object like this:
|
||||
|
||||
```js
|
||||
{
|
||||
en: {
|
||||
NameSpace: {
|
||||
keyWord1: 'keyWord1Translation',
|
||||
keyWord2: 'keyWord2Translation',
|
||||
keyWord3: 'keyWord3Translation',
|
||||
}
|
||||
},
|
||||
'en-UK': {
|
||||
NameSpace: {
|
||||
keyWord1: 'keyWord1DifferentTranslation',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Please check the `index.js` files inside locales folder for an example of this
|
||||
exporting structure.
|
||||
|
||||
### Extending languages dynamically
|
||||
|
||||
You have access to the i18next instance, so you can use the
|
||||
[addResourceBundle](https://www.i18next.com/how-to/add-or-load-translations#add-after-init)
|
||||
method to add and change language resources as needed.
|
||||
|
||||
E.g.
|
||||
|
||||
```js
|
||||
import { i18n } from '@ohif/i18n';
|
||||
i18next.addResourceBundle('pt-BR', 'Buttons', {
|
||||
Angle: 'Ângulo',
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### How to set a whole new language
|
||||
|
||||
To set a brand new language you can do it in two different ways:
|
||||
|
||||
- Opening a pull request for `@ohif/i18n` and sharing the translation with the
|
||||
community. 😍 Please see [Contributing](#contributing-with-new-languages)
|
||||
section for further information.
|
||||
|
||||
- Setting it only in your project or extension:
|
||||
|
||||
You'll need a a final object like the following, what is setting French as
|
||||
language, and send it to `addLocales` method.
|
||||
|
||||
```js
|
||||
const newLanguage =
|
||||
{
|
||||
fr: {
|
||||
Commons: {
|
||||
"Reset": "Réinitialiser",
|
||||
"Previous": "Précédent",
|
||||
},
|
||||
Buttons: {
|
||||
"Rectangle": "Rectangle",
|
||||
"Circle": "Cercle",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To make it easier to translate, you can copy the .json files in the /locales
|
||||
folder and theirs index.js exporters, keeping same keys and NameSpaces.
|
||||
Importing the main index.js file, will provide you an Object as expected by the
|
||||
method `addlocales`;
|
||||
|
||||
E.g. of `addLocales` usage
|
||||
|
||||
```js
|
||||
import { addLocales } from '@ohif/i18n';
|
||||
import locales from './locales/index.js';
|
||||
addLocales(locales);
|
||||
```
|
||||
|
||||
You can also set them manually, one by one, using this
|
||||
[method](#extending-languages-dynamically).
|
||||
|
||||
---
|
||||
|
||||
## Language Detections
|
||||
|
||||
@ohif/i18n uses
|
||||
[i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector)
|
||||
to manage detections, also exports a method called initI18n that accepts a new
|
||||
detector config as parameter.
|
||||
|
||||
### Changing the language
|
||||
|
||||
OHIF Viewer accepts a query param called `lng` in the url to change the
|
||||
language.
|
||||
|
||||
E.g.
|
||||
|
||||
```
|
||||
https://docs.ohif.org/demo/?lng=es-MX
|
||||
```
|
||||
|
||||
### Language Persistence
|
||||
|
||||
The user's language preference is kept automatically by the detector and stored
|
||||
at a cookie called 'i18next', and in a localstorage key called 'i18nextLng'.
|
||||
These names can be changed with a new
|
||||
[Detector Config](https://github.com/i18next/i18next-browser-languageDetector).
|
||||
|
||||
## Debugging translations
|
||||
|
||||
There is an environment variable responsible for debugging the translations,
|
||||
called `REACT_APP_I18N_DEBUG`.
|
||||
|
||||
Run the project as following to get full debug information:
|
||||
|
||||
```bash
|
||||
REACT_APP_I18N_DEBUG=true yarn run dev
|
||||
```
|
||||
|
||||
### Contributing with new languages
|
||||
|
||||
Contributions of any kind are welcome! Please check the
|
||||
[instructions](../development/contributing.md).
|
||||
@@ -0,0 +1,97 @@
|
||||
# Viewer: Themeing
|
||||
|
||||
Themeing is currently accomplished with color variables that are defined within
|
||||
the [`:root`](https://css-tricks.com/almanac/selectors/r/root/) selector
|
||||
(allowing them to cascade across all elements). This repository's components,
|
||||
and the ones we consume from our
|
||||
[`@ohif/ui` component library](https://react.ohif.org/styling-and-theming)
|
||||
utilize them. We are interested in pursuing more robust themeing options, and
|
||||
open to pull requests and discussion issues.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Interface UI Colors */
|
||||
--default-color: #9ccef9;
|
||||
--hover-color: #ffffff;
|
||||
--active-color: #20a5d6;
|
||||
--ui-border-color: #44626f;
|
||||
--ui-border-color-dark: #3c5d80;
|
||||
--ui-border-color-active: #00a4d9;
|
||||
--primary-background-color: #000000;
|
||||
--box-background-color: #3e5975;
|
||||
|
||||
--text-primary-color: #ffffff;
|
||||
--text-secondary-color: #91b9cd;
|
||||
--input-background-color: #2c363f;
|
||||
--input-placeholder-color: #d3d3d3;
|
||||
|
||||
--table-hover-color: #2c363f;
|
||||
--table-text-primary-color: #ffffff;
|
||||
--table-text-secondary-color: #91b9cd;
|
||||
|
||||
--large-numbers-color: #6fbde2;
|
||||
|
||||
--state-error: #ffcccc;
|
||||
--state-error-border: #ffcccc;
|
||||
--state-error-text: #ffcccc;
|
||||
|
||||
/* Common palette */
|
||||
--ui-yellow: #e29e4a;
|
||||
--ui-sky-blue: #6fbde2;
|
||||
|
||||
/* State palette */
|
||||
--ui-state-error: #ffcccc;
|
||||
--ui-state-error-border: #993333;
|
||||
--ui-state-error-text: #661111;
|
||||
--ui-gray-lighter: #436270;
|
||||
--ui-gray-light: #516873;
|
||||
--ui-gray: #263340;
|
||||
--ui-gray-dark: #16202b;
|
||||
--ui-gray-darker: #151a1f;
|
||||
--ui-gray-darkest: #14202a;
|
||||
|
||||
--calendar-day-color: #d3d3d3;
|
||||
--calendar-day-border-color: #d3d3d3;
|
||||
--calendar-day-active-hover-background-color: #516873;
|
||||
--calendar-main-color: #263340;
|
||||
--viewport-border-thickness: 1px;
|
||||
}
|
||||
```
|
||||
|
||||
## White Labeling
|
||||
|
||||
> A white-label product is a product or service produced by one company (the
|
||||
> producer) that other companies (the marketers) rebrand to make it appear as if
|
||||
> they had made it - [Wikipedia: White-Label Product][wikipedia]
|
||||
|
||||
Current white-labeling options are limited. We expose the ability to replace the
|
||||
"Logo" section of the application with a custom "Logo" component. You can do
|
||||
this by adding a `whiteLabeling` key to your
|
||||
[configuration file](./configuration.md).
|
||||
|
||||
```js
|
||||
function RadicalImagingLogo(React) {
|
||||
return React.createElement(
|
||||
'a',
|
||||
{
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
className: 'header-brand',
|
||||
href: 'http://radicalimaging.com',
|
||||
},
|
||||
React.createElement('h5', {}, 'RADICAL IMAGING')
|
||||
);
|
||||
}
|
||||
|
||||
props.whiteLabeling = {
|
||||
createLogoComponentFn: RadicalImagingLogo,
|
||||
};
|
||||
```
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[wikipedia]: https://en.wikipedia.org/wiki/White-label_product
|
||||
<!-- prettier-ignore-end -->
|
||||
Reference in new issue
Block a user