UNPKG

@finos/legend-application-studio

Version:
280 lines 11.7 kB
/** * 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