From abd0b7ed95b1f92adb4bc64841b0acb293adad03 Mon Sep 17 00:00:00 2001 From: Stanislav Romanov Date: Sun, 27 Mar 2022 13:00:49 +0300 Subject: [PATCH] Add table of index attributes --- app/components/input-checkbox.hbs | 4 + app/components/input-checkbox.js | 11 ++ app/routes/admin/indexes.js | 8 +- app/routes/admin/indexes/item/settings.js | 60 ++++++- app/templates/admin/indexes/item/settings.hbs | 47 ++++- package-lock.json | 160 ++++++++++++++++++ package.json | 2 + .../components/input-checkbox-test.js | 26 +++ .../components/input-textarea-test.js | 26 +++ 9 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 app/components/input-checkbox.hbs create mode 100644 app/components/input-checkbox.js create mode 100644 tests/integration/components/input-checkbox-test.js create mode 100644 tests/integration/components/input-textarea-test.js diff --git a/app/components/input-checkbox.hbs b/app/components/input-checkbox.hbs new file mode 100644 index 0000000..64d50e1 --- /dev/null +++ b/app/components/input-checkbox.hbs @@ -0,0 +1,4 @@ + diff --git a/app/components/input-checkbox.js b/app/components/input-checkbox.js new file mode 100644 index 0000000..342367c --- /dev/null +++ b/app/components/input-checkbox.js @@ -0,0 +1,11 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +export default class InputCheckboxComponent extends Component { + @action + onChange() { + if (this.args.onChange) { + this.args.onChange(!this.args.checked); + } + } +} diff --git a/app/routes/admin/indexes.js b/app/routes/admin/indexes.js index bd4192e..7cfdd6e 100644 --- a/app/routes/admin/indexes.js +++ b/app/routes/admin/indexes.js @@ -1,9 +1,3 @@ import Route from '@ember/routing/route'; -// import { inject as service } from '@ember/service'; -export default class AdminIndexesRoute extends Route { - // @service meilisearch; - // async model() { - // return this.modelFor('admin'); - // } -} +export default class AdminIndexesRoute extends Route {} diff --git a/app/routes/admin/indexes/item/settings.js b/app/routes/admin/indexes/item/settings.js index 5be6546..28e8ea3 100644 --- a/app/routes/admin/indexes/item/settings.js +++ b/app/routes/admin/indexes/item/settings.js @@ -1,3 +1,61 @@ import Route from '@ember/routing/route'; +import { hash } from 'rsvp'; -export default class AdminIndexesItemSettingsRoute extends Route {} +function attributeValue(key) { + return function () { + return { + get() { + return this.settings[key].includes(this.name); + }, + + set(value) { + if (value) { + this.settings[key].addObject(this.name); + } else { + this.settings[key].removeObject(this.name); + } + }, + }; + }; +} + +class IndexAttribute { + name; + settings; + + @attributeValue('displayedAttributes') displayed; + @attributeValue('filterableAttributes') filterable; + @attributeValue('searchableAttributes') searchable; + @attributeValue('sortableAttributes') sortable; + + constructor(name, settings) { + this.name = name; + this.settings = settings; + } +} + +export default class AdminIndexesItemSettingsRoute extends Route { + async model() { + const index = this.modelFor('admin.indexes.item'); + const settings = index.getSettings(); + const stats = index.getStats(); + + return hash({ index, settings, stats }).then((result) => { + // Some settings properties may to be ["*"] (all attributes) + // this convert it to [attr1, attr2, ...] + ['displayedAttributes', 'searchableAttributes'].forEach((prop) => { + if ( + result.settings[prop].length === 1 && + result.settings[prop][0] === '*' + ) { + result.settings[prop] = Object.keys(result.stats.fieldDistribution); + } + }); + result.attributes = Object.keys(result.stats.fieldDistribution).map( + (name) => new IndexAttribute(name, result.settings) + ); + + return result; + }); + } +} diff --git a/app/templates/admin/indexes/item/settings.hbs b/app/templates/admin/indexes/item/settings.hbs index ec41987..df76264 100644 --- a/app/templates/admin/indexes/item/settings.hbs +++ b/app/templates/admin/indexes/item/settings.hbs @@ -1,2 +1,47 @@ {{page-title "Settings"}} -{{outlet}} \ No newline at end of file + +{{#let (hash td="px-4 py-2 text-left whitespace-nowrap") as |classes|}} +

