From 3475d4d34a4ebf24d25a5e95c0717000a063ecd1 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 17 Sep 2020 13:51:13 -0400 Subject: [PATCH 01/20] Good basic tests of leftIcon in admin > tests > select --- .../src/admin/tests/Select/SelectTestModel.js | 15 ++++++++ .../src/admin/tests/Select/SelectTestPanel.js | 34 ++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/client-app/src/admin/tests/Select/SelectTestModel.js b/client-app/src/admin/tests/Select/SelectTestModel.js index c277bc886..d8f8b8cff 100644 --- a/client-app/src/admin/tests/Select/SelectTestModel.js +++ b/client-app/src/admin/tests/Select/SelectTestModel.js @@ -6,23 +6,38 @@ import {times} from 'lodash'; export class SelectTestModel { @bindable selectValue; + @bindable creatableValue; + @bindable asyncValue; + @bindable asyncCreatableValue; + @bindable groupedValue; + @bindable.ref objectValue + @bindable bigValue; + @bindable numOptions = 1000; + @bindable bigOptions; + @bindable + asyncCreatableValue2; + + @bindable.ref + objectValue2 + + constructor() { this.addReaction({ track: () => this.numOptions, diff --git a/client-app/src/admin/tests/Select/SelectTestPanel.js b/client-app/src/admin/tests/Select/SelectTestPanel.js index c163c89f3..fb0de8a01 100644 --- a/client-app/src/admin/tests/Select/SelectTestPanel.js +++ b/client-app/src/admin/tests/Select/SelectTestPanel.js @@ -29,12 +29,12 @@ export const SelectTestPanel = hoistCmp({ selectProps: {...restaurantProps, enableCreate: true} }), example({ - name: 'Select queryFn', + name: 'Select queryFn & optionRenderer', bind: 'asyncValue', selectProps: customerProps }), example({ - name: 'Select queryFn enableCreate', + name: 'Select queryFn & enableCreate & optionRenderer', bind: 'asyncCreatableValue', selectProps: {...customerProps, enableCreate: true} }) @@ -73,9 +73,10 @@ export const SelectTestPanel = hoistCmp({ } }), example({ - name: 'Select (with many options) enableWindowed', + name: 'Select (with many options) enableWindowed & leftIcon', bind: 'bigValue', selectProps: { + leftIcon: Icon.search(), options: model.bigOptions, enableWindowed: true, placeholder: 'Select a number...' @@ -84,7 +85,32 @@ export const SelectTestPanel = hoistCmp({ hbox( label('number of options: '), numberInput({bind: 'numOptions'}) - ) + ), + example({ + name: 'Select with leftIcon & object options & hideDropdownIndicator:true', + bind: 'objectValue2', + selectProps: { + leftIcon: Icon.search(), + hideDropdownIndicator: true, + // options: ['test', 'fail'] + options: [ + {label: 'Hot Tea', value: {ingredients: ['water', 'tea leaves'], warnings: ['hot'], price: 1.75}}, + {label: 'Iced Tea', value: {ingredients: ['water', 'tea leaves', 'ice', 'lemon'], price: 2.50}}, + {label: 'Coffee', value: {ingredients: ['coffee beans', 'water'], warnings: ['addictive', 'hot'], price: 3.25}}, + {label: 'Soda', value: {ingredients: 'unknown', warnings: ['sweet', 'acidic'], price: 1.50}}, + {label: 'Red Wine', value: {ingredients: ['grapes', 'water', 'yeast', 'time'], warnings: ['alcoholic', 'staining'], needId: true, price: 6.75}} + ] + } + }), + example({ + name: 'Select with leftIcon & queryFn & enableCreate & optionRenderer', + bind: 'asyncCreatableValue2', + selectProps: { + ...customerProps, + leftIcon: Icon.office(), + enableCreate: true + } + }) ) ) }); From 63d159a360d56d86fb5e92b2b7687f700a967d4a Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 17 Sep 2020 17:58:34 -0400 Subject: [PATCH 02/20] Small refactor of select tests. --- .../src/admin/tests/Select/SelectTestPanel.js | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/client-app/src/admin/tests/Select/SelectTestPanel.js b/client-app/src/admin/tests/Select/SelectTestPanel.js index fb0de8a01..ff4315441 100644 --- a/client-app/src/admin/tests/Select/SelectTestPanel.js +++ b/client-app/src/admin/tests/Select/SelectTestPanel.js @@ -44,32 +44,14 @@ export const SelectTestPanel = hoistCmp({ name: 'Select (with grouped options)', bind: 'groupedValue', selectProps: { - options: [ - {label: 'cookies', options: [ - 'oatmeal', - 'chocolate chip', - 'peanut butter' - ]}, - {label: 'cakes', options: [ - 'red velvet', 'tres leches', 'German\'s chocolate', 'cheesecake' - ]}, - {label: 'ice cream', options: [ - 'vanilla', 'chocolate', 'strawberry' - ]} - ] + options: desserts } }), example({ name: 'Select (with Object options)', bind: 'objectValue', selectProps: { - options: [ - {label: 'Hot Tea', value: {ingredients: ['water', 'tea leaves'], warnings: ['hot'], price: 1.75}}, - {label: 'Iced Tea', value: {ingredients: ['water', 'tea leaves', 'ice', 'lemon'], price: 2.50}}, - {label: 'Coffee', value: {ingredients: ['coffee beans', 'water'], warnings: ['addictive', 'hot'], price: 3.25}}, - {label: 'Soda', value: {ingredients: 'unknown', warnings: ['sweet', 'acidic'], price: 1.50}}, - {label: 'Red Wine', value: {ingredients: ['grapes', 'water', 'yeast', 'time'], warnings: ['alcoholic', 'staining'], needId: true, price: 6.75}} - ] + options: recipes } }), example({ @@ -92,14 +74,7 @@ export const SelectTestPanel = hoistCmp({ selectProps: { leftIcon: Icon.search(), hideDropdownIndicator: true, - // options: ['test', 'fail'] - options: [ - {label: 'Hot Tea', value: {ingredients: ['water', 'tea leaves'], warnings: ['hot'], price: 1.75}}, - {label: 'Iced Tea', value: {ingredients: ['water', 'tea leaves', 'ice', 'lemon'], price: 2.50}}, - {label: 'Coffee', value: {ingredients: ['coffee beans', 'water'], warnings: ['addictive', 'hot'], price: 3.25}}, - {label: 'Soda', value: {ingredients: 'unknown', warnings: ['sweet', 'acidic'], price: 1.50}}, - {label: 'Red Wine', value: {ingredients: ['grapes', 'water', 'yeast', 'time'], warnings: ['alcoholic', 'staining'], needId: true, price: 6.75}} - ] + options: recipes } }), example({ @@ -171,3 +146,25 @@ function queryCustomersAsync(query) { params: {query} }); } + +const recipes = [ + {label: 'Hot Tea', value: {ingredients: ['water', 'tea leaves'], warnings: ['hot'], price: 1.75}}, + {label: 'Iced Tea', value: {ingredients: ['water', 'tea leaves', 'ice', 'lemon'], price: 2.50}}, + {label: 'Coffee', value: {ingredients: ['coffee beans', 'water'], warnings: ['addictive', 'hot'], price: 3.25}}, + {label: 'Soda', value: {ingredients: 'unknown', warnings: ['sweet', 'acidic'], price: 1.50}}, + {label: 'Red Wine', value: {ingredients: ['grapes', 'water', 'yeast', 'time'], warnings: ['alcoholic', 'staining'], needId: true, price: 6.75}} +]; + +const desserts = [ + {label: 'cookies', options: [ + 'oatmeal', + 'chocolate chip', + 'peanut butter' + ]}, + {label: 'cakes', options: [ + 'red velvet', 'tres leches', 'German\'s chocolate', 'cheesecake' + ]}, + {label: 'ice cream', options: [ + 'vanilla', 'chocolate', 'strawberry' + ]} +]; From 8323cfd36a8401be06b06f9eff139de5b6fb211f Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 17 Sep 2020 18:31:47 -0400 Subject: [PATCH 03/20] Functioning search input based on routes, but needs some refinement. --- client-app/src/desktop/App.js | 12 ++++++++++++ client-app/src/desktop/AppModel.js | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/client-app/src/desktop/App.js b/client-app/src/desktop/App.js index 045c45fc1..f41961f68 100755 --- a/client-app/src/desktop/App.js +++ b/client-app/src/desktop/App.js @@ -6,6 +6,8 @@ import {tabSwitcher} from '@xh/hoist/desktop/cmp/tab'; import {panel} from '@xh/hoist/desktop/cmp/panel'; import {appBar, appBarSeparator} from '@xh/hoist/desktop/cmp/appbar'; import {AppModel} from './AppModel'; +import {select} from '@xh/hoist/desktop/cmp/input'; +import {Icon} from '@xh/hoist/icon'; import xhLogo from '../core/img/xh-toolbox-logo.png'; import '../core/Toolbox.scss'; import './App.scss'; @@ -23,6 +25,16 @@ export const App = hoistCmp({ tabSwitcher() ], rightItems: [ + select({ + width: 300, + leftIcon: Icon.search(), + bind: 'globalSearchSelection', + options: model.globalSearchOptions, + placeholder: 'Search for a component...', + hideDropdownIndicator: true, + enableClear: true, + onChange: (val) => model.forwardToTopic(val) + }), webSocketIndicator({iconOnly: true, marginRight: 4}), appBarSeparator() ], diff --git a/client-app/src/desktop/AppModel.js b/client-app/src/desktop/AppModel.js index df1e3ecec..445216fae 100755 --- a/client-app/src/desktop/AppModel.js +++ b/client-app/src/desktop/AppModel.js @@ -17,6 +17,7 @@ import {gridsTab} from './tabs/grids/GridsTab'; import {homeTab} from './tabs/home/HomeTab'; import {otherTab} from './tabs/other/OtherTab'; import {panelsTab} from './tabs/panels/PanelsTab'; +import {bindable} from '@xh/hoist/mobx'; @HoistAppModel export class AppModel { @@ -152,4 +153,21 @@ export class AppModel { } ]; } + + @bindable + globalSearchSelection; + + get globalSearchOptions() { + const toLabel = str => str.replace('default.', '') + .replace('.', ' > '); + + return XH.routerModel.getRouteNames(XH.routerModel.router.rootNode) + .filter(it => it.split('.').length > 2) + .map(it => ({value: it, label: toLabel(it)})); + } + + forwardToTopic(val) { + if (val) XH.navigate(val); + } + } From c8a81902ab9872d0b6834e67a2d7777a8b1b3c71 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Mon, 21 Sep 2020 16:36:21 -0400 Subject: [PATCH 04/20] Improve global search so that it uses grouped options. --- client-app/src/desktop/AppModel.js | 34 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/client-app/src/desktop/AppModel.js b/client-app/src/desktop/AppModel.js index 445216fae..2899ffcf1 100755 --- a/client-app/src/desktop/AppModel.js +++ b/client-app/src/desktop/AppModel.js @@ -158,16 +158,38 @@ export class AppModel { globalSearchSelection; get globalSearchOptions() { - const toLabel = str => str.replace('default.', '') - .replace('.', ' > '); - - return XH.routerModel.getRouteNames(XH.routerModel.router.rootNode) - .filter(it => it.split('.').length > 2) - .map(it => ({value: it, label: toLabel(it)})); + const {rootNode} = XH.routerModel.router, + groupedRoutes = this.getRoutesAsGroupedOptions(rootNode), + unNested = groupedRoutes[0].options[0].options; + + return unNested; } forwardToTopic(val) { if (val) XH.navigate(val); } + getRoutesAsGroupedOptions(node, value = '') { + const option = { + label: node.name, + value: value + node.name + }, + ret = []; + + if (node.children?.length) { + option.options = []; + } + + node.children.forEach(child => { + const value = option.value ? option.value + '.' : ''; + this.getRoutesAsGroupedOptions(child, value) + .forEach(it => { + option.options.push(it); + }); + }); + + ret.push(option); + return ret; + } + } From 27b3507120c28a9f1e3285d1df4d2488cce883e3 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 24 Sep 2020 10:47:30 -0400 Subject: [PATCH 05/20] Added globalsearch hotkey and made it maintain focus for efficient browsing. --- client-app/src/desktop/App.js | 35 +++++++++++++++++++++--------- client-app/src/desktop/AppModel.js | 14 ++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/client-app/src/desktop/App.js b/client-app/src/desktop/App.js index f41961f68..dcd45fbed 100755 --- a/client-app/src/desktop/App.js +++ b/client-app/src/desktop/App.js @@ -8,10 +8,14 @@ import {appBar, appBarSeparator} from '@xh/hoist/desktop/cmp/appbar'; import {AppModel} from './AppModel'; import {select} from '@xh/hoist/desktop/cmp/input'; import {Icon} from '@xh/hoist/icon'; +import {useHotkeys} from '@xh/hoist/desktop/hooks'; + import xhLogo from '../core/img/xh-toolbox-logo.png'; + import '../core/Toolbox.scss'; import './App.scss'; + export const App = hoistCmp({ displayName: 'App', model: uses(AppModel), @@ -25,16 +29,27 @@ export const App = hoistCmp({ tabSwitcher() ], rightItems: [ - select({ - width: 300, - leftIcon: Icon.search(), - bind: 'globalSearchSelection', - options: model.globalSearchOptions, - placeholder: 'Search for a component...', - hideDropdownIndicator: true, - enableClear: true, - onChange: (val) => model.forwardToTopic(val) - }), + useHotkeys( + select({ + ref: model.globalSearchSelectRef, + width: 300, + leftIcon: Icon.search(), + bind: 'globalSearchSelection', + options: model.globalSearchOptions, + placeholder: 'Search for a component...(s)', + hideDropdownIndicator: true, + enableClear: true, + onChange: (val) => model.forwardToTopic(val) + }), + [ + { + global: true, + combo: 's', + label: 'Go to search', + onKeyUp: () => model.focus() + } + ] + ), webSocketIndicator({iconOnly: true, marginRight: 4}), appBarSeparator() ], diff --git a/client-app/src/desktop/AppModel.js b/client-app/src/desktop/AppModel.js index 2899ffcf1..bf926f123 100755 --- a/client-app/src/desktop/AppModel.js +++ b/client-app/src/desktop/AppModel.js @@ -18,6 +18,8 @@ import {homeTab} from './tabs/home/HomeTab'; import {otherTab} from './tabs/other/OtherTab'; import {panelsTab} from './tabs/panels/PanelsTab'; import {bindable} from '@xh/hoist/mobx'; +import {createRef} from 'react'; +import {wait} from '@xh/hoist/promise'; @HoistAppModel export class AppModel { @@ -157,6 +159,8 @@ export class AppModel { @bindable globalSearchSelection; + globalSearchSelectRef = createRef(); + get globalSearchOptions() { const {rootNode} = XH.routerModel.router, groupedRoutes = this.getRoutesAsGroupedOptions(rootNode), @@ -167,6 +171,8 @@ export class AppModel { forwardToTopic(val) { if (val) XH.navigate(val); + this.blur(); + wait(100).then(() => this.focus()); } getRoutesAsGroupedOptions(node, value = '') { @@ -192,4 +198,12 @@ export class AppModel { return ret; } + focus() { + this.globalSearchSelectRef.current?.reactSelectRef?.current?.focus(); + } + + blur() { + this.globalSearchSelectRef.current?.reactSelectRef?.current?.blur(); + } + } From bbd0bd458e79604899329a2ea26199e4174b3554 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 24 Sep 2020 22:50:10 -0400 Subject: [PATCH 06/20] Refactored global search into own component. --- client-app/src/desktop/App.js | 26 +------ client-app/src/desktop/AppModel.js | 55 +-------------- client-app/src/desktop/search/Search.js | 93 +++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 78 deletions(-) create mode 100644 client-app/src/desktop/search/Search.js diff --git a/client-app/src/desktop/App.js b/client-app/src/desktop/App.js index dcd45fbed..8b92400cf 100755 --- a/client-app/src/desktop/App.js +++ b/client-app/src/desktop/App.js @@ -6,10 +6,8 @@ import {tabSwitcher} from '@xh/hoist/desktop/cmp/tab'; import {panel} from '@xh/hoist/desktop/cmp/panel'; import {appBar, appBarSeparator} from '@xh/hoist/desktop/cmp/appbar'; import {AppModel} from './AppModel'; -import {select} from '@xh/hoist/desktop/cmp/input'; -import {Icon} from '@xh/hoist/icon'; -import {useHotkeys} from '@xh/hoist/desktop/hooks'; +import {search} from './search/Search'; import xhLogo from '../core/img/xh-toolbox-logo.png'; import '../core/Toolbox.scss'; @@ -29,27 +27,7 @@ export const App = hoistCmp({ tabSwitcher() ], rightItems: [ - useHotkeys( - select({ - ref: model.globalSearchSelectRef, - width: 300, - leftIcon: Icon.search(), - bind: 'globalSearchSelection', - options: model.globalSearchOptions, - placeholder: 'Search for a component...(s)', - hideDropdownIndicator: true, - enableClear: true, - onChange: (val) => model.forwardToTopic(val) - }), - [ - { - global: true, - combo: 's', - label: 'Go to search', - onKeyUp: () => model.focus() - } - ] - ), + search({width: 300}), webSocketIndicator({iconOnly: true, marginRight: 4}), appBarSeparator() ], diff --git a/client-app/src/desktop/AppModel.js b/client-app/src/desktop/AppModel.js index bf926f123..f3bb2781a 100755 --- a/client-app/src/desktop/AppModel.js +++ b/client-app/src/desktop/AppModel.js @@ -17,9 +17,7 @@ import {gridsTab} from './tabs/grids/GridsTab'; import {homeTab} from './tabs/home/HomeTab'; import {otherTab} from './tabs/other/OtherTab'; import {panelsTab} from './tabs/panels/PanelsTab'; -import {bindable} from '@xh/hoist/mobx'; -import {createRef} from 'react'; -import {wait} from '@xh/hoist/promise'; + @HoistAppModel export class AppModel { @@ -155,55 +153,4 @@ export class AppModel { } ]; } - - @bindable - globalSearchSelection; - - globalSearchSelectRef = createRef(); - - get globalSearchOptions() { - const {rootNode} = XH.routerModel.router, - groupedRoutes = this.getRoutesAsGroupedOptions(rootNode), - unNested = groupedRoutes[0].options[0].options; - - return unNested; - } - - forwardToTopic(val) { - if (val) XH.navigate(val); - this.blur(); - wait(100).then(() => this.focus()); - } - - getRoutesAsGroupedOptions(node, value = '') { - const option = { - label: node.name, - value: value + node.name - }, - ret = []; - - if (node.children?.length) { - option.options = []; - } - - node.children.forEach(child => { - const value = option.value ? option.value + '.' : ''; - this.getRoutesAsGroupedOptions(child, value) - .forEach(it => { - option.options.push(it); - }); - }); - - ret.push(option); - return ret; - } - - focus() { - this.globalSearchSelectRef.current?.reactSelectRef?.current?.focus(); - } - - blur() { - this.globalSearchSelectRef.current?.reactSelectRef?.current?.blur(); - } - } diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js new file mode 100644 index 000000000..cb94caddf --- /dev/null +++ b/client-app/src/desktop/search/Search.js @@ -0,0 +1,93 @@ +import {createRef} from 'react'; + +import {XH, HoistModel, hoistCmp, creates} from '@xh/hoist/core'; +import {select} from '@xh/hoist/desktop/cmp/input'; +import {bindable} from '@xh/hoist/mobx'; +import {getLayoutProps} from '@xh/hoist/utils/react'; +import {useHotkeys} from '@xh/hoist/desktop/hooks'; +import {Icon} from '@xh/hoist/icon'; +import {wait} from '@xh/hoist/promise'; + +export const search = hoistCmp.factory({ + model: creates(() => new Model()), + render({model, ...props}) { + const {globalSearchOptions, selectRef} = model; + + return useHotkeys( + select({ + ref: selectRef, + ...getLayoutProps(props), + leftIcon: Icon.search(), + bind: 'globalSearchSelection', + options: globalSearchOptions, + placeholder: 'Search for a component...(s)', + hideDropdownIndicator: true, + enableClear: true, + onChange: (val) => model.forwardToTopic(val) + }), + [ + { + global: true, + combo: 's', + label: 'Go to search', + onKeyUp: () => model.focus() + } + ] + ); + + } +}); + +@HoistModel +class Model { + @bindable + globalSearchSelection; + + selectRef = createRef(); + + get globalSearchOptions() { + const {rootNode} = XH.routerModel.router, + groupedRoutes = this.getRoutesAsGroupedOptions(rootNode), + unNested = groupedRoutes[0].options[0].options; + + return unNested; + } + + forwardToTopic(val) { + if (val) XH.navigate(val); + this.blur(); + wait(100).then(() => this.focus()); + } + + getRoutesAsGroupedOptions(node, value = '') { + const option = { + label: node.name, + value: value + node.name + }, + ret = []; + + if (node.children?.length) { + option.options = []; + } + + node.children.forEach(child => { + const value = option.value ? option.value + '.' : ''; + this.getRoutesAsGroupedOptions(child, value) + .forEach(it => { + option.options.push(it); + }); + }); + + ret.push(option); + return ret; + } + + focus() { + this.selectRef.current?.reactSelectRef?.current?.focus(); + } + + blur() { + this.selectRef.current?.reactSelectRef?.current?.blur(); + } + +} From 1360b1834325c12739405a262a60edf37cef9f3c Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 24 Sep 2020 22:52:32 -0400 Subject: [PATCH 07/20] Whitespace cleanup. --- client-app/src/desktop/App.js | 3 --- client-app/src/desktop/AppModel.js | 1 - 2 files changed, 4 deletions(-) diff --git a/client-app/src/desktop/App.js b/client-app/src/desktop/App.js index 8b92400cf..57a645631 100755 --- a/client-app/src/desktop/App.js +++ b/client-app/src/desktop/App.js @@ -6,14 +6,11 @@ import {tabSwitcher} from '@xh/hoist/desktop/cmp/tab'; import {panel} from '@xh/hoist/desktop/cmp/panel'; import {appBar, appBarSeparator} from '@xh/hoist/desktop/cmp/appbar'; import {AppModel} from './AppModel'; - import {search} from './search/Search'; import xhLogo from '../core/img/xh-toolbox-logo.png'; - import '../core/Toolbox.scss'; import './App.scss'; - export const App = hoistCmp({ displayName: 'App', model: uses(AppModel), diff --git a/client-app/src/desktop/AppModel.js b/client-app/src/desktop/AppModel.js index f3bb2781a..df1e3ecec 100755 --- a/client-app/src/desktop/AppModel.js +++ b/client-app/src/desktop/AppModel.js @@ -18,7 +18,6 @@ import {homeTab} from './tabs/home/HomeTab'; import {otherTab} from './tabs/other/OtherTab'; import {panelsTab} from './tabs/panels/PanelsTab'; - @HoistAppModel export class AppModel { From d8c1197d2c85f9aba705b972acb596fc6f616687 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 24 Sep 2020 22:58:07 -0400 Subject: [PATCH 08/20] Small refactor. --- client-app/src/desktop/search/Search.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index cb94caddf..e24cb137e 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -40,6 +40,7 @@ export const search = hoistCmp.factory({ @HoistModel class Model { + @bindable globalSearchSelection; @@ -82,12 +83,16 @@ class Model { return ret; } + get selectElem() { + return this.selectRef.current?.reactSelectRef?.current; + } + focus() { - this.selectRef.current?.reactSelectRef?.current?.focus(); + this.selectElem?.focus(); } blur() { - this.selectRef.current?.reactSelectRef?.current?.blur(); + this.selectElem?.blur(); } } From f26b0872db0d3edbe04e78399902e7525e46bf8f Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Fri, 25 Sep 2020 09:31:51 -0400 Subject: [PATCH 09/20] Added tracking to search selection. --- client-app/src/desktop/search/Search.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index e24cb137e..1e2dba6df 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -55,7 +55,14 @@ class Model { } forwardToTopic(val) { - if (val) XH.navigate(val); + if (val) { + XH.navigate(val); + XH.track({ + category: 'Global Search', + message: 'Selected result', + data: {topic: val} + }); + } this.blur(); wait(100).then(() => this.focus()); } From 8a3072ab143ff2b60c95776e9e9dcd06727f3f6f Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 22 Oct 2020 18:06:41 -0400 Subject: [PATCH 10/20] Move search options to softConfig --- client-app/src/desktop/search/Search.js | 47 +++++++++---------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 1e2dba6df..406766639 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -23,6 +23,7 @@ export const search = hoistCmp.factory({ placeholder: 'Search for a component...(s)', hideDropdownIndicator: true, enableClear: true, + valueField: 'route', onChange: (val) => model.forwardToTopic(val) }), [ @@ -47,51 +48,37 @@ class Model { selectRef = createRef(); get globalSearchOptions() { - const {rootNode} = XH.routerModel.router, - groupedRoutes = this.getRoutesAsGroupedOptions(rootNode), - unNested = groupedRoutes[0].options[0].options; + return XH.getConf('searchOptions'); + } - return unNested; + get selectElem() { + return this.selectRef.current?.reactSelectRef?.current; } forwardToTopic(val) { if (val) { - XH.navigate(val); + if (val.startsWith('launch.')) { + this.openExternal(val); + } else { + XH.navigate(val.split('|')[0]); + } + XH.track({ category: 'Global Search', message: 'Selected result', data: {topic: val} }); } + + // let's displayed value reflect selection + // and keeps focus on select box and this.blur(); wait(100).then(() => this.focus()); } - getRoutesAsGroupedOptions(node, value = '') { - const option = { - label: node.name, - value: value + node.name - }, - ret = []; - - if (node.children?.length) { - option.options = []; - } - - node.children.forEach(child => { - const value = option.value ? option.value + '.' : ''; - this.getRoutesAsGroupedOptions(child, value) - .forEach(it => { - option.options.push(it); - }); - }); - - ret.push(option); - return ret; - } - - get selectElem() { - return this.selectRef.current?.reactSelectRef?.current; + openExternal(val) { + const path = val.replace('launch.examples.', ''); + window.open(`/${path}`); } focus() { From 642b2a77ac8aca48e552bd652f9cc213ac207412 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Thu, 5 Nov 2020 11:40:50 -0500 Subject: [PATCH 11/20] Better comment. --- client-app/src/desktop/search/Search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 406766639..bed0617fc 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -70,8 +70,7 @@ class Model { }); } - // let's displayed value reflect selection - // and keeps focus on select box and + // keeps focus on select box to facilate typing a new query this.blur(); wait(100).then(() => this.focus()); } From 96c1942ec7c9d5389a7cd8af1b47f41b5fc08c55 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Tue, 17 Nov 2020 11:37:20 -0500 Subject: [PATCH 12/20] Set new filterFn prop so that it reverts to default react-select filter behaviour. --- client-app/src/desktop/search/Search.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index bed0617fc..69b76ff13 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -1,5 +1,5 @@ import {createRef} from 'react'; - +import {createFilter} from 'react-select'; import {XH, HoistModel, hoistCmp, creates} from '@xh/hoist/core'; import {select} from '@xh/hoist/desktop/cmp/input'; import {bindable} from '@xh/hoist/mobx'; @@ -24,6 +24,7 @@ export const search = hoistCmp.factory({ hideDropdownIndicator: true, enableClear: true, valueField: 'route', + filterFn: createFilter, onChange: (val) => model.forwardToTopic(val) }), [ From e9438d3caa36027ccebb2a3347be14b5a2ae4bd3 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Fri, 27 Nov 2020 18:36:23 -0500 Subject: [PATCH 13/20] Fix use of createFilter func. --- client-app/src/desktop/search/Search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 69b76ff13..8964600a9 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -24,7 +24,7 @@ export const search = hoistCmp.factory({ hideDropdownIndicator: true, enableClear: true, valueField: 'route', - filterFn: createFilter, + filterFn: createFilter(), onChange: (val) => model.forwardToTopic(val) }), [ From 0a8451a2de3de0e5de4a797e8d673694aad52721 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Mon, 30 Nov 2020 12:01:41 -0500 Subject: [PATCH 14/20] Fix aquisition of select's input element. --- client-app/src/desktop/search/Search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 8964600a9..524cb82fd 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -53,7 +53,7 @@ class Model { } get selectElem() { - return this.selectRef.current?.reactSelectRef?.current; + return this.selectRef.current?.querySelector('input'); } forwardToTopic(val) { From 7a7e38a920c5346e69bf02517ca95b5c2917bb5a Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Mon, 30 Nov 2020 12:02:34 -0500 Subject: [PATCH 15/20] Better method name. --- client-app/src/desktop/search/Search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 524cb82fd..125e24ff1 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -52,7 +52,7 @@ class Model { return XH.getConf('searchOptions'); } - get selectElem() { + get inputElem() { return this.selectRef.current?.querySelector('input'); } @@ -82,11 +82,11 @@ class Model { } focus() { - this.selectElem?.focus(); + this.inputElem?.focus(); } blur() { - this.selectElem?.blur(); + this.inputElem?.blur(); } } From 5daed9c18c74ae380c1d86fbefc2f555771b8238 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Tue, 1 Dec 2020 14:58:35 -0500 Subject: [PATCH 16/20] Revert to using reactselect ref. --- client-app/src/desktop/search/Search.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 125e24ff1..3faf72683 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -52,8 +52,8 @@ class Model { return XH.getConf('searchOptions'); } - get inputElem() { - return this.selectRef.current?.querySelector('input'); + get reacSelectCmp() { + return this.selectRef.current?.reactSelectRef?.current; } forwardToTopic(val) { @@ -82,11 +82,11 @@ class Model { } focus() { - this.inputElem?.focus(); + this.reacSelectCmp?.focus(); } blur() { - this.inputElem?.blur(); + this.reacSelectCmp?.blur(); } } From 96e92ff66b6d7e2e511d409b7601191352c7f782 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Tue, 15 Dec 2020 17:42:49 -0500 Subject: [PATCH 17/20] Use new focus & blur methods on Select Model. --- client-app/src/desktop/search/Search.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index 3faf72683..b5d6b8a1c 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -52,10 +52,6 @@ class Model { return XH.getConf('searchOptions'); } - get reacSelectCmp() { - return this.selectRef.current?.reactSelectRef?.current; - } - forwardToTopic(val) { if (val) { if (val.startsWith('launch.')) { @@ -82,11 +78,11 @@ class Model { } focus() { - this.reacSelectCmp?.focus(); + this.selectRef?.current.focus(); } blur() { - this.reacSelectCmp?.blur(); + this.selectRef?.current.blur(); } } From 95503cdb2dd4e5b68a7fc08e911e31399887e5da Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Fri, 7 May 2021 14:09:58 -0400 Subject: [PATCH 18/20] Update Model class --- client-app/src/desktop/search/Search.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js index b5d6b8a1c..42390d545 100644 --- a/client-app/src/desktop/search/Search.js +++ b/client-app/src/desktop/search/Search.js @@ -2,7 +2,7 @@ import {createRef} from 'react'; import {createFilter} from 'react-select'; import {XH, HoistModel, hoistCmp, creates} from '@xh/hoist/core'; import {select} from '@xh/hoist/desktop/cmp/input'; -import {bindable} from '@xh/hoist/mobx'; +import {bindable, makeObservable} from '@xh/hoist/mobx'; import {getLayoutProps} from '@xh/hoist/utils/react'; import {useHotkeys} from '@xh/hoist/desktop/hooks'; import {Icon} from '@xh/hoist/icon'; @@ -40,8 +40,8 @@ export const search = hoistCmp.factory({ } }); -@HoistModel -class Model { + +class Model extends HoistModel { @bindable globalSearchSelection; @@ -52,6 +52,11 @@ class Model { return XH.getConf('searchOptions'); } + constructor() { + super(); + makeObservable(this); + } + forwardToTopic(val) { if (val) { if (val.startsWith('launch.')) { @@ -78,11 +83,11 @@ class Model { } focus() { - this.selectRef?.current.focus(); + this.selectRef?.current.focus(); } blur() { - this.selectRef?.current.blur(); + this.selectRef?.current.blur(); } } From 0c446c78b337187381d9acf74eabe10a7b0f8e88 Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Mon, 5 Jun 2023 11:41:36 -0400 Subject: [PATCH 19/20] Update Search to ts, add config content to bottom in comment. --- client-app/src/desktop/search/Search.js | 93 ----- client-app/src/desktop/search/Search.ts | 506 ++++++++++++++++++++++++ 2 files changed, 506 insertions(+), 93 deletions(-) delete mode 100644 client-app/src/desktop/search/Search.js create mode 100644 client-app/src/desktop/search/Search.ts diff --git a/client-app/src/desktop/search/Search.js b/client-app/src/desktop/search/Search.js deleted file mode 100644 index 42390d545..000000000 --- a/client-app/src/desktop/search/Search.js +++ /dev/null @@ -1,93 +0,0 @@ -import {createRef} from 'react'; -import {createFilter} from 'react-select'; -import {XH, HoistModel, hoistCmp, creates} from '@xh/hoist/core'; -import {select} from '@xh/hoist/desktop/cmp/input'; -import {bindable, makeObservable} from '@xh/hoist/mobx'; -import {getLayoutProps} from '@xh/hoist/utils/react'; -import {useHotkeys} from '@xh/hoist/desktop/hooks'; -import {Icon} from '@xh/hoist/icon'; -import {wait} from '@xh/hoist/promise'; - -export const search = hoistCmp.factory({ - model: creates(() => new Model()), - render({model, ...props}) { - const {globalSearchOptions, selectRef} = model; - - return useHotkeys( - select({ - ref: selectRef, - ...getLayoutProps(props), - leftIcon: Icon.search(), - bind: 'globalSearchSelection', - options: globalSearchOptions, - placeholder: 'Search for a component...(s)', - hideDropdownIndicator: true, - enableClear: true, - valueField: 'route', - filterFn: createFilter(), - onChange: (val) => model.forwardToTopic(val) - }), - [ - { - global: true, - combo: 's', - label: 'Go to search', - onKeyUp: () => model.focus() - } - ] - ); - - } -}); - - -class Model extends HoistModel { - - @bindable - globalSearchSelection; - - selectRef = createRef(); - - get globalSearchOptions() { - return XH.getConf('searchOptions'); - } - - constructor() { - super(); - makeObservable(this); - } - - forwardToTopic(val) { - if (val) { - if (val.startsWith('launch.')) { - this.openExternal(val); - } else { - XH.navigate(val.split('|')[0]); - } - - XH.track({ - category: 'Global Search', - message: 'Selected result', - data: {topic: val} - }); - } - - // keeps focus on select box to facilate typing a new query - this.blur(); - wait(100).then(() => this.focus()); - } - - openExternal(val) { - const path = val.replace('launch.examples.', ''); - window.open(`/${path}`); - } - - focus() { - this.selectRef?.current.focus(); - } - - blur() { - this.selectRef?.current.blur(); - } - -} diff --git a/client-app/src/desktop/search/Search.ts b/client-app/src/desktop/search/Search.ts new file mode 100644 index 000000000..a34b0f87c --- /dev/null +++ b/client-app/src/desktop/search/Search.ts @@ -0,0 +1,506 @@ +import {createRef} from 'react'; +import {createFilter} from 'react-select'; +import {isEmpty} from 'lodash'; +import {XH, HoistModel, hoistCmp, creates, PlainObject} from '@xh/hoist/core'; +import {HoistInputModel} from '@xh/hoist/cmp/input'; +import {select} from '@xh/hoist/desktop/cmp/input'; +import {bindable, makeObservable} from '@xh/hoist/mobx'; +import {getLayoutProps} from '@xh/hoist/utils/react'; +import {useHotkeys} from '@xh/hoist/desktop/hooks'; +import {Icon} from '@xh/hoist/icon'; +import {wait} from '@xh/hoist/promise'; + +export const search = hoistCmp.factory({ + model: creates(() => new Model()), + render({model, ...props}) { + const {globalSearchOptions, selectRef} = model; + + if (isEmpty(globalSearchOptions)) return null; + + return useHotkeys( + select({ + ref: selectRef, + ...getLayoutProps(props), + leftIcon: Icon.search(), + bind: 'globalSearchSelection', + options: globalSearchOptions, + placeholder: 'Search for a component...(s)', + hideDropdownIndicator: true, + enableClear: true, + valueField: 'route', + filterFn: createFilter(null), + onChange: val => model.forwardToTopic(val) + }), + [ + { + global: true, + combo: 's', + label: 'Go to search', + onKeyUp: () => model.focus() + } + ] + ); + } +}); + +class Model extends HoistModel { + @bindable + globalSearchSelection; + + selectRef = createRef(); + + get globalSearchOptions(): PlainObject[] { + return XH.getConf('searchOptions', []); + } + + constructor() { + super(); + makeObservable(this); + } + + forwardToTopic(val) { + if (val) { + if (val.startsWith('launch.')) { + this.openExternal(val); + } else { + XH.navigate(val.split('|')[0]); + } + + XH.track({ + category: 'Global Search', + message: 'Selected result', + data: {topic: val} + }); + } + + // keeps focus on select box to facilate typing a new query + this.blur(); + wait(100).then(() => this.focus()); + } + + openExternal(val) { + const path = val.replace('launch.examples.', ''); + window.open(`/${path}`); + } + + focus() { + this.selectRef?.current.focus(); + } + + blur() { + this.selectRef?.current.blur(); + } +} + +/** + * This is the JSON array that should go into a config called searchOptions + * This can be deleted if this is ever merged in and the searchOptions is added. + * Routes and Labels may need to be updated/removed/added below as toolbox changes. + * + + [ + { + "label": "containers", + "route": "default.layout", + "options": [ + { + "label": "TabContainer", + "route": "default.layout.tabPanel" + }, + { + "label": "Top Tabs", + "route": "default.layout.tabPanel|Top" + }, + { + "label": "Bottom Tabs", + "route": "default.layout.tabPanel|Bottom" + }, + { + "label": "Left Tabs", + "route": "default.layout.tabPanel|Left" + }, + { + "label": "Right Tabs", + "route": "default.layout.tabPanel|Right" + }, + { + "label": "Custom Tab Switcher", + "route": "default.layout.tabPanel|Switcher" + }, + { + "label": "Tab State", + "route": "default.layout.tabPanel|State" + }, + { + "label": "Dynamic Tabs", + "route": "default.layout.tabPanel|Dynamic" + }, + { + "label": "DockContainer", + "route": "default.layout.dock" + }, + { + "label": "DashCanvas", + "route": "default.layout.dashCanvas" + }, + { + "label": "DashContainer", + "route": "default.layout.dashContainer" + }, + { + "label": "HBox", + "route": "default.layout.hbox" + }, + { + "label": "VBox", + "route": "default.layout.vbox" + }, + { + "label": "TileFrame", + "route": "default.layout.tileFrame" + } + ] + }, + { + "label": "Examples", + "route": "default.examples", + "options": [ + { + "label": "Portfolio", + "route": "launch.examples.portfolio" + }, + { + "label": "News", + "route": "launch.examples.news" + }, + { + "label": "FDA Recalls", + "route": "launch.examples.recalls" + }, + { + "label": "File Manager", + "route": "launch.examples.fileManager" + } + ] + }, + { + "label": "panels", + "route": "default.panels", + "options": [ + { + "label": "LoadingIndicator", + "route": "default.panels.loadingIndicator" + }, + { + "label": "Mask", + "route": "default.panels.mask" + }, + { + "label": "Sizing", + "route": "default.panels.sizing" + }, + { + "label": "Toolbars", + "route": "default.panels.toolbars" + } + ] + }, + { + "label": "charts", + "route": "default.charts", + "options": [ + { + "label": "Line", + "route": "default.charts.line" + }, + { + "label": "Chart Aspect Ratio", + "route": "default.charts.line|AspectRatio" + }, + { + "label": "OHLC", + "route": "default.charts.ohlc" + }, + { + "label": "Grid TreeMap", + "route": "default.charts.gridTreeMap" + }, + { + "label": "Simple TreeMap", + "route": "default.charts.simpleTreeMap" + }, + { + "label": "Split TreeMap", + "route": "default.charts.splitTreeMap" + } + ] + }, + { + "label": "grids", + "route": "default.grids", + "options": [ + { + "label": "Standard", + "route": "default.grids.standard" + }, + { + "label": "Tree with CheckBox", + "route": "default.grids.treeWithCheckBox" + }, + { + "label": "Grouped Rows", + "route": "default.grids.groupedRows" + }, + { + "label": "Grouped Cols", + "route": "default.grids.groupedCols" + }, + { + "label": "Dataview", + "route": "default.grids.dataview" + }, + { + "label": "agGrid", + "route": "default.grids.agGrid" + }, + { + "label": "Tree", + "route": "default.grids.tree" + }, + { + "label": "Rest", + "route": "default.grids.rest" + } + ] + }, + { + "label": "forms", + "route": "default.forms", + "options": [ + { + "label": "Toolbar Form", + "route": "default.forms.toolbarForm" + }, + { + "label": "Inputs", + "route": "default.forms.inputs" + }, + { + "label": "TextInput", + "route": "default.forms.inputs|TextInput" + }, + { + "label": "TextArea", + "route": "default.forms.inputs|TextArea" + }, + { + "label": "JSONInput", + "route": "default.forms.inputs|JSONInput" + }, + { + "label": "NumberInput", + "route": "default.forms.inputs|NumberInput" + }, + { + "label": "Slider", + "route": "default.forms.inputs|Slider" + }, + { + "label": "DateInput", + "route": "default.forms.inputs|DateInput" + }, + { + "label": "Select", + "route": "default.forms.inputs|Select" + }, + { + "label": "Checkbox", + "route": "default.forms.inputs|Checkbox" + }, + { + "label": "ButtonGroupInput", + "route": "default.forms.inputs|ButtonGroupInput" + }, + { + "label": "RadioInput", + "route": "default.forms.inputs|RadioInput" + }, + { + "label": "Form", + "route": "default.forms.form" + } + ] + }, + { + "label": "other", + "route": "default.other", + "options": [ + { + "label": "LeftRightChooser", + "route": "default.other.leftRightChooser" + }, + { + "label": "File Chooser", + "route": "default.other.fileChooser" + }, + { + "label": "Timestamp", + "route": "default.other.timestamp" + }, + { + "label": "PinPad", + "route": "default.other.pinPad" + }, + { + "label": "Clock", + "route": "default.other.clock" + }, + { + "label": "Icons", + "route": "default.other.icons" + }, + { + "label": "Element Factories vs. JSX", + "route": "default.other.jsx" + } + ] + }, + { + "label": "App Notifications", + "route": "default.other.appNotifications", + "options": [ + { + "label": "App Update", + "route": "default.other.appNotifications|Update" + }, + { + "label": "App Sleep Mode", + "route": "default.other.appNotifications|Sleep" + } + ] + }, + { + "label": "Number Formats", + "route": "default.other.numberFormats", + "options": [ + { + "label": "fmtNumber", + "route": "default.other.numberFormats|fmtNumber" + }, + { + "label": "fmtPrice", + "route": "default.other.numberFormats|fmtPrice" + }, + { + "label": "fmtQuantity", + "route": "default.other.numberFormats|fmtQuantity" + }, + { + "label": "fmtPercent", + "route": "default.other.numberFormats|fmtPercent" + }, + { + "label": "fmtThousands", + "route": "default.other.numberFormats|fmtThousands" + }, + { + "label": "fmtMillions", + "route": "default.other.numberFormats|fmtMillions" + }, + { + "label": "fmtBillions", + "route": "default.other.numberFormats|fmtBillions" + }, + { + "label": "Precision", + "route": "default.other.numberFormats|Precision" + }, + { + "label": "zeroPad", + "route": "default.other.numberFormats|zeroPad" + }, + { + "label": "ledger", + "route": "default.other.numberFormats|ledger" + }, + { + "label": "forceLedgerAlign", + "route": "default.other.numberFormats|forceLedgerAlign" + }, + { + "label": "colorSpec", + "route": "default.other.numberFormats|colorSpec" + }, + { + "label": "withPlusSign", + "route": "default.other.numberFormats|withPlusSign" + }, + { + "label": "withSignGlyph", + "route": "default.other.numberFormats|withSignGlyph" + }, + { + "label": "label", + "route": "default.other.numberFormats|label" + }, + { + "label": "nullDisplay", + "route": "default.other.numberFormats|nullDisplay" + } + ] + }, + { + "label": "Date Formats", + "route": "default.other.dateFormats", + "options": [ + { + "label": "fmtDate", + "route": "default.other.dateFormats|fmtDate" + }, + { + "label": "fmtCompactDate", + "route": "default.other.dateFormats|fmtCompactDate" + }, + { + "label": "fmtDateTime", + "route": "default.other.dateFormats|fmtDateTime" + }, + { + "label": "fmtTime", + "route": "default.other.dateFormats|fmtTime" + }, + { + "label": "tooltip", + "route": "default.other.dateFormats|tooltip" + } + ] + }, + { + "label": "Popups", + "route": "default.other.popups", + "options": [ + { + "label": "Alert", + "route": "default.other.popups|Alert" + }, + { + "label": "Confirm", + "route": "default.other.popups|Confirm" + }, + { + "label": "Prompt", + "route": "default.other.popups|Prompt" + }, + { + "label": "Message", + "route": "default.other.popups|Message" + }, + { + "label": "Toast", + "route": "default.other.popups|Toast" + } + ] + } + ] + + */ From 273b5c9488c8d594311c445b227f3753fbba1cfe Mon Sep 17 00:00:00 2001 From: Colin Rudd Date: Wed, 22 May 2024 12:22:57 -0400 Subject: [PATCH 20/20] fix merge --- client-app/src/desktop/search/Search.ts | 413 ------------------ .../init/io/xh/toolbox/BootStrap.groovy | 409 +++++++++++++++++ 2 files changed, 409 insertions(+), 413 deletions(-) diff --git a/client-app/src/desktop/search/Search.ts b/client-app/src/desktop/search/Search.ts index a34b0f87c..9a3d6c41a 100644 --- a/client-app/src/desktop/search/Search.ts +++ b/client-app/src/desktop/search/Search.ts @@ -91,416 +91,3 @@ class Model extends HoistModel { this.selectRef?.current.blur(); } } - -/** - * This is the JSON array that should go into a config called searchOptions - * This can be deleted if this is ever merged in and the searchOptions is added. - * Routes and Labels may need to be updated/removed/added below as toolbox changes. - * - - [ - { - "label": "containers", - "route": "default.layout", - "options": [ - { - "label": "TabContainer", - "route": "default.layout.tabPanel" - }, - { - "label": "Top Tabs", - "route": "default.layout.tabPanel|Top" - }, - { - "label": "Bottom Tabs", - "route": "default.layout.tabPanel|Bottom" - }, - { - "label": "Left Tabs", - "route": "default.layout.tabPanel|Left" - }, - { - "label": "Right Tabs", - "route": "default.layout.tabPanel|Right" - }, - { - "label": "Custom Tab Switcher", - "route": "default.layout.tabPanel|Switcher" - }, - { - "label": "Tab State", - "route": "default.layout.tabPanel|State" - }, - { - "label": "Dynamic Tabs", - "route": "default.layout.tabPanel|Dynamic" - }, - { - "label": "DockContainer", - "route": "default.layout.dock" - }, - { - "label": "DashCanvas", - "route": "default.layout.dashCanvas" - }, - { - "label": "DashContainer", - "route": "default.layout.dashContainer" - }, - { - "label": "HBox", - "route": "default.layout.hbox" - }, - { - "label": "VBox", - "route": "default.layout.vbox" - }, - { - "label": "TileFrame", - "route": "default.layout.tileFrame" - } - ] - }, - { - "label": "Examples", - "route": "default.examples", - "options": [ - { - "label": "Portfolio", - "route": "launch.examples.portfolio" - }, - { - "label": "News", - "route": "launch.examples.news" - }, - { - "label": "FDA Recalls", - "route": "launch.examples.recalls" - }, - { - "label": "File Manager", - "route": "launch.examples.fileManager" - } - ] - }, - { - "label": "panels", - "route": "default.panels", - "options": [ - { - "label": "LoadingIndicator", - "route": "default.panels.loadingIndicator" - }, - { - "label": "Mask", - "route": "default.panels.mask" - }, - { - "label": "Sizing", - "route": "default.panels.sizing" - }, - { - "label": "Toolbars", - "route": "default.panels.toolbars" - } - ] - }, - { - "label": "charts", - "route": "default.charts", - "options": [ - { - "label": "Line", - "route": "default.charts.line" - }, - { - "label": "Chart Aspect Ratio", - "route": "default.charts.line|AspectRatio" - }, - { - "label": "OHLC", - "route": "default.charts.ohlc" - }, - { - "label": "Grid TreeMap", - "route": "default.charts.gridTreeMap" - }, - { - "label": "Simple TreeMap", - "route": "default.charts.simpleTreeMap" - }, - { - "label": "Split TreeMap", - "route": "default.charts.splitTreeMap" - } - ] - }, - { - "label": "grids", - "route": "default.grids", - "options": [ - { - "label": "Standard", - "route": "default.grids.standard" - }, - { - "label": "Tree with CheckBox", - "route": "default.grids.treeWithCheckBox" - }, - { - "label": "Grouped Rows", - "route": "default.grids.groupedRows" - }, - { - "label": "Grouped Cols", - "route": "default.grids.groupedCols" - }, - { - "label": "Dataview", - "route": "default.grids.dataview" - }, - { - "label": "agGrid", - "route": "default.grids.agGrid" - }, - { - "label": "Tree", - "route": "default.grids.tree" - }, - { - "label": "Rest", - "route": "default.grids.rest" - } - ] - }, - { - "label": "forms", - "route": "default.forms", - "options": [ - { - "label": "Toolbar Form", - "route": "default.forms.toolbarForm" - }, - { - "label": "Inputs", - "route": "default.forms.inputs" - }, - { - "label": "TextInput", - "route": "default.forms.inputs|TextInput" - }, - { - "label": "TextArea", - "route": "default.forms.inputs|TextArea" - }, - { - "label": "JSONInput", - "route": "default.forms.inputs|JSONInput" - }, - { - "label": "NumberInput", - "route": "default.forms.inputs|NumberInput" - }, - { - "label": "Slider", - "route": "default.forms.inputs|Slider" - }, - { - "label": "DateInput", - "route": "default.forms.inputs|DateInput" - }, - { - "label": "Select", - "route": "default.forms.inputs|Select" - }, - { - "label": "Checkbox", - "route": "default.forms.inputs|Checkbox" - }, - { - "label": "ButtonGroupInput", - "route": "default.forms.inputs|ButtonGroupInput" - }, - { - "label": "RadioInput", - "route": "default.forms.inputs|RadioInput" - }, - { - "label": "Form", - "route": "default.forms.form" - } - ] - }, - { - "label": "other", - "route": "default.other", - "options": [ - { - "label": "LeftRightChooser", - "route": "default.other.leftRightChooser" - }, - { - "label": "File Chooser", - "route": "default.other.fileChooser" - }, - { - "label": "Timestamp", - "route": "default.other.timestamp" - }, - { - "label": "PinPad", - "route": "default.other.pinPad" - }, - { - "label": "Clock", - "route": "default.other.clock" - }, - { - "label": "Icons", - "route": "default.other.icons" - }, - { - "label": "Element Factories vs. JSX", - "route": "default.other.jsx" - } - ] - }, - { - "label": "App Notifications", - "route": "default.other.appNotifications", - "options": [ - { - "label": "App Update", - "route": "default.other.appNotifications|Update" - }, - { - "label": "App Sleep Mode", - "route": "default.other.appNotifications|Sleep" - } - ] - }, - { - "label": "Number Formats", - "route": "default.other.numberFormats", - "options": [ - { - "label": "fmtNumber", - "route": "default.other.numberFormats|fmtNumber" - }, - { - "label": "fmtPrice", - "route": "default.other.numberFormats|fmtPrice" - }, - { - "label": "fmtQuantity", - "route": "default.other.numberFormats|fmtQuantity" - }, - { - "label": "fmtPercent", - "route": "default.other.numberFormats|fmtPercent" - }, - { - "label": "fmtThousands", - "route": "default.other.numberFormats|fmtThousands" - }, - { - "label": "fmtMillions", - "route": "default.other.numberFormats|fmtMillions" - }, - { - "label": "fmtBillions", - "route": "default.other.numberFormats|fmtBillions" - }, - { - "label": "Precision", - "route": "default.other.numberFormats|Precision" - }, - { - "label": "zeroPad", - "route": "default.other.numberFormats|zeroPad" - }, - { - "label": "ledger", - "route": "default.other.numberFormats|ledger" - }, - { - "label": "forceLedgerAlign", - "route": "default.other.numberFormats|forceLedgerAlign" - }, - { - "label": "colorSpec", - "route": "default.other.numberFormats|colorSpec" - }, - { - "label": "withPlusSign", - "route": "default.other.numberFormats|withPlusSign" - }, - { - "label": "withSignGlyph", - "route": "default.other.numberFormats|withSignGlyph" - }, - { - "label": "label", - "route": "default.other.numberFormats|label" - }, - { - "label": "nullDisplay", - "route": "default.other.numberFormats|nullDisplay" - } - ] - }, - { - "label": "Date Formats", - "route": "default.other.dateFormats", - "options": [ - { - "label": "fmtDate", - "route": "default.other.dateFormats|fmtDate" - }, - { - "label": "fmtCompactDate", - "route": "default.other.dateFormats|fmtCompactDate" - }, - { - "label": "fmtDateTime", - "route": "default.other.dateFormats|fmtDateTime" - }, - { - "label": "fmtTime", - "route": "default.other.dateFormats|fmtTime" - }, - { - "label": "tooltip", - "route": "default.other.dateFormats|tooltip" - } - ] - }, - { - "label": "Popups", - "route": "default.other.popups", - "options": [ - { - "label": "Alert", - "route": "default.other.popups|Alert" - }, - { - "label": "Confirm", - "route": "default.other.popups|Confirm" - }, - { - "label": "Prompt", - "route": "default.other.popups|Prompt" - }, - { - "label": "Message", - "route": "default.other.popups|Message" - }, - { - "label": "Toast", - "route": "default.other.popups|Toast" - } - ] - } - ] - - */ diff --git a/grails-app/init/io/xh/toolbox/BootStrap.groovy b/grails-app/init/io/xh/toolbox/BootStrap.groovy index e1396a941..f8e77f2fa 100755 --- a/grails-app/init/io/xh/toolbox/BootStrap.groovy +++ b/grails-app/init/io/xh/toolbox/BootStrap.groovy @@ -254,6 +254,415 @@ class BootStrap implements LogSupport { ] ], clientVisible: true + ], + searchOptions: [ + groupName: 'Toolbox', + valueType: 'json', + defaultValue: [ + [ + label: "containers", + route: "default.layout", + options: [ + [ + label: "TabContainer", + route: "default.layout.tabPanel" + ], + [ + label: "Top Tabs", + route: "default.layout.tabPanel|Top" + ], + [ + label: "Bottom Tabs", + route: "default.layout.tabPanel|Bottom" + ], + [ + label: "Left Tabs", + route: "default.layout.tabPanel|Left" + ], + [ + label: "Right Tabs", + route: "default.layout.tabPanel|Right" + ], + [ + label: "Custom Tab Switcher", + route: "default.layout.tabPanel|Switcher" + ], + [ + label: "Tab State", + route: "default.layout.tabPanel|State" + ], + [ + label: "Dynamic Tabs", + route: "default.layout.tabPanel|Dynamic" + ], + [ + label: "DockContainer", + route: "default.layout.dock" + ], + [ + label: "DashCanvas", + route: "default.layout.dashCanvas" + ], + [ + label: "DashContainer", + route: "default.layout.dashContainer" + ], + [ + label: "HBox", + route: "default.layout.hbox" + ], + [ + label: "VBox", + route: "default.layout.vbox" + ], + [ + label: "TileFrame", + route: "default.layout.tileFrame" + ] + ] + ], + [ + label: "Examples", + route: "default.examples", + options: [ + [ + label: "Portfolio", + route: "launch.examples.portfolio" + ], + [ + label: "News", + route: "launch.examples.news" + ], + [ + label: "FDA Recalls", + route: "launch.examples.recalls" + ], + [ + label: "File Manager", + route: "launch.examples.fileManager" + ] + ] + ], + [ + label: "panels", + route: "default.panels", + options: [ + [ + label: "LoadingIndicator", + route: "default.panels.loadingIndicator" + ], + [ + label: "Mask", + route: "default.panels.mask" + ], + [ + label: "Sizing", + route: "default.panels.sizing" + ], + [ + label: "Toolbars", + route: "default.panels.toolbars" + ] + ] + ], + [ + label: "charts", + route: "default.charts", + options: [ + [ + label: "Line", + route: "default.charts.line" + ], + [ + label: "Chart Aspect Ratio", + route: "default.charts.line|AspectRatio" + ], + [ + label: "OHLC", + route: "default.charts.ohlc" + ], + [ + label: "Grid TreeMap", + route: "default.charts.gridTreeMap" + ], + [ + label: "Simple TreeMap", + route: "default.charts.simpleTreeMap" + ], + [ + label: "Split TreeMap", + route: "default.charts.splitTreeMap" + ] + ] + ], + [ + label: "grids", + route: "default.grids", + options: [ + [ + label: "Standard", + route: "default.grids.standard" + ], + [ + label: "Tree with CheckBox", + route: "default.grids.treeWithCheckBox" + ], + [ + label: "Grouped Rows", + route: "default.grids.groupedRows" + ], + [ + label: "Grouped Cols", + route: "default.grids.groupedCols" + ], + [ + label: "Dataview", + route: "default.grids.dataview" + ], + [ + label: "agGrid", + route: "default.grids.agGrid" + ], + [ + label: "Tree", + route: "default.grids.tree" + ], + [ + label: "Rest", + route: "default.grids.rest" + ] + ] + ], + [ + label: "forms", + route: "default.forms", + options: [ + [ + label: "Toolbar Form", + route: "default.forms.toolbarForm" + ], + [ + label: "Inputs", + route: "default.forms.inputs" + ], + [ + label: "TextInput", + route: "default.forms.inputs|TextInput" + ], + [ + label: "TextArea", + route: "default.forms.inputs|TextArea" + ], + [ + label: "JSONInput", + route: "default.forms.inputs|JSONInput" + ], + [ + label: "NumberInput", + route: "default.forms.inputs|NumberInput" + ], + [ + label: "Slider", + route: "default.forms.inputs|Slider" + ], + [ + label: "DateInput", + route: "default.forms.inputs|DateInput" + ], + [ + label: "Select", + route: "default.forms.inputs|Select" + ], + [ + label: "Checkbox", + route: "default.forms.inputs|Checkbox" + ], + [ + label: "ButtonGroupInput", + route: "default.forms.inputs|ButtonGroupInput" + ], + [ + label: "RadioInput", + route: "default.forms.inputs|RadioInput" + ], + [ + label: "Form", + route: "default.forms.form" + ] + ] + ], + [ + label: "other", + route: "default.other", + options: [ + [ + label: "LeftRightChooser", + route: "default.other.leftRightChooser" + ], + [ + label: "File Chooser", + route: "default.other.fileChooser" + ], + [ + label: "Timestamp", + route: "default.other.timestamp" + ], + [ + label: "PinPad", + route: "default.other.pinPad" + ], + [ + label: "Clock", + route: "default.other.clock" + ], + [ + label: "Icons", + route: "default.other.icons" + ], + [ + label: "Element Factories vs. JSX", + route: "default.other.jsx" + ] + ] + ], + [ + label: "App Notifications", + route: "default.other.appNotifications", + options: [ + [ + label: "App Update", + route: "default.other.appNotifications|Update" + ], + [ + label: "App Sleep Mode", + route: "default.other.appNotifications|Sleep" + ] + ] + ], + [ + label: "Number Formats", + route: "default.other.numberFormats", + options: [ + [ + label: "fmtNumber", + route: "default.other.numberFormats|fmtNumber" + ], + [ + label: "fmtPrice", + route: "default.other.numberFormats|fmtPrice" + ], + [ + label: "fmtQuantity", + route: "default.other.numberFormats|fmtQuantity" + ], + [ + label: "fmtPercent", + route: "default.other.numberFormats|fmtPercent" + ], + [ + label: "fmtThousands", + route: "default.other.numberFormats|fmtThousands" + ], + [ + label: "fmtMillions", + route: "default.other.numberFormats|fmtMillions" + ], + [ + label: "fmtBillions", + route: "default.other.numberFormats|fmtBillions" + ], + [ + label: "Precision", + route: "default.other.numberFormats|Precision" + ], + [ + label: "zeroPad", + route: "default.other.numberFormats|zeroPad" + ], + [ + label: "ledger", + route: "default.other.numberFormats|ledger" + ], + [ + label: "forceLedgerAlign", + route: "default.other.numberFormats|forceLedgerAlign" + ], + [ + label: "colorSpec", + route: "default.other.numberFormats|colorSpec" + ], + [ + label: "withPlusSign", + route: "default.other.numberFormats|withPlusSign" + ], + [ + label: "withSignGlyph", + route: "default.other.numberFormats|withSignGlyph" + ], + [ + label: "label", + route: "default.other.numberFormats|label" + ], + [ + label: "nullDisplay", + route: "default.other.numberFormats|nullDisplay" + ] + ] + ], + [ + label: "Date Formats", + route: "default.other.dateFormats", + options: [ + [ + label: "fmtDate", + route: "default.other.dateFormats|fmtDate" + ], + [ + label: "fmtCompactDate", + route: "default.other.dateFormats|fmtCompactDate" + ], + [ + label: "fmtDateTime", + route: "default.other.dateFormats|fmtDateTime" + ], + [ + label: "fmtTime", + route: "default.other.dateFormats|fmtTime" + ], + [ + label: "tooltip", + route: "default.other.dateFormats|tooltip" + ] + ] + ], + [ + label: "Popups", + route: "default.other.popups", + options: [ + [ + label: "Alert", + route: "default.other.popups|Alert" + ], + [ + label: "Confirm", + route: "default.other.popups|Confirm" + ], + [ + label: "Prompt", + route: "default.other.popups|Prompt" + ], + [ + label: "Message", + route: "default.other.popups|Message" + ], + [ + label: "Toast", + route: "default.other.popups|Toast" + ] + ] + ] + ], + clientVisible: true ] ]) }