@finos/legend-application-studio
Version:
Legend Studio application core
280 lines • 11.7 kB
JavaScript
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ActionState, LogEvent, assertErrorThrown, guaranteeNonNullable, isNonNullable, } from '@finos/legend-shared';
import { action, computed, flow, makeObservable, observable } from 'mobx';
import { LEGEND_STUDIO_APP_EVENT } from '../__lib__/LegendStudioEvent.js';
import { ShowcaseRegistryServerClient, } from '@finos/legend-server-showcase';
import { ApplicationExtensionState, DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH, } from '@finos/legend-application';
import { DIRECTORY_PATH_DELIMITER } from '@finos/legend-graph';
import { SHOWCASE_MANAGER_VIRTUAL_ASSISTANT_TAB_KEY } from '../components/extensions/Core_LegendStudioApplicationPlugin.js';
import { LegendStudioTelemetryHelper } from '../__lib__/LegendStudioTelemetryHelper.js';
export var SHOWCASE_MANAGER_VIEW;
(function (SHOWCASE_MANAGER_VIEW) {
SHOWCASE_MANAGER_VIEW["EXPLORER"] = "EXPLORER";
SHOWCASE_MANAGER_VIEW["SEARCH"] = "SEARCH";
})(SHOWCASE_MANAGER_VIEW || (SHOWCASE_MANAGER_VIEW = {}));
export var SHOWCASE_MANAGER_SEARCH_CATEGORY;
(function (SHOWCASE_MANAGER_SEARCH_CATEGORY) {
SHOWCASE_MANAGER_SEARCH_CATEGORY["SHOWCASE"] = "SHOWCASE";
SHOWCASE_MANAGER_SEARCH_CATEGORY["CODE"] = "CODE";
})(SHOWCASE_MANAGER_SEARCH_CATEGORY || (SHOWCASE_MANAGER_SEARCH_CATEGORY = {}));
export class ShowcasesExplorerTreeNodeData {
isOpen;
id;
label;
parentId;
childrenIds = [];
metadata;
constructor(id, label, parentId, metadata) {
this.id = id;
this.label = label;
this.parentId = parentId;
this.metadata = metadata;
}
}
const buildShowcasesExplorerTreeNode = (showcase, path, parentId, nodes, rootIds) => {
let node;
const idx = path.indexOf(DIRECTORY_PATH_DELIMITER);
if (idx === -1) {
// showcase node
node = new ShowcasesExplorerTreeNodeData(`${parentId ? `${parentId}${DIRECTORY_PATH_DELIMITER}` : ''}${path}`, showcase.title, parentId, showcase);
}
else {
// directory node
const directoryName = path.substring(0, idx);
const directoryNodeId = `${parentId ? `${parentId}${DIRECTORY_PATH_DELIMITER}` : ''}${directoryName}`;
node =
nodes.get(directoryNodeId) ??
new ShowcasesExplorerTreeNodeData(directoryNodeId, directoryName, undefined, undefined);
}
nodes.set(node.id, node);
if (!parentId && !rootIds.includes(node.id)) {
rootIds.push(node.id);
}
if (parentId) {
const parentNode = nodes.get(parentId);
if (parentNode) {
if (!parentNode.childrenIds.includes(node.id)) {
parentNode.childrenIds.push(node.id);
}
}
}
if (idx !== -1) {
buildShowcasesExplorerTreeNode(showcase, path.substring(idx + 1), node.id, nodes, rootIds);
}
return node;
};
const buildShowcasesExplorerTreeData = (showcases) => {
const rootIds = [];
const nodes = new Map();
showcases.forEach((showcase) => buildShowcasesExplorerTreeNode(showcase, showcase.path, undefined, nodes, rootIds));
return { rootIds, nodes };
};
export class ShowcaseManagerState extends ApplicationExtensionState {
static IDENTIFIER = 'showcase-manager';
applicationStore;
initState = ActionState.create();
fetchShowcaseState = ActionState.create();
textSearchState = ActionState.create();
showcaseServerClient;
allShowcases;
currentShowcase;
showcaseLineToScroll;
currentView = SHOWCASE_MANAGER_VIEW.EXPLORER;
explorerTreeData;
searchText = '';
showcaseSearchResults;
textSearchResults;
currentSearchCaterogy = SHOWCASE_MANAGER_SEARCH_CATEGORY.SHOWCASE;
constructor(applicationStore) {
super();
makeObservable(this, {
allShowcases: observable,
currentShowcase: observable,
currentView: observable,
explorerTreeData: observable.ref,
searchText: observable,
textSearchResults: observable.ref,
showcaseSearchResults: observable.ref,
currentSearchCaterogy: observable,
showcaseLineToScroll: observable,
nonDevShowcases: computed,
logOpenManager: action,
setCurrentView: action,
closeShowcase: action,
setExplorerTreeData: action,
setSearchText: action,
resetSearch: action,
setCurrentSearchCategory: action,
search: flow,
initialize: flow,
openShowcase: flow,
});
this.applicationStore = applicationStore;
if (this.applicationStore.config.showcaseServerUrl) {
this.showcaseServerClient = new ShowcaseRegistryServerClient({
baseUrl: this.applicationStore.config.showcaseServerUrl,
});
}
}
get INTERNAL__identifierKey() {
return ShowcaseManagerState.IDENTIFIER;
}
get nonDevShowcases() {
return this.allShowcases?.filter((showcase) => !showcase.development) ?? [];
}
static retrieveNullableState(applicationStore) {
return applicationStore.extensionStates.find((extensionState) => {
if (
/**
* In development mode, when we make changes in certain areas like utils or base states, the following `instanceof`
* check will fail as if there were multiple copies of the classes with the same name, this could be caused by either
* React `fast-refresh` or `webpack HMR`; we didn't have time to really do a thorough debug here, as such,
* we will just do a simple key check to match the right state to bypass the problem for development mode.
*/
// eslint-disable-next-line no-process-env
process.env.NODE_ENV === 'development') {
return (extensionState.INTERNAL__identifierKey ===
ShowcaseManagerState.IDENTIFIER);
}
return extensionState instanceof ShowcaseManagerState;
});
}
static retrieveState(applicationStore) {
return guaranteeNonNullable(ShowcaseManagerState.retrieveNullableState(applicationStore), `Can't find showcase manager state: make sure it is added as an editor extension state`);
}
get isEnabled() {
return Boolean(this.showcaseServerClient);
}
get client() {
return guaranteeNonNullable(this.showcaseServerClient, `Showcase registry server client is not configured`);
}
setCurrentView(val) {
this.currentView = val;
}
*openShowcase(metadata, showcaseLineToScroll) {
this.fetchShowcaseState.inProgress();
try {
const showcase = (yield this.client.getShowcase(metadata.path));
this.currentShowcase = showcase;
LegendStudioTelemetryHelper.logEvent_ShowcaseManagerShowcaseProjectLaunch(this.applicationStore.telemetryService, {
showcasePath: showcase.path,
});
this.showcaseLineToScroll = showcaseLineToScroll;
this.fetchShowcaseState.pass();
}
catch (error) {
assertErrorThrown(error);
this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
this.fetchShowcaseState.fail();
}
}
logOpenManager() {
if (this.allShowcases) {
const report = {
showcasesTotalCount: this.allShowcases.length,
showcasesDevelopmentCount: this.nonDevShowcases.length,
};
LegendStudioTelemetryHelper.logEvent_ShowcaseManagerLaunch(this.applicationStore.telemetryService, report);
}
}
closeShowcase() {
this.currentShowcase = undefined;
this.showcaseLineToScroll = undefined;
}
setExplorerTreeData(val) {
this.explorerTreeData = val;
}
setSearchText(val) {
this.searchText = val;
}
resetSearch() {
this.searchText = '';
this.textSearchResults = undefined;
this.showcaseSearchResults = undefined;
}
setCurrentSearchCategory(val) {
this.currentSearchCaterogy = val;
}
*initialize() {
if (!this.isEnabled || this.initState.isInProgress) {
return;
}
this.initState.inProgress();
try {
this.allShowcases =
(yield this.client.getShowcases());
this.explorerTreeData = buildShowcasesExplorerTreeData(this.nonDevShowcases);
// expand all the root nodes by default
this.explorerTreeData.rootIds.forEach((rootId) => {
const rootNode = this.explorerTreeData?.nodes.get(rootId);
if (rootNode) {
rootNode.isOpen = true;
}
});
this.setExplorerTreeData({ ...this.explorerTreeData });
this.initState.pass();
}
catch (error) {
assertErrorThrown(error);
this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
this.initState.fail();
}
}
*search() {
if (this.textSearchState.isInProgress ||
this.searchText.length <= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH) {
return;
}
this.textSearchState.inProgress();
try {
const result = (yield this.client.search(this.searchText));
this.textSearchResults = result.textMatches
.map((match) => {
const matchingShowcase = this.nonDevShowcases.find((showcase) => showcase.path === match.path);
if (matchingShowcase) {
return {
showcase: matchingShowcase,
match,
};
}
return undefined;
})
.filter(isNonNullable);
this.showcaseSearchResults = result.showcases
.map((showcasePath) => this.nonDevShowcases.find((showcase) => showcase.path === showcasePath))
.filter(isNonNullable);
}
catch (error) {
assertErrorThrown(error);
this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
}
finally {
this.textSearchState.complete();
}
}
}
export const openShowcaseManager = (applicationStore) => {
const showcaseManagerState = ShowcaseManagerState.retrieveNullableState(applicationStore);
if (showcaseManagerState?.isEnabled) {
applicationStore.assistantService.setIsHidden(false);
applicationStore.assistantService.setIsOpen(true);
applicationStore.assistantService.setIsPanelMaximized(true);
applicationStore.assistantService.setSelectedTab(SHOWCASE_MANAGER_VIRTUAL_ASSISTANT_TAB_KEY);
showcaseManagerState.logOpenManager();
}
};
//# sourceMappingURL=ShowcaseManagerState.js.map