Attributes

+ + + + + + + + + + + + {{#each @model.attributes as |attribute|}} + + + + + + + + {{/each}} + +
#DisplayedFilterableSearchableSortable
{{attribute.name}} + + + + + + + +
+{{/let}} diff --git a/package-lock.json b/package-lock.json index 5f4abd8..7c9c4ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "ember-cli-postcss": "^8.0.0", "ember-cli-sri": "^2.1.1", "ember-cli-terser": "^4.0.2", + "ember-composable-helpers": "^5.0.0", "ember-data": "~4.2.0", "ember-export-application-global": "^2.0.1", "ember-fetch": "^8.1.1", @@ -52,6 +53,7 @@ "ember-qunit": "^5.1.5", "ember-resolver": "^8.0.3", "ember-resources": "^4.4.0", + "ember-set-helper": "^2.0.1", "ember-source": "~4.2.0", "ember-template-lint": "^4.2.0", "ember-truth-helpers": "^3.0.0", @@ -11270,6 +11272,78 @@ "node": ">= 10.0.0" } }, + "node_modules/ember-composable-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ember-composable-helpers/-/ember-composable-helpers-5.0.0.tgz", + "integrity": "sha512-gyUrjiSju4QwNrsCLbBpP0FL6VDFZaELNW7Kbcp60xXhjvNjncYgzm4zzYXhT+i1lLA6WEgRZ3lOGgyBORYD0w==", + "dev": true, + "dependencies": { + "@babel/core": "^7.0.0", + "broccoli-funnel": "2.0.1", + "ember-cli-babel": "^7.26.3", + "resolve": "^1.10.0" + }, + "engines": { + "node": "12.* || 14.* || >= 16" + } + }, + "node_modules/ember-composable-helpers/node_modules/broccoli-funnel": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz", + "integrity": "sha512-C8Lnp9TVsSSiZMGEF16C0dCiNg2oJqUKwuZ1K4kVC6qRPG/2Cj/rtB5kRCC9qEbwqhX71bDbfHROx0L3J7zXQg==", + "dev": true, + "dependencies": { + "array-equal": "^1.0.0", + "blank-object": "^1.0.1", + "broccoli-plugin": "^1.3.0", + "debug": "^2.2.0", + "fast-ordered-set": "^1.0.0", + "fs-tree-diff": "^0.5.3", + "heimdalljs": "^0.2.0", + "minimatch": "^3.0.0", + "mkdirp": "^0.5.0", + "path-posix": "^1.0.0", + "rimraf": "^2.4.3", + "symlink-or-copy": "^1.0.0", + "walk-sync": "^0.3.1" + }, + "engines": { + "node": "^4.5 || 6.* || >= 7.*" + } + }, + "node_modules/ember-composable-helpers/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/ember-composable-helpers/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/ember-composable-helpers/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ember-composable-helpers/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "node_modules/ember-data": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ember-data/-/ember-data-4.2.0.tgz", @@ -13021,6 +13095,18 @@ "node": "8.* || 10.* || >= 12" } }, + "node_modules/ember-set-helper": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ember-set-helper/-/ember-set-helper-2.0.1.tgz", + "integrity": "sha512-6IIimVGOdehZcncH1ilCY4p7hWBtZqWYMc1Xodr1ATOCuIk6ZO1yztKcUQhlmwl7fE82gL4wHD01T6XP5W59Ng==", + "dev": true, + "dependencies": { + "ember-cli-babel": "^7.18.0" + }, + "engines": { + "node": "10.* || >= 12" + } + }, "node_modules/ember-source": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ember-source/-/ember-source-4.2.0.tgz", @@ -33326,6 +33412,71 @@ } } }, + "ember-composable-helpers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ember-composable-helpers/-/ember-composable-helpers-5.0.0.tgz", + "integrity": "sha512-gyUrjiSju4QwNrsCLbBpP0FL6VDFZaELNW7Kbcp60xXhjvNjncYgzm4zzYXhT+i1lLA6WEgRZ3lOGgyBORYD0w==", + "dev": true, + "requires": { + "@babel/core": "^7.0.0", + "broccoli-funnel": "2.0.1", + "ember-cli-babel": "^7.26.3", + "resolve": "^1.10.0" + }, + "dependencies": { + "broccoli-funnel": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/broccoli-funnel/-/broccoli-funnel-2.0.1.tgz", + "integrity": "sha512-C8Lnp9TVsSSiZMGEF16C0dCiNg2oJqUKwuZ1K4kVC6qRPG/2Cj/rtB5kRCC9qEbwqhX71bDbfHROx0L3J7zXQg==", + "dev": true, + "requires": { + "array-equal": "^1.0.0", + "blank-object": "^1.0.1", + "broccoli-plugin": "^1.3.0", + "debug": "^2.2.0", + "fast-ordered-set": "^1.0.0", + "fs-tree-diff": "^0.5.3", + "heimdalljs": "^0.2.0", + "minimatch": "^3.0.0", + "mkdirp": "^0.5.0", + "path-posix": "^1.0.0", + "rimraf": "^2.4.3", + "symlink-or-copy": "^1.0.0", + "walk-sync": "^0.3.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "ember-data": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ember-data/-/ember-data-4.2.0.tgz", @@ -34747,6 +34898,15 @@ "recast": "^0.18.1" } }, + "ember-set-helper": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ember-set-helper/-/ember-set-helper-2.0.1.tgz", + "integrity": "sha512-6IIimVGOdehZcncH1ilCY4p7hWBtZqWYMc1Xodr1ATOCuIk6ZO1yztKcUQhlmwl7fE82gL4wHD01T6XP5W59Ng==", + "dev": true, + "requires": { + "ember-cli-babel": "^7.18.0" + } + }, "ember-source": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ember-source/-/ember-source-4.2.0.tgz", diff --git a/package.json b/package.json index 1d60723..f772d12 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "ember-cli-postcss": "^8.0.0", "ember-cli-sri": "^2.1.1", "ember-cli-terser": "^4.0.2", + "ember-composable-helpers": "^5.0.0", "ember-data": "~4.2.0", "ember-export-application-global": "^2.0.1", "ember-fetch": "^8.1.1", @@ -72,6 +73,7 @@ "ember-qunit": "^5.1.5", "ember-resolver": "^8.0.3", "ember-resources": "^4.4.0", + "ember-set-helper": "^2.0.1", "ember-source": "~4.2.0", "ember-template-lint": "^4.2.0", "ember-truth-helpers": "^3.0.0", diff --git a/tests/integration/components/input-checkbox-test.js b/tests/integration/components/input-checkbox-test.js new file mode 100644 index 0000000..5ec0e4f --- /dev/null +++ b/tests/integration/components/input-checkbox-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | input-checkbox', function (hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs``); + + assert.dom(this.element).hasText(''); + + // Template block usage: + await render(hbs` + + template block text + + `); + + assert.dom(this.element).hasText('template block text'); + }); +}); diff --git a/tests/integration/components/input-textarea-test.js b/tests/integration/components/input-textarea-test.js new file mode 100644 index 0000000..715eef8 --- /dev/null +++ b/tests/integration/components/input-textarea-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | input-textarea', function (hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs``); + + assert.dom(this.element).hasText(''); + + // Template block usage: + await render(hbs` + + template block text + + `); + + assert.dom(this.element).hasText('template block text'); + }); +});