Add index setting form
This commit is contained in:
parent
c6aaf661bf
commit
9bab44310a
13 changed files with 247 additions and 140 deletions
|
|
@ -61,11 +61,13 @@ export default class ButtonComponent extends Component {
|
|||
}
|
||||
|
||||
@action
|
||||
async handleClick() {
|
||||
async handleClick(event) {
|
||||
if (typeof this.args.onClick !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
try {
|
||||
const maybePromise = this.args.onClick(this.args.value);
|
||||
|
||||
|
|
|
|||
13
app/components/form/index-setting.hbs
Normal file
13
app/components/form/index-setting.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<form class='mb-4' {{on 'submit' this.save}}>
|
||||
<InputTextarea
|
||||
@label={{namelize @name}}
|
||||
@name={{@name}}
|
||||
@value={{this.value}}
|
||||
@required={{true}}
|
||||
@onChange={{set this 'value'}}
|
||||
/>
|
||||
|
||||
<Button type='submit' @text='Save' @style='primary' />
|
||||
<Button @text='Cancel' @onClick={{this.cancel}} />
|
||||
<Button @text='Reset' @onClick={{this.reset}} />
|
||||
</form>
|
||||
48
app/components/form/index-setting.js
Normal file
48
app/components/form/index-setting.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { action } from '@ember/object';
|
||||
import { capitalize } from '@ember/string';
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class FormIndexSettingComponent extends Component {
|
||||
@tracked value;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
const fnName = `get${capitalize(this.args.name)}`;
|
||||
|
||||
this.args.index[fnName]().then((result) => {
|
||||
this.value = JSON.stringify(result);
|
||||
});
|
||||
}
|
||||
|
||||
get capitalizeName() {
|
||||
return capitalize(this.args.name);
|
||||
}
|
||||
|
||||
@action
|
||||
save(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(event.currentTarget);
|
||||
const data = formData.get(this.args.name);
|
||||
const fnName = `update${this.capitalizeName}`;
|
||||
|
||||
this.args.index[fnName](JSON.parse(data));
|
||||
}
|
||||
|
||||
@action
|
||||
async cancel() {
|
||||
const fnName = `get${this.capitalizeName}`;
|
||||
const oldValue = await this.args.index[fnName]();
|
||||
|
||||
this.value = JSON.stringify(oldValue);
|
||||
}
|
||||
|
||||
@action
|
||||
async reset() {
|
||||
const fnName = `reset${this.capitalizeName}`;
|
||||
|
||||
this.args.index[fnName]();
|
||||
}
|
||||
}
|
||||
7
app/components/headers/h3.hbs
Normal file
7
app/components/headers/h3.hbs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<h3 class='text-xl mb-4' ...attributes>
|
||||
{{#if (has-block)}}
|
||||
{{yield}}
|
||||
{{else}}
|
||||
{{@title}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
|
|
@ -1,26 +1,25 @@
|
|||
<div class="mb-4">
|
||||
<div class='mb-4'>
|
||||
{{#if @label}}
|
||||
<label for={{this.id}} class="block font-medium mb-1 text-dark">
|
||||
<label for={{this.id}} class='block font-medium mb-1 text-dark'>
|
||||
{{@label}}
|
||||
</label>
|
||||
{{/if}}
|
||||
<div class="relative flex items-center border rounded-md">
|
||||
<div class='relative flex items-center border rounded-md'>
|
||||
{{#if @prefixIcon}}
|
||||
<@prefixIcon class="h-8 w-8 pl-2" />
|
||||
<@prefixIcon class='h-8 w-8 pl-2' />
|
||||
{{/if}}
|
||||
<textarea
|
||||
type="text"
|
||||
<Textarea
|
||||
type='text'
|
||||
name={{@name}}
|
||||
id={{this.id}}
|
||||
class="block w-full p-2 bg-transparent focus:outline-none"
|
||||
class='block w-full p-2 bg-transparent focus:outline-none'
|
||||
placeholder={{@placeholder}}
|
||||
@value={{@value}}
|
||||
{{on 'change' this.onChange}}
|
||||
>
|
||||
{{~@value~}}
|
||||
</textarea>
|
||||
/>
|
||||
</div>
|
||||
{{#if @helper}}
|
||||
<div class="mt-1 text-sm">
|
||||
<div class='mt-1 text-sm'>
|
||||
{{@helper}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -1,97 +1,92 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { action, get, set } from '@ember/object';
|
||||
import arrayEquals from 'meiliadmin/utils/array-equals';
|
||||
import { ContentSaveOutline, Check, CircleMedium } from 'ember-mdi';
|
||||
// import { action, get, set } from '@ember/object';
|
||||
// import { capitalize } from '@ember/string';
|
||||
// import arrayEquals from 'meiliadmin/utils/array-equals';
|
||||
// import { ContentSaveOutline, Check, CircleMedium } from 'ember-mdi';
|
||||
|
||||
export default class AdminIndexesItemSettingsController extends Controller {
|
||||
emptyObj = {};
|
||||
ContentSaveOutline = ContentSaveOutline;
|
||||
Check = Check;
|
||||
CircleMedium = CircleMedium;
|
||||
|
||||
get rankingRulesFields() {
|
||||
const arr = [];
|
||||
// eslint-disable-next-line ember/no-get
|
||||
const rankingRules = get(this, 'model.settings.rankingRules');
|
||||
|
||||
Object.keys(this.model.stats.fieldDistribution).forEach((key) => {
|
||||
const asc = `${key}:asc`;
|
||||
const desc = `${key}:desc`;
|
||||
|
||||
if (!rankingRules.includes(asc)) {
|
||||
arr.push(asc);
|
||||
}
|
||||
|
||||
if (!rankingRules.includes(desc)) {
|
||||
arr.push(desc);
|
||||
}
|
||||
});
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
@action
|
||||
selectNewRankingRule(value) {
|
||||
this.model.settings.rankingRules.addObject(value);
|
||||
}
|
||||
|
||||
@action
|
||||
removeRankingRule(value) {
|
||||
this.model.settings.rankingRules.removeObject(value);
|
||||
}
|
||||
|
||||
@action
|
||||
saveStrToJSON(prop, emptyValue, str) {
|
||||
if (typeof str !== 'string' || str === '') {
|
||||
this.model.settings[prop] = emptyValue;
|
||||
} else {
|
||||
this.model.settings[prop] = JSON.parse(str);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
save() {
|
||||
const fields = Object.keys(this.model.stats.fieldDistribution);
|
||||
const settings = Object.assign({}, this.model.settings);
|
||||
|
||||
['displayedAttributes', 'searchableAttributes'].forEach((prop) => {
|
||||
if (arrayEquals(settings[prop].sort(), fields.sort())) {
|
||||
settings[prop] = ['*'];
|
||||
}
|
||||
});
|
||||
|
||||
return this.model.index.updateSettings(settings);
|
||||
}
|
||||
|
||||
@action
|
||||
reorderItems(itemModels) {
|
||||
set(this.model.settings, 'rankingRules', itemModels);
|
||||
}
|
||||
|
||||
@action
|
||||
setAttributeValue(key, item) {
|
||||
let arr = this.model[key];
|
||||
|
||||
if (arr.length === 1 && arr[0] === '*') {
|
||||
arr = Array.from(this.model.index.fields);
|
||||
}
|
||||
|
||||
if (arr.includes(item)) {
|
||||
arr = arr.filter((i) => i !== item);
|
||||
} else {
|
||||
arr = arr.concat([item]);
|
||||
}
|
||||
|
||||
set(this.model, key, arr);
|
||||
}
|
||||
|
||||
@action
|
||||
update(key, value) {
|
||||
this.model.index[key](value);
|
||||
}
|
||||
|
||||
@action
|
||||
reset(key) {
|
||||
this.model.index[key]();
|
||||
}
|
||||
// @action
|
||||
// save(name, value) {
|
||||
// const fnName = `update${capitalize(name)}`;
|
||||
// return this.model.index[fnName](value);
|
||||
// }
|
||||
// @action
|
||||
// async cancel(name) {
|
||||
// console.log(...arguments, this.model[name]);
|
||||
// const fnName = `get${capitalize(name)}`;
|
||||
// this.model[name] = await this.model.index[fnName]();
|
||||
// console.log(this.model[name]);
|
||||
// }
|
||||
// emptyObj = {};
|
||||
// ContentSaveOutline = ContentSaveOutline;
|
||||
// Check = Check;
|
||||
// CircleMedium = CircleMedium;
|
||||
// get rankingRulesFields() {
|
||||
// const arr = [];
|
||||
// // eslint-disable-next-line ember/no-get
|
||||
// const rankingRules = get(this, 'model.settings.rankingRules');
|
||||
// Object.keys(this.model.stats.fieldDistribution).forEach((key) => {
|
||||
// const asc = `${key}:asc`;
|
||||
// const desc = `${key}:desc`;
|
||||
// if (!rankingRules.includes(asc)) {
|
||||
// arr.push(asc);
|
||||
// }
|
||||
// if (!rankingRules.includes(desc)) {
|
||||
// arr.push(desc);
|
||||
// }
|
||||
// });
|
||||
// return arr;
|
||||
// }
|
||||
// @action
|
||||
// selectNewRankingRule(value) {
|
||||
// this.model.settings.rankingRules.addObject(value);
|
||||
// }
|
||||
// @action
|
||||
// removeRankingRule(value) {
|
||||
// this.model.settings.rankingRules.removeObject(value);
|
||||
// }
|
||||
// @action
|
||||
// saveStrToJSON(prop, emptyValue, str) {
|
||||
// if (typeof str !== 'string' || str === '') {
|
||||
// this.model.settings[prop] = emptyValue;
|
||||
// } else {
|
||||
// this.model.settings[prop] = JSON.parse(str);
|
||||
// }
|
||||
// }
|
||||
// @action
|
||||
// save() {
|
||||
// const fields = Object.keys(this.model.stats.fieldDistribution);
|
||||
// const settings = Object.assign({}, this.model.settings);
|
||||
// ['displayedAttributes', 'searchableAttributes'].forEach((prop) => {
|
||||
// if (arrayEquals(settings[prop].sort(), fields.sort())) {
|
||||
// settings[prop] = ['*'];
|
||||
// }
|
||||
// });
|
||||
// return this.model.index.updateSettings(settings);
|
||||
// }
|
||||
// @action
|
||||
// reorderItems(itemModels) {
|
||||
// set(this.model.settings, 'rankingRules', itemModels);
|
||||
// }
|
||||
// @action
|
||||
// setAttributeValue(key, item) {
|
||||
// let arr = this.model[key];
|
||||
// if (arr.length === 1 && arr[0] === '*') {
|
||||
// arr = Array.from(this.model.index.fields);
|
||||
// }
|
||||
// if (arr.includes(item)) {
|
||||
// arr = arr.filter((i) => i !== item);
|
||||
// } else {
|
||||
// arr = arr.concat([item]);
|
||||
// }
|
||||
// set(this.model, key, arr);
|
||||
// }
|
||||
// @action
|
||||
// update(key, value) {
|
||||
// this.model.index[key](value);
|
||||
// }
|
||||
// @action
|
||||
// reset(key) {
|
||||
// this.model.index[key]();
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
6
app/helpers/namelize.js
Normal file
6
app/helpers/namelize.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { helper } from '@ember/component/helper';
|
||||
import { capitalize, underscore } from '@ember/string';
|
||||
|
||||
export default helper(function namelize([str]) {
|
||||
return capitalize(underscore(str).replaceAll('_', ' '));
|
||||
});
|
||||
|
|
@ -66,30 +66,22 @@ export default class Index {
|
|||
});
|
||||
}
|
||||
|
||||
// get allAttributesAreDisplayed() {
|
||||
// return (
|
||||
// this.displayedAttributes.value &&
|
||||
// this.displayedAttributes.value.length === 1 &&
|
||||
// this.displayedAttributes.value[0] === '*'
|
||||
// );
|
||||
// }
|
||||
getDisplayedAttributes() {
|
||||
return query(`${this.path}/settings/displayed-attributes`);
|
||||
}
|
||||
|
||||
// getDisplayedAttributes() {
|
||||
// return query(`${this.path}/settings/displayed-attributes`);
|
||||
// }
|
||||
updateDisplayedAttributes(value) {
|
||||
return query(`${this.path}/settings/displayed-attributes`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(value),
|
||||
});
|
||||
}
|
||||
|
||||
// updateDisplayedAttributes(value) {
|
||||
// return query(`${this.path}/settings/displayed-attributes`, {
|
||||
// method: 'POST',
|
||||
// body: JSON.stringify(value),
|
||||
// });
|
||||
// }
|
||||
|
||||
// resetDisplayedAttributes() {
|
||||
// return query(`${this.path}/settings/displayed-attributes`, {
|
||||
// method: 'DELETE',
|
||||
// });
|
||||
// }
|
||||
resetDisplayedAttributes() {
|
||||
return query(`${this.path}/settings/displayed-attributes`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// getSearchableAttributes() {
|
||||
// return query(`${this.path}/settings/searchable-attributes`);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { hash } from 'rsvp';
|
||||
// import { hash } from 'rsvp';
|
||||
|
||||
export default class AdminIndexesItemSettingsRoute extends Route {
|
||||
async model() {
|
||||
// const index = this.modelFor('admin.indexes.item');
|
||||
// const stats = index.stats;
|
||||
|
||||
return hash({
|
||||
// index,
|
||||
// stats,
|
||||
// displayedAttributes: index.getDisplayedAttributes(),
|
||||
// searchableAttributes: index.getSearchableAttributes(),
|
||||
});
|
||||
}
|
||||
// async model() {
|
||||
// const index = this.modelFor('admin.indexes.item');
|
||||
// return hash({
|
||||
// index,
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<div class="flex mb-4">
|
||||
<Tab @route="admin.indexes.item.documents" @text="Documents" @model={{@model}} />
|
||||
<Tab @route="admin.indexes.item.info" @text="Info" @model={{@model}} />
|
||||
<Tab @route="admin.indexes.item.settings" @text="Settings" @model={{@model}} />
|
||||
<Tab @route="admin.indexes.item.edit" @text="Edit" @model={{@model}} />
|
||||
<Tab @route="admin.indexes.item.delete" @text="Delete" @model={{@model}} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
TODO: refactoting
|
||||
{{! <Headers::H2 @title="Displayed attributes"/> }}
|
||||
|
||||
<Form::IndexSetting
|
||||
@name='displayedAttributes'
|
||||
@index={{@model}}
|
||||
/>
|
||||
|
||||
{{!-- <label class="text-xl mb-2 block">
|
||||
Displayed attributes
|
||||
</label>
|
||||
|
|
|
|||
26
tests/integration/components/form/index-setting-test.js
Normal file
26
tests/integration/components/form/index-setting-test.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | form/index-setting', 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`<Form::IndexSetting />`);
|
||||
|
||||
assert.dom(this.element).hasText('');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
<Form::IndexSetting>
|
||||
template block text
|
||||
</Form::IndexSetting>
|
||||
`);
|
||||
|
||||
assert.dom(this.element).hasText('template block text');
|
||||
});
|
||||
});
|
||||
17
tests/integration/helpers/namelize-test.js
Normal file
17
tests/integration/helpers/namelize-test.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'meiliadmin/tests/helpers';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Helper | namelize', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it renders', async function (assert) {
|
||||
this.set('inputValue', '1234');
|
||||
|
||||
await render(hbs`{{namelize this.inputValue}}`);
|
||||
|
||||
assert.dom(this.element).hasText('1234');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue