Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gn 4901 autofill variable #472

Merged
merged 32 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2054acf
First version of the autofill variable, checkbox not working yet
lagartoverde Sep 2, 2024
ce1d1d9
weird bug
lagartoverde Sep 3, 2024
584a610
solved weird bug
lagartoverde Sep 3, 2024
aa00c65
another implementation
lagartoverde Sep 3, 2024
3bc8526
correctly process the convertToString attribute
lagartoverde Sep 3, 2024
3b65509
ready for testing
lagartoverde Sep 3, 2024
f4f5f78
set the placeholder to the key
lagartoverde Sep 3, 2024
6301d86
remove button and replace automatically
lagartoverde Sep 3, 2024
50a6c5f
use a plugin to autofill the variables
lagartoverde Sep 9, 2024
ec6098f
check both values in the plugin
lagartoverde Sep 9, 2024
a114436
linting and changeset
lagartoverde Sep 9, 2024
488ef32
one last linting
lagartoverde Sep 9, 2024
d0c54d9
convert to gts and fix problem when modifying variables
lagartoverde Sep 25, 2024
a6a502a
improved text of the convert to string option
lagartoverde Sep 25, 2024
001b66f
added first version of the edit component
lagartoverde Sep 26, 2024
8d39f04
chore: remove unused imports
abeforgit Sep 26, 2024
7006fcb
fix: get rid of side-effects in getter
abeforgit Sep 26, 2024
f6deaaa
fix: use the mainview to set the attribute
abeforgit Sep 26, 2024
241709b
fix linting issues
lagartoverde Sep 27, 2024
5b44174
autofilled variable can only be initialized once and cleanup
lagartoverde Sep 27, 2024
8e3bb74
linting
lagartoverde Sep 27, 2024
266d1ae
Merge remote-tracking branch 'origin/master' into GN-4901-autofill-va…
lagartoverde Sep 27, 2024
423051f
add meta for snippet insertion after merge
lagartoverde Sep 27, 2024
d5b2016
Fix some merge issues/typos
piemonkey Sep 30, 2024
a637f76
you are now able to update the label
lagartoverde Oct 1, 2024
0459b40
Merge remote-tracking branch 'origin/master' into GN-4901-autofill-va…
lagartoverde Oct 1, 2024
5617447
linting
lagartoverde Oct 1, 2024
5c13d1c
Update translations/nl-BE.yaml
lagartoverde Oct 4, 2024
68216d2
Update translations/nl-BE.yaml
lagartoverde Oct 4, 2024
d6d559b
Update translations/nl-BE.yaml
lagartoverde Oct 4, 2024
a1e8268
Update translations/en-US.yaml
lagartoverde Oct 4, 2024
7bb5983
Merge branch 'master' into GN-4901-autofill-variable
lagartoverde Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/mean-deers-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lblod/ember-rdfa-editor-lblod-plugins': minor
---

Add autofill variable
224 changes: 224 additions & 0 deletions addon/components/variable-plugin/autofilled/edit.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { NodeSelection, type SayController } from '@lblod/ember-rdfa-editor';
import IntlService from 'ember-intl/services/intl';
import AuFormRow from '@appuniversum/ember-appuniversum/components/au-form-row';
import AuLabel from '@appuniversum/ember-appuniversum/components/au-label';
import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
import AuCheckbox from '@appuniversum/ember-appuniversum/components/au-checkbox';
import AuNativeInput from '@lblod/ember-rdfa-editor-lblod-plugins/components/au-native-input';
import AuCard from '@appuniversum/ember-appuniversum/components/au-card';
import AuHeading from '@appuniversum/ember-appuniversum/components/au-heading';
import t from 'ember-intl/helpers/t';
import { on } from '@ember/modifier';
import { trackedReset } from 'tracked-toolbox';
import { EXT } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory/data-factory';
import { getOutgoingTriple } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
import LabelInput from '../utils/label-input';
import {
ContentLiteralTerm,
SayLiteral,
SayNamedNode,
} from '@lblod/ember-rdfa-editor/core/say-data-factory';
type Args = {
controller: SayController;
};

type nodeProperty =
| {
predicate: string;
object: SayNamedNode<string>;
}
| {
predicate: string;
object: SayLiteral;
}
| {
predicate: string;
object: ContentLiteralTerm;
};

