Add index setting form

This commit is contained in:
Stanislav Romanov 2022-09-02 10:18:37 +03:00
parent c6aaf661bf
commit 9bab44310a
13 changed files with 247 additions and 140 deletions

View file

@ -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);

View 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>

View 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]();
}
}

View file

@ -0,0 +1,7 @@
<h3 class='text-xl mb-4' ...attributes>
{{#if (has-block)}}
{{yield}}
{{else}}
{{@title}}
{{/if}}
</h3>

View file

@ -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}}

View file

@ -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
View 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('_', ' '));
});

View file

@ -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`);

View file

@ -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,
// });
// }
}

View file

@ -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>

View file

@ -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>

View 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');
});
});

View 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');
});
});