Files
ohif-viewer/platform/core/src/classes/README.md
T
Danny Brown 08ff214ea6 Chore/kill yalc with fire (#629)
* init

* more shifting

* Move @babel dependencies up to workspace root

* Begin updating dependent libraries to use sync'd webpack builds w/ watches

* Commit changes before a long weekend

* Split packages into platform and extensions

* Consolidate how/where we specify file/module type entrypoints

* Make it possible to pass in extensions as App props

* Resolve viewer's modules

* Target for UMD bundle

* Add Webpack Stylus loader

* Provide WebPack build options for microscopy, vtk, and ui

* Better entrypoint for extensions

* Push changes up to switch PCs

* Fix ESM symlink build for Viewers

* Shift docs to root

* Specify additional lerna config props

* Begin providing basic readme info

* Rename example extension folder

* Shift links to bottom of doc

* First attempt at a netlify deploy preview

* Attempt to fix deploy preview build

* push workspace enabled to initial command; remove second yarn install; use npx to call gitbook cli commands

* Try to use global gitbook-cli

* Export node_modules path

* More agressive with modifying PATH

* Follow deploy log output advice

* try again to set bin path

* Try swapping bash with a new shell

* Try bash -l instead of exec bash

* Annd let's try again

* and again

* We may have figured it out johnny, boy

* We need to pull cornerstone-wado-image-loader files from hoisted node_modules

* Attempt to fix ticks/escapes

* Change copy syntax; try running tests on viewers from root for circleci

* Lower version to match circleci image

* Try alternative jest-canvas-mock location and version file syntax

* Run version command instead of calling node directly

* Try alternative jest transform

* Set path and enable workspaces

* Add codecov flags

* Use cpx so our copying finishes?

* Get all platform unit tests to run

* Run and report individually and in parallel

* Try once relying on codecov yaml to split w/ flags

* Add projects to split by flags

* Generate separate reports

* Trigger codecov after everything has finished running; these may not support flags

* Use recommended flags from issue comments for codecov

* Fix typo

* Remove clear flag

* Shift back to calling codecov from root

* Generate example for codecov issue

* Try fixing paths

* Simplify

* Try using codecov orb

* Bump circleci version

* Upload core and viewer

* Use full string paths

* Remove individual codecov calls

* Fix dir

* Combine files before upload

* Escape anchors

* tryfix syntax

* Escape string literal

* Combine lines to reduce path

* long paths

* Use home alias

* Fix filename

* Try to see the contents of our cat'd file

* Also upload `core`

* Try running with aliased folder

* Fix path; split PR and Merge unit tests into separate jobs

* Set default threshold

* Fix typo

* Changing to scoped package names

* Adding note

* Catch more updates

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.0
 - @ohif/extension-dicom-html@0.0.4-alpha.0
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.0
 - @ohif/extension-dicom-pdf@0.0.8-alpha.0
 - @ohif/extension-vtk@0.1.4-alpha.0
 - @ohif/core@0.11.1-alpha.0
 - @ohif/i18n@0.2.3-alpha.0
 - @ohif/ui@0.2.18-alpha.0
 - @ohif/viewer@0.0.22-alpha.0

* Clean up primary readme

* Support for dev and dev:* commands

* Shift build command; satisfy default PWA build

* Remove old scripts

* Clean up UI to set webpack scripts

* Tidy up project links

* Clean duplicate code in UI project

* Update UI project's docs

* Clean up ui and i18n config

* Reduce duplicate code in `@ohif/core`

* Fix @ohif/ui versions

* bump @ohif/core versions

* Redux testkit dep

* Remove unused/duplicate config files for projects/packages

* ohif-core --> @ohif/core

* Safer publish command

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.1
 - @ohif/extension-dicom-html@0.0.4-alpha.1
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.1
 - @ohif/extension-dicom-pdf@0.0.8-alpha.1
 - @ohif/extension-vtk@0.1.4-alpha.1
 - @ohif/core@0.11.1-alpha.1
 - @ohif/i18n@0.2.3-alpha.1
 - @ohif/ui@0.2.18-alpha.1
 - @ohif/viewer@0.0.22-alpha.1

* test version bump

* Add global prettier config

* chore(release): publish %s [skip ci]

 - @ohif/viewer@0.0.22-alpha.2

* test lerna publish

* Update package.jsons

* Fix build scripts

* catch changes

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.2
 - @ohif/extension-dicom-html@0.0.4-alpha.2
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.2
 - @ohif/extension-dicom-pdf@0.0.8-alpha.2
 - @ohif/extension-vtk@0.1.4-alpha.2
 - @ohif/core@0.11.1-alpha.2
 - @ohif/i18n@0.2.3-alpha.2
 - @ohif/ui@0.2.18-alpha.2
 - @ohif/viewer@0.0.22-alpha.3

* fix eslint issues caused by eslint 6 and our react-app config

* Publish with canary tag

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.3
 - @ohif/extension-dicom-html@0.0.4-alpha.3
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.3
 - @ohif/extension-dicom-pdf@0.0.8-alpha.3
 - @ohif/extension-vtk@0.1.4-alpha.3
 - @ohif/core@0.11.1-alpha.3
 - @ohif/i18n@0.2.3-alpha.3
 - @ohif/ui@0.2.18-alpha.3
 - @ohif/viewer@0.0.22-alpha.4

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.4
 - @ohif/extension-dicom-html@0.0.4-alpha.4
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.4
 - @ohif/extension-dicom-pdf@0.0.8-alpha.4
 - @ohif/extension-vtk@0.1.4-alpha.4
 - @ohif/core@0.11.1-alpha.4
 - @ohif/i18n@0.2.3-alpha.4
 - @ohif/ui@0.2.18-alpha.4
 - @ohif/viewer@0.0.22-alpha.5

* Simplify build

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.5
 - @ohif/extension-dicom-html@0.0.4-alpha.5
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.5
 - @ohif/extension-dicom-pdf@0.0.8-alpha.5
 - @ohif/extension-vtk@0.1.4-alpha.5
 - @ohif/core@0.11.1-alpha.5
 - @ohif/i18n@0.2.3-alpha.5
 - @ohif/ui@0.2.18-alpha.5
 - @ohif/viewer@0.0.22-alpha.6

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.6
 - @ohif/extension-dicom-html@0.0.4-alpha.6
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.6
 - @ohif/extension-dicom-pdf@0.0.8-alpha.6
 - @ohif/extension-vtk@0.1.4-alpha.6
 - @ohif/core@0.11.1-alpha.6
 - @ohif/i18n@0.2.3-alpha.6
 - @ohif/ui@0.2.18-alpha.6
 - @ohif/viewer@0.0.22-alpha.7

* Split version and publish

* chore(release): publish %s [skip ci]

 - @ohif/extension-cornerstone@0.0.39-alpha.7
 - @ohif/extension-dicom-html@0.0.4-alpha.7
 - @ohif/extension-dicom-microscopy@0.0.9-alpha.7
 - @ohif/extension-dicom-pdf@0.0.8-alpha.7
 - @ohif/extension-vtk@0.1.4-alpha.7
 - @ohif/core@0.11.1-alpha.7
 - @ohif/i18n@0.2.3-alpha.7
 - @ohif/ui@0.2.18-alpha.7
 - @ohif/viewer@0.0.22-alpha.8

* Try simplify netlify build

* react-viewerbase --> @ohif/ui

* add test for stylus loader

* Try new way to specify publish path

* Use an output folder that won't be ignored

* Try move command

* fiddle with paths

* Dig for some information

* Make sure we're in root for our commands

* Remove discovery

* Setup script-tag example

* Fix typo

* Move config folder

* Update cornerstone extension to use shared/root webpack configs

* capture changes

* Update extension webpack configs

* Don't check in docz output

* Fix babel runtime resolution issue

* Simplify ui build steps

* Push in progress

* Shift directories

* Get viewer dev path to work

* Fix viewer commonjs build

* Fix build pwa config for viewers

* Make sure our package specific command can be called from root

* Update notes

* Fix imports and misc. merge notes

* Bump wado-image-loader version

* Switch up commands to remove webworkers copy

* Fix CI config

* Fix more broken package references

* Add react-dropzone

* Persist so e2e test can use

* Fix lockfile

* Use cypress orb to simplify CI

* Fix config

* Try again

* Install yarn latest for orb

* Install yarn a different way

* Wait on correct port

* Run tests in viewer project

* Fix cypress config

* Make Cypress happier - use default location

* Simplify e2e testing

* Capture UI changes since fork

* Catch core up

* Grab latest deps after merge

* Fix broken import

* Make sure cornerstone-wado-image-loader resolves to 3+

* Note regarding orbs

* Fix refresh on 404 routes

* Fix odd error for cornerstone-wado-image-loader

* Different target for UMD

* Simplify dev script

* Try to get fancy with netlify output

* Let's do it again

* Try to fix measurementTools issue

* See if we can get our lerna magic to work on merge to monorepo branch
2019-08-13 15:36:46 -04:00

9.7 KiB

Table of contents

In this document, some important objects are described. In the files there are comments that can help better undestand their methods and properties.

The Resize Viewport Manager object

This object has multiple functions to manage window resize event. It relocates Dialogs, resizes viewport elements and scrollbars and some other UI components such as Study and Series Quick Switch, when available.

Usage

It's only necessary to bind handleResize function to the window resize event as follows. The ohif:viewerbase package needs to be imported by the referring code as well.

import { Viewerbase } from 'meteor/ohif:viewerbase';

const ResizeViewportManager = new Viewerbase.ResizeViewportManager();
window.addEventListener('resize', ResizeViewportManager.getResizeHandler());

An example os its usage can be found in ohif-viewerbase/client/components/viewer/viewerMain/viewerMain.js.

The Image Set object

An object that represents a list of images that are associated by any arbitrary criteria being thus content agnostic. Besides the main attributes (images and uid) it allows additional attributes to be appended to it (currently indiscriminately, but this should be changed).

Usage

ImageSet constructor requires an array of SOP instances like in the example below. It's necessary to import ohif:viewerbase.

import { Viewerbase } from 'meteor/ohif:viewerbase';

const imageSet = new Viewerbase.ImageSet(sopInstances);

imageSet.setAttributes({
    displaySetInstanceUid: imageSet.uid,
    seriesInstanceUid: seriesData.seriesInstanceUid,
    seriesNumber: seriesData.seriesNumber,
    seriesDescription: seriesData.seriesDescription,
    numImageFrames: instances.length,
    frameRate: instance.getRawValue('x00181063'),
    modality: seriesData.modality,
    isMultiFrame: isMultiFrame(instance)
});

// Sort instances by InstanceNumber (0020,0013)
imageSet.sortBy((a, b) => {
    return (parseInt(a.getRawValue('x00200013', 0)) || 0) - (parseInt(b.getRawValue('x00200013', 0)) || 0);
});

Each SOP instance in this example is an instance of OHIFInstanceMetadata object, which is a specialization of InstanceMetadata. To read more about the Metadata API click here.

The Layout Manager object

Objects of this class are responsible for creating, organizing and maintaining (manage) viewport rendering. It creates a grid, positioning viewports accordingly to it's configuration keeping all viewports data (in viewportData property) for easy access from other components. It support many layout configurations and some of them were fully tested: 1x1, 1x2, 1x3, 2x1, 2x2, 2x3, 3x1, 3x2, 3x3. Other configurations may work as well. Finally it provides some useful functions to move through viewports and zoom it.

Usage

In order to use LayoutManager the ohif:viewerbase package needs to be imported by the referring code and instantiated as follows. An example os its usage is in ohif-viewerbase/client/components/viewer/viewerMain/viewerMain.js.

import { Viewerbase } from 'meteor/ohif:viewerbase';

// Get an array of studies object. This function needs to be implemented, it does not exist.
const studies = getArrayOfStudiesObjects();
const parentElement = document.getElementById('layoutManagerTarget');
const LayoutManager = new Viewerbase.LayoutManager(parentElement, studies);

The default configuration is 1x1, and to change it just set layoutProps and call updateViewports to update the layout as follows.

import { Viewerbase } from 'meteor/ohif:viewerbase';

// Get an array of studies object. This function needs to be implemented, it does not exist.
const studies = getArrayOfStudiesObjects();
const parentElement = document.getElementById('layoutManagerTarget');
const LayoutManager = new LayoutManager(parentElement, studies);

// Set the layout proprerties to 2x2 layout
LayoutManager.layoutProps = {
    rows: 2,
    columns: 2
};

// It will render four viewports: two in each row.
LayoutManager.updateViewports();

The layoutManagerTarget element will have a new class layout-2-2 (to allow further styling) and it's inner content will a new div#imageViewerViewports that has four inner elements like the following (some elements and attributes were removed for example purpose):

<div class="viewportContainer active" style="height:50%; width:50%;">
    <div class="removable">
        <div class="imageViewerViewport">
            <canvas></canvas>
        </div>
        <div class="imageViewerViewportOverlay"></div>
        <div class="imageViewerLoadingIndicator"></div>
        <div class="imageViewerErrorLoadingIndicator"></div>
        <div class="viewportOrientationMarkers"></div>
    </div>
</div>

Each of this div.viewportContainer will have some classes to help CSS specific styling accordingly to the element's position in the grid: top, middle and bottom. This classes are added by viewer/components/gridLayout/ component in ohif-viewerbase package.

The Type Safe Collections

With the introduction of the new Study Metadata API in which study metadata is represented by class hierarchies (using prototype-based inheritance), the usage of standard Minimongo collections as a central client-side storage for this data became no longer an option. Standard Mongo and Minimongo collections internally flatten data (in other words, data gets serialized) before storage hence no functions or prototype chains are preserved. In that scenario, when an object is restored (fetched), what is returned is actually a flattened copy of the original object with no functions or prototype (it's no longer an instance of it's original class). As an attempt to overcome this limitation a new type of collection was intruduced: the TypeSafeCollection.

The TypeSafeCollection is a simple list-like collection which tries to implement an API similar but not compatible with Mongo's API. It supports basic features like search by attribute map and ID, retrieval by index, sorting of result sets, insertion, removal and reactive operations but, unlike Mongo's API, it (still) lacks support to advanced functionality like complex search criterea or flexible sorting options.

Implementation

The TypeSafeCollection is implemented on top of the JavaScript Array object. Each element inserted in the collection is appended to the end of its internal array as a key-value pair (KVP) object where the key is a unique randomly generated ID string and the value is the element itself. Once the object has been successfully stored, the generated ID (its ID) is returned to the client code and can later be used to access that specific element. At this point, an important difference to the Minimongo API can be highlighted: a TypeSafeCollection instance will never make any changes to the stored element (e.g., no "_id" property will ever be assigned to the original object). Another relevant feature that is supported by this design decision is that not only objects can be stored in this collections, but literally anything.

Inside the codebase, the value attribute of each KVP entry in the collection is refered to as the payload of the entry since it's what really matters to the user. Hence, this term will also be used here to refer to the value that has been stored in the collection. That being said, we can approach another important feature of these collections: A single payload cannot be stored more than once in a given collection. When an attempt of inserting a payload which is already present in the collection is detected, the insert operation will fail and null will be returned. In that regard, the collection behaves like Set object not permitting a payload to be stored more than once. Strict equality is used when comparing payloads, thus cloned objects are not considered the same. This feature adds an additional garantee that a given study/series/instance will not be listed more than once (it was designed as a replacement for central study collections which were always checked for duplicates).

Please refer to the codebase for the full TypeSafeCollection API.

Usage

In order to use the TypeSafeCollection class, the ohif:viewerbase package needs to be imported by the referring code and instantiated as follows:

import { Viewerbase } from 'meteor/ohif:viewerbase'; // i.e., Viewerbase.TypeSafeCollection
OR

import 'meteor/ohif:viewerbase'; // i.e., OHIF.viewerbase.TypeSafeCollection
// The later is preferred when the client code already makes use of the "OHIF" namespace making the second
// "import" a garantee that the ".viewerbase" namespace has been properly loaded.

A few usage examples:


const Users = new OHIF.viewerbase.TypeSafeCollection();

[[ ... ]]

// Insert a User object...
let userId = Users.insert({
    data: {
        firstName: 'John',
        lastName: 'Doe',
        age: 45
    },
    getFullName() {
        return `${this.data.firstName} ${this.data.lastName}`;
    },
    getAge() {
        return this.data.age;
    }
});

[[ ... ]]

let theUserWeJustStored = Users.findById(userId); // ;-)

[[ ... ]]

// Retrieve a single user with "Doe" as `lastName`...
let myUser = Users.findBy({ 'data.lastName': 'Doe' });
// Or all users with "Doe" as `lastName`, sorted by `firstName` in ascending
// order and using the `age` attribute to break ties in descending order...
let myUsers = Users.findAllBy({ 'data.lastName': 'Doe' }, {
    sort: [ [ 'data.firstName', 'asc' ], [ 'data.age', 'desc' ] ]
});