@finos/legend-application-pure-ide
Version:
Legend Pure IDE application core
115 lines • 10.6 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
* 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 { observer } from 'mobx-react-lite';
import { FileCoordinate, trimPathLeadingSlash, } from '../../server/models/File.js';
import { flowResult } from 'mobx';
import { CaseSensitiveIcon, ChevronDownIcon, ChevronRightIcon, CloseIcon, clsx, CollapseTreeIcon, ExpandTreeIcon, FileAltIcon, PanelLoadingIndicator, RefreshIcon, RegexIcon, TimesIcon, } from '@finos/legend-art';
import { useApplicationStore } from '@finos/legend-application';
import { usePureIDEStore } from '../PureIDEStoreProvider.js';
import { useEffect, useMemo, useRef } from 'react';
import { debounce } from '@finos/legend-shared';
import { PANEL_MODE } from '../../stores/PureIDEConfig.js';
const TextSearchResultEntryDisplay = observer((props) => {
const { searchResult, result } = props;
const ideStore = usePureIDEStore();
const applicationStore = useApplicationStore();
const goToResult = (coordinate) => () => flowResult(ideStore.loadFile(result.sourceId, new FileCoordinate(result.sourceId, coordinate.startLine, coordinate.startColumn))).catch(applicationStore.alertUnhandledError);
const dismissResultForFile = () => searchResult.dismissSearchEntry(result);
const dismissCoordinate = (coordinate) => () => {
result.dismissCoordinate(coordinate);
if (!result.coordinates.length) {
searchResult.dismissSearchEntry(result);
}
};
return (_jsxs("div", { className: "text-search-panel__entry", children: [_jsxs("div", { className: "text-search-panel__entry__header", onClick: () => result.setIsExpanded(!result.isExpanded), children: [_jsxs("div", { className: "text-search-panel__entry__header__title", children: [_jsx("div", { className: "text-search-panel__entry__header__title__expander", children: result.isExpanded ? _jsx(ChevronDownIcon, {}) : _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "text-search-panel__entry__header__title__label", children: _jsx(FileAltIcon, {}) }), _jsx("div", { className: "text-search-panel__entry__header__title__content", children: trimPathLeadingSlash(result.sourceId) })] }), _jsxs("div", { className: "text-search-panel__entry__header__actions", children: [_jsx("div", { className: "text-search-panel__entry__header__action text-search-panel__entry__header__action--with-counter", children: _jsx("div", { className: "text-search-panel__entry__header__action__counter", children: result.coordinates.length }) }), _jsx("button", { className: "text-search-panel__entry__header__action text-search-panel__entry__header__action--hidden", tabIndex: -1, title: "Dismiss", onClick: dismissResultForFile, children: _jsx(TimesIcon, {}) })] })] }), result.isExpanded && (_jsx("div", { className: "text-search-panel__entry__content", children: result.coordinates.map((coordinate) => (_jsxs("div", { className: "text-search-panel__entry__content__item", children: [_jsxs("div", { className: "text-search-panel__entry__content__item__label text-search-panel__entry__content__item__label--full", title: coordinate.preview
? `${coordinate.preview.before}${coordinate.preview.found.replaceAll(/\n/g, '\u21B5')}${coordinate.preview.after}`
: 'Go To Result', onClick: goToResult(coordinate), children: [coordinate.preview && (_jsxs("div", { className: "text-search-panel__entry__content__item__label__content", children: [_jsx("div", { className: "text-search-panel__entry__content__item__label__coordinates", children: `[${coordinate.startLine}:${coordinate.startColumn}]` }), _jsxs("div", { className: "text-search-panel__entry__content__item__label__preview", children: [_jsx("span", { className: "text-search-panel__entry__content__item__label__preview__text", children: coordinate.preview.before }), _jsx("span", { className: "text-search-panel__entry__content__item__label__preview__text text-search-panel__entry__content__item__label__preview__text--found", children: coordinate.preview.found.replaceAll(/\n/g, '\u21B5') }), _jsx("span", { className: "text-search-panel__entry__content__item__label__preview__text", children: coordinate.preview.after })] })] })), !coordinate.preview && (_jsx(_Fragment, { children: `line: ${coordinate.startLine} - column: ${coordinate.startColumn}` }))] }), _jsx("div", { className: "text-search-panel__entry__content__item__actions", children: _jsx("button", { className: "text-search-panel__entry__content__item__action text-search-panel__entry__content__item__action--hidden", tabIndex: -1, title: "Dismiss", onClick: dismissCoordinate(coordinate), children: _jsx(TimesIcon, {}) }) })] }, coordinate.uuid))) }))] }));
});
const TextSearchResultDisplay = observer((props) => {
const { searchResult } = props;
const ideStore = usePureIDEStore();
const applicationStore = useApplicationStore();
const showExpandAction = searchResult.searchEntries.some((entry) => !entry.isExpanded);
const refresh = () => {
flowResult(ideStore.textSearchState.search()).catch(applicationStore.alertUnhandledError);
};
const clear = () => {
ideStore.textSearchState.setText('');
ideStore.textSearchState.setResult(undefined);
};
const expandAll = () => {
searchResult.searchEntries.forEach((entry) => entry.setIsExpanded(true));
};
const collapseAll = () => {
searchResult.searchEntries.forEach((entry) => entry.setIsExpanded(false));
};
return (_jsxs("div", { className: "text-search-panel__content", children: [_jsxs("div", { className: "text-search-panel__content__header", children: [_jsx("div", { className: "text-search-panel__content__header__title", children: !searchResult.searchEntries.length
? `No result`
: `${searchResult.numberOfResults} result(s) in ${searchResult.numberOfFiles} files` }), _jsxs("div", { className: "text-search-panel__content__header__actions", children: [_jsx("button", { className: "text-search-panel__content__header__action", tabIndex: -1, title: "Refresh", onClick: refresh, children: _jsx(RefreshIcon, {}) }), _jsx("button", { className: "text-search-panel__content__header__action", tabIndex: -1, title: "Clear", onClick: clear, children: _jsx(CloseIcon, {}) }), !showExpandAction && (_jsx("button", { className: "text-search-panel__content__header__action", tabIndex: -1, title: "Collapse All", onClick: collapseAll, children: _jsx(CollapseTreeIcon, {}) })), showExpandAction && (_jsx("button", { className: "text-search-panel__content__header__action", tabIndex: -1, title: "Expand All", onClick: expandAll, children: _jsx(ExpandTreeIcon, {}) }))] })] }), _jsx("div", { className: "text-search-panel__content__results", children: searchResult.searchEntries.map((searchEntry) => (_jsx(TextSearchResultEntryDisplay, { searchResult: searchResult, result: searchEntry }, searchEntry.uuid))) })] }));
});
export const TextSearchPanel = observer(() => {
const ideStore = usePureIDEStore();
const searchInputRef = useRef(null);
const searchState = ideStore.textSearchState;
const toggleCaseSensitive = () => searchState.setCaseSensitive(!searchState.isCaseSensitive);
const toggleRegExp = () => searchState.setRegExp(!searchState.isRegExp);
const debouncedSearch = useMemo(() => debounce(() => searchState.search(), 300), [searchState]);
const onSearchTextChange = (event) => {
const value = event.target.value;
searchState.setText(value);
debouncedSearch.cancel();
if (!value) {
searchState.setResult(undefined);
}
else {
debouncedSearch();
}
};
const onSearchKeyDown = (event) => {
if (event.code === 'Enter') {
debouncedSearch.cancel();
if (searchState.text) {
debouncedSearch();
}
}
else if (event.code === 'Escape') {
searchInputRef.current?.select();
}
};
useEffect(() => {
if (searchInputRef.current) {
searchState.setSearchInput(searchInputRef.current);
}
return () => searchState.setSearchInput(undefined);
}, [searchState]);
useEffect(() => {
if (ideStore.panelGroupDisplayState.isOpen &&
ideStore.activePanelMode === PANEL_MODE.SEARCH) {
searchState.focus();
}
}, [
searchState,
ideStore.panelGroupDisplayState.isOpen,
ideStore.activePanelMode,
]);
return (_jsxs("div", { className: "text-search-panel", children: [_jsx(PanelLoadingIndicator, { isLoading: ideStore.textSearchState.loadState.isInProgress }), _jsx("div", { className: "text-search-panel__header", children: _jsxs("div", { className: "text-search-panel__searcher__input__container", children: [_jsx("input", { ref: searchInputRef, autoFocus: true, className: "text-search-panel__searcher__input input--dark", onChange: onSearchTextChange, onKeyDown: onSearchKeyDown, value: searchState.text, placeholder: "Search" }), _jsxs("div", { className: "text-search-panel__searcher__input__actions", children: [_jsx("button", { className: clsx('text-search-panel__searcher__input__action', {
'text-search-panel__searcher__input__action--active': searchState.isCaseSensitive,
}), tabIndex: -1, title: "Match Case", onClick: toggleCaseSensitive, children: _jsx(CaseSensitiveIcon, {}) }), _jsx("button", { className: clsx('text-search-panel__searcher__input__action', {
'text-search-panel__searcher__input__action--active': searchState.isRegExp,
}), tabIndex: -1, title: "Use Regular Expression", onClick: toggleRegExp, children: _jsx(RegexIcon, {}) })] })] }) }), ideStore.textSearchState.result && (_jsx(TextSearchResultDisplay, { searchResult: ideStore.textSearchState.result }))] }));
});
//# sourceMappingURL=TextSearchPanel.js.map