Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions frontend/src/components/cme-form-view/FormBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,23 @@ class FormBuilder {
return this._tokens;
}

set tokenValues(val: { [name: string]: string | string[] }) {
this._tokenValues = val;
}

get tokenValues(): { [name: string]: string | string[] } {
return this._tokenValues;
}

set formItemChangeHandler(fn: () => void) {
this._handleFormItemChange = fn;
}

build(): TemplateResult[] {
const formElements = this._tokens.map((token) => {
if (token.isConditionalToken && token.linkedToken && token.matchValue && this.tokenValues?.[token.linkedToken.name] !== token.matchValue) {
return html`${nothing}`;
}
switch (token.type) {
case 'enum':
return this._renderEnumTypeWidget(token);
Expand All @@ -42,6 +53,8 @@ class FormBuilder {

private _tokens: Token[] = [];

private _tokenValues: { [name: string]: string | string[] } = {};

private _handleFormItemChange: () => void = noop;

private _renderFormItem(
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/cme-form-view/TemplateCompiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ class TemplateCompiler {
compile(): string {
let compiled = this._template;

this._tokens.forEach(({name, prefix = '', suffix = ''}) => {
this._tokens.forEach(({ name, prefix = '', suffix = '', isConditionalToken, linkedToken, matchValue }) => {
let value = this._tokenValues[name] || '';
value = value ? prefix + value + suffix : '';
const canShowConditionallyRendered = !isConditionalToken || !linkedToken || this._tokenValues[linkedToken.name] === matchValue;
value = value && canShowConditionallyRendered ? prefix + value + suffix : '';
compiled = compiled.replace(new RegExp(`{${name}}`, 'g'), value);
});

Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/cme-form-view/cme-form-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export class FormView extends connect(store)(LitElement) {

formBuilder.formItemChangeHandler = this._handleFormItemChange;
formBuilder.tokens = this._tokens;
formBuilder.tokenValues = this._tokenValues;

const formElements = formBuilder.build();

Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/cme-settings-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ export class SettingsContent extends connect(store)(LitElement) {
<cme-token-item-edit
data-index="${i}"
.token="${t}"
.tokens="${this._tokens}"
slot="body"
@save="${this._onTokenSave}"
@delete="${this._onTokenDelete}"
Expand Down
142 changes: 142 additions & 0 deletions frontend/src/components/cme-token-item-edit/cme-token-item-edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export class TokenItemEdit extends LitElement {
options,
lines,
value,
isConditionalToken,
linkedToken,
matchValue
} = val;

this._label = label ?? 'Untitled';
Expand All @@ -60,6 +63,9 @@ export class TokenItemEdit extends LitElement {
this._options = options ?? [];
this._lines = !isUndefined(lines) ? String(lines) : '';
this._value = value ?? '';
this._isConditionalToken = isConditionalToken ?? false;
this._linkedToken = linkedToken;
this._matchValue = matchValue ?? '';
}

get token(): Token {
Expand Down Expand Up @@ -125,12 +131,21 @@ export class TokenItemEdit extends LitElement {
retval.options = this._options;
}

if (this._isConditionalToken) {
retval.isConditionalToken = true;
retval.linkedToken = this._linkedToken;
retval.matchValue = this._matchValue;
}

return retval;
}

@property({type: Boolean})
active = false;

@property({ type: Array })
tokens: Token[] = [];

@state()
private _label = '';

Expand Down Expand Up @@ -182,9 +197,22 @@ export class TokenItemEdit extends LitElement {
@state()
private _value = '';

@state()
private _isConditionalToken = false;

@state()
private _linkedToken?: Token;

@state()
private _matchValue = '';

@state()
private _isOptionsWindowVisible = false;

get tokenOptions() {
return this.tokens?.filter((t) => t.name !== this._name) ?? [];
}

private _onNameChange(ev: CustomEvent) {
this._name = ev.detail;
}
Expand Down Expand Up @@ -259,6 +287,30 @@ export class TokenItemEdit extends LitElement {
this._options = ev.detail;
}

private _onIsConditionalTokenChange(ev: CustomEvent) {
this._isConditionalToken = ev.detail.checked;
if (!ev.detail.checked) {
this._linkedToken = undefined;
this._matchValue = '';
}
}

private _onLinkedTokenChange(ev: CustomEvent) {
const val = (ev.detail.value as string);

this._linkedToken = this.tokenOptions.find((t) => t.name === val);
this._matchValue = '';
}

private _onMatchValueChange(ev: CustomEvent) {
this._matchValue = ev.detail.value as string;
}

private _onMatchValueEnumChange(ev: CustomEvent) {
const valueLabel = ev.detail.value as string;
this._matchValue = this._linkedToken?.options?.find((o) => o.label === valueLabel)?.value as string;
}

private _onEditClick() {
this.active = true;
}
Expand Down Expand Up @@ -646,6 +698,93 @@ export class TokenItemEdit extends LitElement {
</div>
`;

const isConditionalTokenWidget = html`
<vscode-form-group class="${classMap({ disabled: !this.tokenOptions?.length })}">
<vscode-label for="isConditionalToken">Conditional Token</vscode-label>
<vscode-checkbox
id="isConditionalToken"
name="flags"
value="isConditionalToken"
?checked="${this._isConditionalToken}"
@vsc-change="${this._onIsConditionalTokenChange}"
></vscode-checkbox>
</vscode-form-group>
`;

const linkedTokenWidget = html`
<vscode-form-group variant="horizontal">
<vscode-label for="linkedToken" required>Linked Token</vscode-label>
<vscode-single-select
id="linkedToken"
name="linkedToken"
combobox
@vsc-change="${this._onLinkedTokenChange}"
>
<vscode-option hidden ?selected="true"> </vscode-option>
${this.tokenOptions.map(token => html`
<vscode-option ?selected="${this._linkedToken?.name === token.name}">
${token.name}
</vscode-option>
`)}
</vscode-single-select>
</vscode-form-group>
`;

const matchValueEnumWidget = html`
<vscode-form-group variant="horizontal">
<vscode-label for="matchValue">Match Value</vscode-label>
<vscode-single-select
id="matchValue"
name="matchValue"
@vsc-change="${this._onMatchValueEnumChange}"
>
${this._linkedToken?.options?.map(option => html`
<vscode-option ?selected="${this._matchValue === option.value}"
>${option.label}</vscode-option
>
`)}
</vscode-single-select>
</vscode-form-group>
`;

const matchValueTextWidget = html`
<vscode-form-group>
<vscode-label for="matchValue">Match Value</vscode-label>
<vscode-inputbox
value="${this._matchValue}"
id="matchValue"
name="matchValue"
@vsc-input="${this._onMatchValueChange}"
></vscode-inputbox>
</vscode-form-group>
`;

const _matchValueBooleanWidget = html`
<vscode-form-group variant="horizontal">
<vscode-label for="matchValue">Match Value</vscode-label>
<vscode-single-select
id="matchValue"
name="matchValue"
@vsc-change="${this._onMatchValueChange}"
>
<vscode-option ?selected="${this._matchValue === 'true'}"
>true</vscode-option
>
<vscode-option ?selected="${this._matchValue === 'false'}"
>false</vscode-option
>
</vscode-single-select>
</vscode-form-group>
`;

const _matchValueWidget = !this._isConditionalToken || !this._linkedToken
? nothing
: this._linkedToken.type === 'boolean'
? _matchValueBooleanWidget
: this._linkedToken.type === 'enum'
? matchValueEnumWidget
: matchValueTextWidget;

const activeView = html`
<div>
<vscode-form-container id="form" responsive>
Expand All @@ -654,6 +793,9 @@ export class TokenItemEdit extends LitElement {
${multilineWidget} ${monospaceWidget} ${linesWidget} ${maxLinesWidget}
${maxLengthWidget} ${maxLineLengthWidget} ${multipleWidget} ${separatorWidget}
${comboboxWidget} ${optionsWidget}
${isConditionalTokenWidget}
${this._isConditionalToken ? linkedTokenWidget : nothing}
${_matchValueWidget}
${this._isOptionsWindowVisible ? optionsWindow : nothing}
<vscode-form-group>
<vscode-button @click="${this._onSaveClick}">Save</vscode-button>
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ declare global {
separator?: string;
prefix?: string;
suffix?: string;
isConditionalToken?: boolean;
linkedToken?: Token;
matchValue?: string;
}

type DefaultViewConfig = 'text' | 'form';
Expand Down
Loading