Skip to content

Commit

Permalink
allow adding and removing custom fields, hide functionality behind fe…
Browse files Browse the repository at this point in the history
…ature flag
  • Loading branch information
karel kremer committed Dec 19, 2024
1 parent 8868f2b commit 2d978be
Show file tree
Hide file tree
Showing 17 changed files with 303 additions and 183 deletions.
18 changes: 18 additions & 0 deletions app/components/editable-form.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{#unless this.loading}}
<SemanticForms::Instance
@instanceId={{@instanceId}}
@form={{this.currentForm}}
@onCancel={{@onCancel}}
@onSave={{@onSave}}
@formInitialized={{@formInitialized}}
@customHistoryMessage={{@customHistoryMessage}}
>
{{#if this.editableFormsEnabled}}
<GenerateCustomFieldButton
@form={{this.currentForm}}
@onUpdate={{this.onFormUpdate}}
/>
{{/if}}
{{yield}}
</SemanticForms::Instance>
{{/unless}}
41 changes: 41 additions & 0 deletions app/components/editable-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { service } from '@ember/service';
import { provide } from 'ember-provide-consume-context';

export default class EditableFormComponent extends Component {
baseFormId;
@tracked currentForm;
@tracked loading = true;
@service formReplacements;
@service semanticFormRepository;
@service features;

constructor() {
super(...arguments);
this.baseFormId = this.args.form.id;
this.updateForm();
}

async updateForm() {
this.loading = true;
const currentFormId = this.formReplacements.getReplacement(this.baseFormId);
const form = await this.semanticFormRepository.getFormDefinition(
currentFormId,
true
);
this.currentForm = form;
this.loading = false;
}

get editableFormsEnabled() {
return this.features.isEnabled('editable-forms');
}

@provide('on-form-update')
@action
onFormUpdate() {
this.updateForm();
}
}
45 changes: 44 additions & 1 deletion app/components/generate-custom-field-button.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,47 @@
>
Voeg een veld toe
</AuButton>
{{yield}}
{{yield}}

<AuModal
@modalOpen={{this.showModal}}
@closeModal={{this.closeModal}}
@closable={{true}}
@title="Voeg een veld toe"
>
<div class="au-o-box au-o-flow">
<div>
<AuLabel @required={{true}} for="field-name">Naam</AuLabel>
<AuInput
@width="block"
@iconAlignment="left"
value={{this.fieldName}}
id="field-name"
{{on "input" this.updateName}}
/>
</div>
<AuToolbar class="au-u-margin-top" as |Group|>
<Group>
<AuButtonGroup>
<Shared::Tooltip
@showTooltip={{this.invalidFieldInfo}}
@tooltipText="Vul alle informatie in om het veld op te slaan."
@alignment="left"
>
<AuButton
{{on "click" this.onSaveField}}
@disabled={{this.disabled}}
@loading={{this.loading}}
>
Creëer veld
</AuButton>
</Shared::Tooltip>
<AuButton {{on "click" this.closeModal}} @skin="secondary">
Annuleer
</AuButton>
</AuButtonGroup>
</Group>
</AuToolbar>
</div>

</AuModal>
55 changes: 53 additions & 2 deletions app/components/generate-custom-field-button.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,60 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { JSON_API_TYPE } from 'frontend-lmb/utils/constants';

export default class GenerateCustomFieldButtonComponent extends Component {
@service formReplacements;
@tracked showModal = false;
@tracked loading = false;
@tracked fieldName = '';

get invalidName() {
return !this.fieldName || this.fieldName.trim().length < 1;
}

get disabled() {
return this.invalidName;
}

@action
onAddField() {
console.log(`add clicked ${this.args.form.id}`);
async onAddField() {
this.showModal = true;
this.fieldName = '';
}

@action
closeModal() {
this.showModal = false;
}

@action async onSaveField() {
this.loading = true;
const result = await fetch(`/form-content/${this.args.form.id}/fields`, {
method: 'POST',
headers: {
'Content-Type': JSON_API_TYPE,
},
body: JSON.stringify({
displayType:
'http://lblod.data.gift/display-types/lmb/custom-string-input',
order: 9000,
name: this.fieldName,
}),
});

const body = await result.json();
const newFormId = body.id;
this.formReplacements.setReplacement(this.args.form.id, newFormId);
if (this.args.onUpdate) {
this.args.onUpdate();
}
this.loading = false;
this.showModal = false;
}

@action updateName(event) {
this.fieldName = event.target.value;
}
}
13 changes: 5 additions & 8 deletions app/components/mandatarissen/mandataris-extra-info-card.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,16 @@
@closeModal={{this.toggleModal}}
>
<div class="au-o-box">
<SemanticForms::Instance
<EditableForm
@instanceId={{@mandataris.id}}
@form={{@form}}
@onCancel={{this.toggleModal}}
@onSave={{this.onSave}}
@formInitialized={{fn (mut this.formInitialized) true}}
@customHistoryMessage={{true}}
>
{{#if this.formInitialized}}
<GenerateCustomFieldButton @form={{@form}} />
{{else}}
<Skeleton::Forms::MandatarisExtraInfo />
{{/if}}
</SemanticForms::Instance>
/>
{{#unless this.formInitialized}}
<Skeleton::Forms::MandatarisExtraInfo />
{{/unless}}
</div>
</AuModal>
55 changes: 29 additions & 26 deletions app/components/rdf-input-fields/custom-field-wrapper.hbs
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
<AuLabel
for={{this.inputId}}
@error={{this.hasErrors}}
@warning={{this.hasWarnings}}
@required={{this.isRequired}}
>{{this.title}}</AuLabel>
<div
class="au-u-flex au-u-flex--between au-u-flex--vertical-start au-u-flex--spaced-tiny"
>
<div class="flex-grow">
{{yield}}
</div>
<AuButton
@skin="secondary"
@alert={{true}}
@icon="trash"
{{on "click" this.onRemove}}
{{#unless this.removed}}
<AuLabel
for={{this.inputId}}
@error={{this.hasErrors}}
@warning={{this.hasWarnings}}
@required={{this.isRequired}}
>{{this.title}}</AuLabel>
<div
class="au-u-flex au-u-flex--between au-u-flex--vertical-start au-u-flex--spaced-tiny"
>
Remove
</AuButton>
</div>
{{#each this.errors as |error|}}
<AuHelpText @error={{true}}>{{error.resultMessage}}</AuHelpText>
{{/each}}
<div class="flex-grow">
{{yield}}
</div>
<AuButton
@skin="secondary"
@alert={{true}}
@icon="trash"
@loading={{this.removing}}
{{on "click" this.onRemove}}
>
Remove
</AuButton>
</div>
{{#each this.errors as |error|}}
<AuHelpText @error={{true}}>{{error.resultMessage}}</AuHelpText>
{{/each}}

{{#each this.warnings as |warning|}}
<AuHelpText @warning={{true}}>{{warning.resultMessage}}</AuHelpText>
{{/each}}
{{#each this.warnings as |warning|}}
<AuHelpText @warning={{true}}>{{warning.resultMessage}}</AuHelpText>
{{/each}}
{{/unless}}
26 changes: 22 additions & 4 deletions app/components/rdf-input-fields/custom-field-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { JSON_API_TYPE } from 'frontend-lmb/utils/constants';
import { consume } from 'ember-provide-consume-context';

export default class RdfInputFieldsCustomFieldWrapperComponent extends Component {
@service formReplacements;
@consume('on-form-update') onUpdate;

@tracked removing = false;
get title() {
return this.args.field?.label;
}

@action
onRemove() {
console.log(
`remove clicked on ${this.args.field.uri} of form ${this.args.form}`
);
async onRemove() {
this.removing = true;
await fetch(`/form-content/fields`, {
method: 'DELETE',
headers: {
'Content-Type': JSON_API_TYPE,
},
body: JSON.stringify({
fieldUri: this.args.field.uri.value,
formUri: this.args.form.uri,
}),
});
this.onUpdate();
this.removed = true;
}
}
2 changes: 2 additions & 0 deletions app/routes/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ export default class ApplicationRoute extends Route {
@service router;
@service decretaleOrganen;
@service mandatarisStatus;
@service formReplacements;

async beforeModel() {
await this.session.setup();
await this.formReplacements.setup();
await Promise.all([
this.decretaleOrganen.setup(),
this.mandatarisStatus.loadStatusOptions(),
Expand Down
32 changes: 0 additions & 32 deletions app/services/form-dirty-state.js

This file was deleted.

40 changes: 40 additions & 0 deletions app/services/form-replacements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { JSON_API_TYPE } from 'frontend-lmb/utils/constants';

export default class FormReplacementsService extends Service {
@tracked formReplacements = null;

async setup() {
const result = await fetch(`/form-content/form-replacements`, {
method: 'GET',
headers: {
'Content-Type': JSON_API_TYPE,
},
});

const idReplacements = await result.json();
const mapping = {};
for (const replacement of idReplacements.replacements) {
mapping[replacement.standardId] = replacement.replacementId;
}
this.formReplacements = mapping;
}

setReplacement(standardId, replacementId) {
const newFormReplacements = { ...this.formReplacements };
// maybe the 'standardid' is already a replaced form, let's check the current mapping
let trueStandardId = standardId;
for (const [key, value] of Object.entries(this.formReplacements)) {
if (value === standardId) {
trueStandardId = key;
}
}
newFormReplacements[trueStandardId] = replacementId;
this.formReplacements = newFormReplacements;
}

getReplacement(standardId) {
return this.formReplacements[standardId] || standardId;
}
}
Loading

0 comments on commit 2d978be

Please sign in to comment.