fix(cli): better support for external modules and toolGroups in templates (#3364)

* choe(modes, components): improved readability

This commit includes changes to improve performance in the basic-dev-mode and Thumbnail components.
Additionally, a change in the webpack configuration file was made to ignore ".min.js.map" files.
The defaultDataSourceName was also added to several configuration files, and whiteLabeling code was removed
from the local_orthanc configuration file.

* fix(cli): better path management and add dependencies

* better docs

* add default tool group to the templates

* add review comments

* apply review comments

* try to fix test

* fix thumbnail in tests
This commit is contained in:
Alireza authored and GitHub committed 2023-05-08 15:49:28 -04:00
1 parent 187e6b5f30
commit 2f355fa158
26 files changed
+193 -142

No files matched your search

+29 -1
View File
@@ -41,9 +41,37 @@ async function linkPackage(packageDir, options, addToConfig, keyword) {
results = await execa(`yarn`, ['link', packageName]);
console.log(results.stdout);
// Add the node_modules of the linked package so that webpack
// can find the linked package externals if there are
const webpackPwaPath = path.join(
viewerDirectory,
'.webpack',
'webpack.pwa.js'
);
async function updateWebpackConfig(webpackConfigPath, packageDir) {
const packageNodeModules = path.join(packageDir, 'node_modules');
const fileContent = await fs.promises.readFile(webpackConfigPath, 'utf8');
const newLine = `path.resolve(__dirname, '${packageNodeModules}'),`;
const modifiedFileContent = fileContent.replace(
/(modules:\s*\[)([\s\S]*?)(\])/,
`$1$2 ${newLine}$3`
);
await fs.promises.writeFile(webpackConfigPath, modifiedFileContent);
}
await updateWebpackConfig(webpackPwaPath, packageDir);
// change directory to viewer packages and add the config item
process.chdir(viewerDirectory);
addToConfig(packageName, { version });
addToConfig(packageName, {
version,
});
// run prettier on the webpack config
results = await execa(`yarn`, ['prettier', '--write', webpackPwaPath]);
}
function linkExtension(packageDir, options) {
@@ -1,4 +1,6 @@
import { execa } from 'execa';
import fs from 'fs';
import path from 'path';
import {
validateYarn,
removeExtensionFromConfig,
@@ -17,10 +19,51 @@ const linkPackage = async (packageName, options, removeFromConfig) => {
const results = await execa(`yarn`, ['unlink', packageName]);
console.log(results.stdout);
const webpackPwaPath = path.join(
viewerDirectory,
'.webpack',
'webpack.pwa.js'
);
await removePathFromWebpackConfig(webpackPwaPath, packageName);
//update the plugin.json file
removeFromConfig(packageName);
// run prettier on the webpack config
await execa(`yarn`, ['prettier', '--write', webpackPwaPath]);
};
async function removePathFromWebpackConfig(webpackConfigPath, packageName) {
const fileContent = await fs.promises.readFile(webpackConfigPath, 'utf8');
const packageNameSubstring = `${packageName}/node_modules`;
const pathResolveStart = 'path.resolve(';
const closingParenthesis = ')';
let startIndex = fileContent.indexOf(packageNameSubstring);
if (startIndex === -1) {
return;
}
// Find the start of the "path.resolve" line.
startIndex = fileContent.lastIndexOf(pathResolveStart, startIndex);
// Find the end of the line with the closing parenthesis.
let endIndex = fileContent.indexOf(closingParenthesis, startIndex) + 1;
// Check if there's a comma after the closing parenthesis and remove it as well.
if (fileContent[endIndex] === ',') {
endIndex++;
}
const modifiedFileContent =
fileContent.slice(0, startIndex) + fileContent.slice(endIndex);
await fs.promises.writeFile(webpackConfigPath, modifiedFileContent);
}
function unlinkExtension(extensionName, options) {
linkPackage(extensionName, options, removeExtensionFromConfig);
}
@@ -6,9 +6,9 @@ export default function writePluginConfigFile(pluginConfig) {
fs.writeFileSync(
`./pluginConfig.json`,
jsonStringOfFileContents,
jsonStringOfFileContents + '\n', // Add a newline character at the end
{ flag: 'w+' },
(err) => {
err => {
if (err) {
console.error(err);
return;
+12 -4
View File
@@ -1,4 +1,5 @@
import path from 'path';
import os from 'os';
function getPathQuestions(packageType) {
return [
@@ -6,7 +7,7 @@ function getPathQuestions(packageType) {
type: 'input',
name: 'name',
message: `What is the name of your ${packageType}?`,
validate: (input) => {
validate: input => {
if (!input) {
return 'Please enter a name';
}
@@ -17,8 +18,8 @@ function getPathQuestions(packageType) {
{
type: 'input',
name: 'baseDir',
message: `What is the target absolute path to create your ${packageType} (we recommend you do not use the OHIF ${packageType} folder (./${packageType}s) unless you are developing a core ${packageType}):`,
validate: (input) => {
message: `What is the target path to create your ${packageType} (we recommend you do not use the OHIF ${packageType} folder (./${packageType}s) unless you are developing a core ${packageType}):`,
validate: input => {
if (!input) {
console.log('Please provide a valid target directory path');
return;
@@ -26,7 +27,13 @@ function getPathQuestions(packageType) {
return true;
},
filter: (input, answers) => {
return path.resolve(input, answers.name);
// Replace ~ with the user's home directory
const expandedPath = input.replace(/^~(?=$|\/|\\)/, os.homedir());
// Resolve the path to an absolute path
const resolvedPath = path.resolve(expandedPath, answers.name);
return resolvedPath;
},
},
{
@@ -43,6 +50,7 @@ function getRepoQuestions(packageType) {
type: 'confirm',
name: 'gitRepository',
message: 'Should it be a git repository?',
default: false,
},
{
type: 'confirm',
+73 -7
View File
@@ -1,4 +1,6 @@
import { hotkeys } from '@ohif/core';
import { id } from './id';
import { initToolGroups, toolbarButtons } from '@ohif/mode-longitudinal';
const ohif = {
layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout',
@@ -38,12 +40,76 @@ function modeFactory({ modeConfiguration }) {
* Runs when the Mode Route is mounted to the DOM. Usually used to initialize
* Services and other resources.
*/
onModeEnter: ({ servicesManager, extensionManager }) => {},
/**
* Runs when the Mode Route is unmounted from the DOM. Usually used to clean
* up resources and states
*/
onModeExit: () => {},
onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => {
const {
measurementService,
toolbarService,
toolGroupService,
} = servicesManager.services;
measurementService.clearMeasurements();
// Init Default and SR ToolGroups
initToolGroups(extensionManager, toolGroupService, commandsManager);
let unsubscribe;
const activateTool = () => {
toolbarService.recordInteraction({
groupId: 'WindowLevel',
itemId: 'WindowLevel',
interactionType: 'tool',
commands: [
{
commandName: 'setToolActive',
commandOptions: {
toolName: 'WindowLevel',
},
context: 'CORNERSTONE',
},
],
});
// We don't need to reset the active tool whenever a viewport is getting
// added to the toolGroup.
unsubscribe();
};
// Since we only have one viewport for the basic cs3d mode and it has
// only one hanging protocol, we can just use the first viewport
({ unsubscribe } = toolGroupService.subscribe(
toolGroupService.EVENTS.VIEWPORT_ADDED,
activateTool
));
toolbarService.init(extensionManager);
toolbarService.addButtons(toolbarButtons);
toolbarService.createButtonSection('primary', [
'MeasurementTools',
'Zoom',
'WindowLevel',
'Pan',
'Capture',
'Layout',
'MPR',
'Crosshairs',
'MoreTools',
]);
},
onModeExit: ({ servicesManager }) => {
const {
toolGroupService,
syncGroupService,
toolbarService,
segmentationService,
cornerstoneViewportService,
} = servicesManager.services;
toolGroupService.destroy();
syncGroupService.destroy();
segmentationService.destroy();
cornerstoneViewportService.destroy();
},
/** */
validationTags: {
study: [],
@@ -93,7 +159,7 @@ function modeFactory({ modeConfiguration }) {
/** SopClassHandlers used by the mode */
sopClassHandlers: [ohif.sopClassHandler],
/** hotkeys for mode */
hotkeys: [''],
hotkeys: [...hotkeys.defaults.hotkeyBindings],
};
}