fix: Make the commands ordering the registration order of hte mode (#4492)

This commit is contained in:
Bill Wallace 2024-11-22 12:00:47 -05:00 committed by GitHub
parent f0dee87882
commit edfaf7248d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 56 deletions

View File

@ -1,7 +1,6 @@
{ {
"name": "ohif-monorepo-root", "name": "ohif-monorepo-root",
"private": true, "private": true,
"packageManager": "yarn@1.22.22",
"workspaces": { "workspaces": {
"packages": [ "packages": [
"platform/*", "platform/*",

View File

@ -19,8 +19,12 @@ import { Command, Commands, ComplexCommand } from '../types/Command';
* to extend this class, please check it's source before adding new methods. * to extend this class, please check it's source before adding new methods.
*/ */
export class CommandsManager { export class CommandsManager {
constructor({} = {}) { private contexts = {};
this.contexts = {}; // Has the reverse order in which contexts are created, used for the default ordering
private contextOrder = new Array<string>();
constructor(_options = {}) {
// No-op
} }
/** /**
@ -33,7 +37,7 @@ export class CommandsManager {
* @param {string} contextName - Namespace for commands * @param {string} contextName - Namespace for commands
* @returns {undefined} * @returns {undefined}
*/ */
createContext(contextName) { createContext(contextName, priority?: number) {
if (!contextName) { if (!contextName) {
return; return;
} }
@ -43,6 +47,8 @@ export class CommandsManager {
} }
this.contexts[contextName] = {}; this.contexts[contextName] = {};
// Add the context name to the start of the list.
this.contextOrder.splice(0, 0, contextName);
} }
/** /**
@ -104,34 +110,22 @@ export class CommandsManager {
* *
* @method * @method
* @param {String} commandName - Command to find * @param {String} commandName - Command to find
* @param {String} [contextName] - Specific command to look in. Defaults to current activeContexts * @param {String} [contextName] - Specific command to look in. Defaults to current activeContexts.
* Also allows an array of contexts to look in.
*/ */
getCommand = (commandName: string, contextName?: string) => { getCommand = (commandName: string, contextName: string | string[] = this.contextOrder) => {
const contexts = []; const contexts = [];
if (contextName) { if (Array.isArray(contextName)) {
contexts.push(...contextName.map(name => this.getContext(name)).filter(it => !!it));
} else if (contextName) {
const context = this.getContext(contextName); const context = this.getContext(contextName);
if (context) { if (context) {
contexts.push(context); contexts.push(context);
} }
} else {
Object.keys(this.contexts).forEach(contextName => {
contexts.push(this.getContext(contextName));
});
} }
if (contexts.length === 0) { return contexts.find(context => !!context[commandName])?.[commandName];
return;
}
let foundCommand;
contexts.forEach(context => {
if (context[commandName]) {
foundCommand = context[commandName];
}
});
return foundCommand;
}; };
/** /**
@ -141,7 +135,7 @@ export class CommandsManager {
* @param {Object} [options={}] - Extra options to pass the command. Like a mousedown event * @param {Object} [options={}] - Extra options to pass the command. Like a mousedown event
* @param {String} [contextName] * @param {String} [contextName]
*/ */
public runCommand(commandName: string, options = {}, contextName?: string) { public runCommand(commandName: string, options = {}, contextName?: string | string[]) {
const definition = this.getCommand(commandName, contextName); const definition = this.getCommand(commandName, contextName);
if (!definition) { if (!definition) {
log.warn(`Command "${commandName}" not found in current context`); log.warn(`Command "${commandName}" not found in current context`);

View File

@ -7,21 +7,30 @@ sidebar_label: Commands Manager
## Overview ## Overview
The `CommandsManager` is a class defined in the `@ohif/core` project. The Commands Manager tracks named commands (or functions) that are scoped to The `CommandsManager` is a class defined in the `@ohif/core` project.
The Commands Manager tracks named commands (or functions) that are scoped to
a context. When we attempt to run a command with a given name, we look for it a context. When we attempt to run a command with a given name, we look for it
in our active contexts. If found, we run the command, passing in any application in our active contexts, in the order specified.
If found, we run the command, passing in any application
or call specific data specified in the command's definition. or call specific data specified in the command's definition.
> Note: A single instance of `CommandsManager` should be defined in the consuming application, and it is used when constructing the `ExtensionManager`. The order specified is the REVERSE of the order the modules are registered in
for the mode dependency. That is, the last module registered has the highest priority
and will be searched first for commands. This has nothing to do with when the
command itself is registered, although registrations for the same command in different
modules in the same context will also use last registration wins.
> Note: A single instance of `CommandsManager` should be defined in the consuming
application, and it is used when constructing the `ExtensionManager`.
A `simplified skeleton` of the `CommandsManager` is shown below: A `simplified skeleton` of the `CommandsManager` is shown below:
```js ```js
export class CommandsManager { export class CommandsManager {
constructor({ getActiveContexts } = {}) { contexts = {};
this.contexts = {}; contextOrder = [];
this._getActiveContexts = getActiveContexts;
} constructor(_ignoredConfig) {}
getContext(contextName) { getContext(contextName) {
const context = this.contexts[contextName]; const context = this.contexts[contextName];
@ -33,6 +42,7 @@ export class CommandsManager {
createContext(contextName) { createContext(contextName) {
/** ... **/ /** ... **/
this.contexts[contextName] = {}; this.contexts[contextName] = {};
this.contextOrder.push at beginning(contextName)
} }
@ -43,6 +53,11 @@ export class CommandsManager {
context[commandName] = definition; context[commandName] = definition;
} }
getCommand(commandName, contextName) {
const useContext = contextName || first context having commandName in contextOrder
return useContext[commandName];
}
runCommand(commandName, options = {}, contextName) { runCommand(commandName, options = {}, contextName) {
const definition = this.getCommand(commandName, contextName); const definition = this.getCommand(commandName, contextName);
/**...**/ /**...**/
@ -64,33 +79,13 @@ export class CommandsManager {
### Instantiating ### Instantiating
When we instantiate the `CommandsManager`, we are passing two methods: No methods or configuration is used within the construction.
- `getAppState` - Should return the application's state when called (Not implemented in `v3`)
- `getActiveContexts` - Should return the application's active contexts when
called
These methods are used internally to help determine which commands are currently
valid, and how to provide them with any state they may need at the time they are
called.
```js title="platform/app/src/appInit.js"
const commandsManagerConfig = {
getAppState: () => {},
/** Used by commands to determine active context */
getActiveContexts: () => [
'VIEWER',
'DEFAULT',
'ACTIVE_VIEWPORT::CORNERSTONE',
],
};
const commandsManager = new CommandsManager(commandsManagerConfig);
```
## Commands/Context Registration ## Commands/Context Registration
The `ExtensionManager` handles registering commands and creating contexts, so you don't need to register all your commands manually. Simply, create a `commandsModule` in your extension, and it will get automatically registered in the `context` provided. The `ExtensionManager` handles registering commands and creating contexts, so you
don't need to register all your commands manually. Simply, create a `commandsModule`
in your extension, and it will get automatically registered in the `context` provided.
A *simplified version* of this registration is shown below to give an idea about the process. A *simplified version* of this registration is shown below to give an idea about the process.
@ -173,7 +168,7 @@ use `runCommand(commandName, options = {}, contextName)`.
commandsManager.runCommand('speak', { command: 'hello' }); commandsManager.runCommand('speak', { command: 'hello' });
// Run command, from Default context // Run command, from Default context
commandsManager.runCommand('speak', { command: 'hello' }, ['DEFAULT']); commandsManager.runCommand('speak', { command: 'hello' }, 'DEFAULT');
// Returns all commands for a given context // Returns all commands for a given context
commandsManager.getContext('string'); commandsManager.getContext('string');