export default class AutoFilledVariableInsertComponent extends Component<Args> {
@service declare intl: IntlService;

// memo is the path to the trigger, which calls update
// see https://github.com/tracked-tools/tracked-toolbox?tab=readme-ov-file#trackedreset
// it's sort of badly explained in the docs, but it's a more generic version
// of localCopy, which we can't use here cause our derived state from the args
// is too complex to express as a string path
@trackedReset({
memo: 'args.controller.mainEditorState',
// using this as the first arg is special typescript syntax
// which allows you to explicitly type the this context, cause
// ts is not smart enough to know that
update(this: AutoFilledVariableInsertComponent) {
return this.convertToStringAttr;
},
})
convertToString: boolean = false;

@trackedReset({
memo: 'args.controller.mainEditorState',
update(this: AutoFilledVariableInsertComponent) {
return this.autofillKeyAttr;
},
})
autofillKey?: string;

@trackedReset({
memo: 'args.controller.mainEditorState',
update(this: AutoFilledVariableInsertComponent) {
return this.labelAttr;
},
})
label!: string;

get selectedVariable() {
const { selection } = this.controller.mainEditorState;
if (
selection instanceof NodeSelection &&
selection.node.type === this.controller.schema.nodes.autofilled_variable
) {
return {
node: selection.node,
pos: selection.from,
};
} else {
return null;
}
}
get autofillKeyAttr() {
return this.selectedVariable?.node.attrs.autofillKey;
}
get convertToStringAttr() {
return this.selectedVariable?.node.attrs.convertToString;
}
get labelAttr() {
if (!this.selectedVariable) return '';
return getOutgoingTriple(this.selectedVariable.node.attrs, EXT('label'))
?.object.value;
}

get showCard() {
return !!this.selectedVariable;
}

get controller() {
return this.args.controller;
}

get schema() {
return this.args.controller.schema;
}

get documentLanguage() {
return this.controller.documentLanguage;
}

@action
updateLabel(event: InputEvent) {
piemonkey marked this conversation as resolved.
Show resolved Hide resolved
this.label = (event.target as HTMLInputElement).value;
}

@action
updateAutofillKey(event: InputEvent) {
this.autofillKey = (event.target as HTMLInputElement).value;
}

@action
updateConvertToString(value: boolean) {
this.convertToString = value;
}

@action
edit() {
if (this.selectedVariable) {
this.controller.withTransaction(
(tr) => {
const position = this.selectedVariable?.pos as number;
tr.setNodeAttribute(position, 'autofillKey', this.autofillKey);
tr.setNodeAttribute(
position,
'convertToString',
this.convertToString,
);
const oldProperties = this.selectedVariable?.node.attrs.properties;
const newProperties = oldProperties.filter(
(property: nodeProperty) =>
property.predicate !== EXT('label').full,
);
newProperties.push({
predicate: EXT('label').full,
object: sayDataFactory.literal(this.label || ''),
});
tr.setNodeAttribute(position, 'properties', newProperties);
return tr;
},
// because the variable pill contains a nested editor, when it's
// selected, the currentEditorView is the nested one. When you run
// withTransaction without the optional second argument, it defaults to using
// the current view.
//
// Here, we don't want that, cause we want to edit the outside node, not
// any node in the nested editor.
{ view: this.controller.mainEditorView },
);
}
}
<template>
{{#if this.showCard}}
<AuCard
@flex={{true}}
@divided={{true}}
@isOpenInitially={{true}}
@expandable={{true}}
@shadow={{true}}
@size='small'
as |c|
>
<c.header>
<AuHeading @level='3' @skin='6'>
{{t 'variable-plugin.enter-variable-value'}}
</AuHeading>
</c.header>
<c.content>
<AuFormRow>
<LabelInput
@label={{this.label}}
@updateLabel={{this.updateLabel}}
/>
</AuFormRow>
<AuFormRow>
<AuLabel for='autofill_key'>
{{t 'variable-plugin.autofill.autofillKey'}}
</AuLabel>
<AuNativeInput
id='autofill_key'
placeholder={{t
'variable-plugin.autofill.autofillKeyPlaceholder'
}}
@type='text'
@width='block'
value={{this.autofillKey}}
{{on 'input' this.updateAutofillKey}}
/>
</AuFormRow>
<AuFormRow>
<AuCheckbox
id='convert_to_string'
@checked={{this.convertToString}}
@onChange={{this.updateConvertToString}}
>
{{t 'variable-plugin.autofill.convertToString'}}
</AuCheckbox>
</AuFormRow>
<AuButton {{on 'click' this.edit}}>
{{t 'variable-plugin.button'}}
</AuButton>
</c.content>
</AuCard>
{{/if}}
</template>
}
143 changes: 143 additions & 0 deletions addon/components/variable-plugin/autofilled/insert.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { service } from '@ember/service';
import { type SayController } from '@lblod/ember-rdfa-editor';
import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
import { v4 as uuidv4 } from 'uuid';
import IntlService from 'ember-intl/services/intl';
import {
DCT,
EXT,
RDF,
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
import { replaceSelectionWithAndSelectNode } from '@lblod/ember-rdfa-editor-lblod-plugins/commands';
import AuFormRow from '@appuniversum/ember-appuniversum/components/au-form-row';
import AuLabel from '@appuniversum/ember-appuniversum/components/au-label';
import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
import AuCheckbox from '@appuniversum/ember-appuniversum/components/au-checkbox';
import AuNativeInput from '@lblod/ember-rdfa-editor-lblod-plugins/components/au-native-input';
import t from 'ember-intl/helpers/t';
import { on } from '@ember/modifier';
import LabelInput from '@lblod/ember-rdfa-editor-lblod-plugins/components/variable-plugin/utils/label-input';

type Args = {
controller: SayController;
};

export default class AutoFilledVariableInsertComponent extends Component<Args> {
@service declare intl: IntlService;
@tracked label: string = '';
@tracked autofillKey?: string;
@tracked convertToString?: boolean;

get controller() {
return this.args.controller;
}

get schema() {
return this.args.controller.schema;
}

get documentLanguage() {
return this.controller.documentLanguage;
}

@action
updateLabel(event: InputEvent) {
this.label = (event.target as HTMLInputElement).value;
}

@action
updateAutofillKey(event: InputEvent) {
this.autofillKey = (event.target as HTMLInputElement).value;
}

@action
updateConvertToString(value: boolean) {
this.convertToString = value;
}

@action
insert() {
const mappingSubject = `http://data.lblod.info/mappings/${uuidv4()}`;
const variableInstance = `http://data.lblod.info/variables/${uuidv4()}`;
const variableId = uuidv4();

const placeholder = this.intl.t('variable.autofilled.label', {
locale: this.documentLanguage,
});

const label = this.label != '' ? this.label : placeholder;
const node = this.schema.nodes.autofilled_variable.create(
{
subject: mappingSubject,
rdfaNodeType: 'resource',
__rdfaId: variableId,
properties: [
{
predicate: RDF('type').full,
object: sayDataFactory.namedNode(EXT('Mapping').full),
},
{
predicate: EXT('instance').full,
object: sayDataFactory.namedNode(variableInstance),
},
{
predicate: EXT('label').full,
object: sayDataFactory.literal(label),
},
{
predicate: DCT('type').full,
object: sayDataFactory.literal('autofilled'),
},
{
predicate: EXT('content').full,
object: sayDataFactory.contentLiteral(),
},
],
autofillKey: this.autofillKey,
convertToString: this.convertToString,
},

this.schema.node('placeholder', {
placeholderText: `Autofill ${this.autofillKey}`,
}),
);
this.label = '';

this.controller.doCommand(replaceSelectionWithAndSelectNode(node), {
view: this.controller.mainEditorView,
});
}
<template>
<AuFormRow>
<LabelInput @label={{this.label}} @updateLabel={{this.updateLabel}} />
</AuFormRow>
<AuFormRow>
<AuLabel for='autofill_key'>
{{t 'variable-plugin.autofill.autofillKey'}}
</AuLabel>
<AuNativeInput
id='autofill_key'
placeholder={{t 'variable-plugin.autofill.autofillKeyPlaceholder'}}
@type='text'
@width='block'
value={{this.autofillKey}}
{{on 'input' this.updateAutofillKey}}
/>
</AuFormRow>
<AuFormRow>
<AuCheckbox
id='convert_to_string'
@checked={{this.convertToString}}
@onChange={{this.updateConvertToString}}
>
{{t 'variable-plugin.autofill.convertToString'}}
</AuCheckbox>
</AuFormRow>
<AuButton {{on 'click' this.insert}}>
{{t 'variable-plugin.button'}}
</AuButton>
</template>
}
Loading