From 2a9d3c568feaa1fe704305562205758f78edfb05 Mon Sep 17 00:00:00 2001 From: Yannan Date: Thu, 25 Aug 2022 10:32:12 -0400 Subject: [PATCH] allow loading query from inside of query builder --- .changeset/giant-coats-lay.md | 5 + .changeset/proud-boxes-joke.md | 4 + .../style/index.scss | 45 ++++ .../src/components/QueryEditor.tsx | 233 +++++++++++++++++- .../src/stores/QueryEditorStore.ts | 55 +++++ .../style/_query-editor.scss | 146 +++++++++++ .../uml-editor/AssociationEditor.tsx | 1 - 7 files changed, 485 insertions(+), 4 deletions(-) create mode 100644 .changeset/giant-coats-lay.md create mode 100644 .changeset/proud-boxes-joke.md diff --git a/.changeset/giant-coats-lay.md b/.changeset/giant-coats-lay.md new file mode 100644 index 00000000000..12743f38c78 --- /dev/null +++ b/.changeset/giant-coats-lay.md @@ -0,0 +1,5 @@ +--- +'@finos/legend-application-query': patch +--- + +Allow loading query from inside of query builder ([#1435](https://github.com/finos/legend-studio/issues/1435)). diff --git a/.changeset/proud-boxes-joke.md b/.changeset/proud-boxes-joke.md new file mode 100644 index 00000000000..3ece90eb69c --- /dev/null +++ b/.changeset/proud-boxes-joke.md @@ -0,0 +1,4 @@ +--- +'@finos/legend-application-query-bootstrap': patch +'@finos/legend-application-studio': patch +--- diff --git a/packages/legend-application-query-bootstrap/style/index.scss b/packages/legend-application-query-bootstrap/style/index.scss index b8ea13ea832..9dc7b7afee5 100644 --- a/packages/legend-application-query-bootstrap/style/index.scss +++ b/packages/legend-application-query-bootstrap/style/index.scss @@ -247,6 +247,51 @@ } } + // ---------------------------- Query Loader ------------------------------- + + .query-editor { + &__query-loader { + &__filter-section { + &__header__label { + color: var(--color-legacy-dark-grey-200); + } + + &__section__toggler__btn { + svg { + color: var(--color-legacy-light-blue-100); + } + } + + &__section__toggler__prompt { + color: var(--color-legacy-dark-grey-200); + } + } + + &__search-section { + border-bottom: 0.1rem solid var(--color-legacy-light-grey-200); + + &__input { + border: 0.1rem solid var(--color-legacy-light-grey-200); + } + } + + &__body { + .table { + color: var(--color-legacy-dark-grey-200); + } + + &__table__row:hover { + color: var(--color-legacy-light-blue-100); + background-color: var(--color-legacy-light-grey-200); + } + + &__table__row--selected { + background-color: var(--color-legacy-light-grey-200); + } + } + } + } + // ---------------------------- Property Search ------------------------------- .query-builder-property-search-panel { diff --git a/packages/legend-application-query/src/components/QueryEditor.tsx b/packages/legend-application-query/src/components/QueryEditor.tsx index 14fc124b0b1..9cc239fec72 100644 --- a/packages/legend-application-query/src/components/QueryEditor.tsx +++ b/packages/legend-application-query/src/components/QueryEditor.tsx @@ -15,6 +15,7 @@ */ import { + type SelectComponent, Dialog, ArrowLeftIcon, ExternalLinkSquareIcon, @@ -25,10 +26,14 @@ import { clsx, EmptyLightBulbIcon, LightBulbIcon, + SearchIcon, + TimesIcon, + CheckSquareIcon, + SquareIcon, } from '@finos/legend-art'; import { getQueryParameters } from '@finos/legend-shared'; import { observer } from 'mobx-react-lite'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { useParams } from 'react-router'; @@ -41,6 +46,7 @@ import { LEGEND_QUERY_QUERY_PARAM_TOKEN, LEGEND_QUERY_PATH_PARAM_TOKEN, generateStudioProjectViewUrl, + generateExistingQueryEditorRoute, } from '../stores/LegendQueryRouter.js'; import { type QueryEditorStore, @@ -50,7 +56,10 @@ import { ServiceQueryEditorStore, } from '../stores/QueryEditorStore.js'; import { QueryBuilder } from './QueryBuilder.js'; -import { useApplicationStore } from '@finos/legend-application'; +import { + type ApplicationStore, + useApplicationStore, +} from '@finos/legend-application'; import { CreateQueryEditorStoreProvider, ExistingQueryEditorStoreProvider, @@ -58,11 +67,14 @@ import { useQueryEditorStore, } from './QueryEditorStoreProvider.js'; import { - extractElementNameFromPath, + type LightQuery, type RawLambda, + extractElementNameFromPath, } from '@finos/legend-graph'; import { flowResult } from 'mobx'; import { useLegendQueryApplicationStore } from './LegendQueryBaseStoreProvider.js'; +import type { LegendQueryApplicationConfig } from '../application/LegendQueryApplicationConfig.js'; +import type { LegendQueryApplicationPlugin } from '../stores/LegendQueryApplicationPlugin.js'; const QueryExportDialogContent = observer( (props: { exportState: QueryExportState }) => { @@ -189,9 +201,211 @@ const renderQueryEditorHeaderLabel = ( return null; }; +const QueryLoader = observer( + (props: { + editorStore: QueryEditorStore; + applicationStore: ApplicationStore< + LegendQueryApplicationConfig, + LegendQueryApplicationPlugin + >; + }) => { + const { editorStore, applicationStore } = props; + const queryFinderRef = useRef(null); + const [selectedQueryID, setSelectedQueryID] = useState(''); + const queryLoaderColumns = ['Name', 'Author', 'VersionID']; + const closeQueryImporter = (): void => { + editorStore.setIsQueryLoaderOpen(!editorStore.isQueryLoaderOpen); + }; + const handleEnterQueryImporter = (): void => + queryFinderRef.current?.focus(); + const loadSelectedQuery = (): void => { + if (selectedQueryID) { + editorStore.setIsQueryLoaderOpen(!editorStore.isQueryLoaderOpen); + applicationStore.navigator.goTo( + generateExistingQueryEditorRoute(selectedQueryID), + ); + window.location.reload(); + } else { + applicationStore.notifyWarning( + 'No query is selected. Please select a query to load or close.', + ); + } + }; + const buildQueryTableRow = (query: LightQuery): string[] => [ + query.name, + query.owner ?? 'anonymous', + query.versionId, + ]; + const searchInputRef = useRef(null); + const searchQuery: React.ChangeEventHandler = (event) => { + editorStore.setSearchText(event.target.value); + if (editorStore.searchText.length >= 0) { + flowResult(editorStore.loadQueries(editorStore.searchText)) + .then(() => editorStore.setIsLoadingQueryInProgress(false)) + .catch(applicationStore.alertUnhandledError); + } else { + flowResult(editorStore.loadQueries('')) + .then(() => editorStore.setIsLoadingQueryInProgress(false)) + .catch(applicationStore.alertUnhandledError); + } + }; + const clearQuerySearching = (): void => { + editorStore.setSearchText(''); + flowResult(editorStore.loadQueries(editorStore.searchText)) + .then(() => editorStore.setIsLoadingQueryInProgress(false)) + .catch(applicationStore.alertUnhandledError); + }; + const toggleIsMineOnly = (): void => { + editorStore.setIsMineOnly(!editorStore.isMineOnly); + }; + + return ( + +
+
Select a Query to Load
+
+
+ Filter the queries +
+
+ +
+ Mine Only +
+
+
+
+
+ + {!editorStore.searchText ? ( +
+ +
+ ) : ( + <> + + + )} +
+
+
+ {!editorStore.isLoadingQueryInProgress && ( + <> + + + + {queryLoaderColumns.map((column, idx) => ( + // eslint-disable-next-line react/no-array-index-key + + ))} + + + + {(editorStore.isMineOnly + ? editorStore.queries.filter((q) => q.isCurrentUserQuery) + : editorStore.queries + ).map((q) => ( + setSelectedQueryID(q.id)} + > + {buildQueryTableRow(q).map((value) => ( + + ))} + + ))} + +
+ {column} +
+ {value} +
+
+ Show relevant queries by searching names +
+ + )} + {editorStore.isLoadingQueryInProgress && ( + <> + + loading queries... + + )} +
+
+ + +
+
+
+ ); + }, +); + const QueryEditorHeaderContent = observer(() => { const editorStore = useQueryEditorStore(); const applicationStore = useLegendQueryApplicationStore(); + const loadQuery = (): void => { + editorStore.setIsQueryLoaderOpen(!editorStore.isQueryLoaderOpen); + flowResult(editorStore.loadQueries('')) + .then(() => editorStore.setIsLoadingQueryInProgress(false)) + .catch(applicationStore.alertUnhandledError); + }; const viewQueryProject = (): void => { const { groupId, artifactId, versionId } = editorStore.getProjectInfo(); applicationStore.navigator.openNewWindow( @@ -228,6 +442,13 @@ const QueryEditorHeaderContent = observer(() => { {renderQueryEditorHeaderLabel(editorStore)}
+ )} + {editorStore.isQueryLoaderOpen && ( + + )}