()
- openData = false
-
- get config() {
- return OPEN_DATA_LICENSES
+ get isOpenDataLicense(): boolean {
+ return !!this.value.find(
+ (constraint) => constraint.text === OPEN_DATA_LICENSE
+ )
}
ngOnChanges() {
- if (this.value && this.value.length > 0) {
- this.openData = this.config.includes(this.value[0].text)
- } else {
- this.openData = false
- }
- this.openDataChange.emit(this.openData)
+ this.openDataChange.emit(this.isOpenDataLicense)
}
onOpenDataToggled(openData: boolean) {
this.openDataChange.emit(openData)
if (openData) {
- this.valueChange.emit([{ text: this.config[0] }])
+ this.valueChange.emit([
+ {
+ text: OPEN_DATA_LICENSE,
+ },
+ ])
+ } else {
+ this.valueChange.emit(
+ this.value.filter((constraint) => constraint.text !== OPEN_DATA_LICENSE)
+ )
}
}
}
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
index ffa4569b7f..60344f8c67 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html
@@ -3,7 +3,7 @@
-->
@@ -92,10 +92,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
index f49da4237b..79167142ed 100644
--- a/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
+++ b/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts
@@ -27,7 +27,11 @@ import {
FormFieldLicenseComponent,
FormFieldTemporalExtentsComponent,
} from '.'
-import { FieldModelSpecifier, FormFieldConfig } from '../../../models'
+import {
+ FieldModelSpecifier,
+ FormFieldComponentName,
+ FormFieldConfig,
+} from '../../../models'
import { FormFieldArrayComponent } from './form-field-array/form-field-array.component'
import { FormFieldContactsForResourceComponent } from './form-field-contacts-for-resource/form-field-contacts-for-resource.component'
import { FormFieldContactsComponent } from './form-field-contacts/form-field-contacts.component'
@@ -42,6 +46,8 @@ import { FormFieldRichComponent } from './form-field-rich/form-field-rich.compon
import { FormFieldSimpleComponent } from './form-field-simple/form-field-simple.component'
import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/form-field-spatial-extent.component'
import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
+import { FormFieldConstraintsShortcutsComponent } from './form-field-constraints-shortcuts/form-field-constraints-shortcuts.component'
+import { FormFieldConstraintsComponent } from './form-field-constraints/form-field-constraints.component'
@Component({
selector: 'gn-ui-form-field',
@@ -72,27 +78,41 @@ import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency
FormFieldOnlineResourcesComponent,
FormFieldOnlineLinkResourcesComponent,
FormFieldContactsComponent,
+ FormFieldConstraintsComponent,
+ FormFieldConstraintsShortcutsComponent,
],
})
export class FormFieldComponent {
@Input() uniqueIdentifier: string
@Input() model: CatalogRecordKeys
@Input() modelSpecifier: FieldModelSpecifier
+ @Input() componentName: FormFieldComponentName
+
@Input() config: FormFieldConfig
@Input() value: unknown
@Output() valueChange: EventEmitter = new EventEmitter()
@ViewChild('titleInput') titleInput: ElementRef
+ isOpenData = false
- isHidden = false
+ toggleIsOpenData(event: boolean) {
+ this.isOpenData = event
+ }
focusTitleInput() {
this.titleInput.nativeElement.children[0].focus()
}
get withoutWrapper() {
- return this.model === 'title' || this.model === 'abstract'
+ return (
+ this.model === 'title' ||
+ this.model === 'abstract' ||
+ this.model === 'legalConstraints' ||
+ this.model === 'securityConstraints' ||
+ this.model === 'otherConstraints' ||
+ this.componentName === 'form-field-constraints-shortcuts'
+ )
}
get valueAsString() {
diff --git a/libs/feature/editor/src/lib/components/record-form/record-form.component.html b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
index 84e01238b0..81694a100b 100644
--- a/libs/feature/editor/src/lib/components/record-form/record-form.component.html
+++ b/libs/feature/editor/src/lib/components/record-form/record-form.component.html
@@ -45,6 +45,7 @@
[modelSpecifier]="field.config.modelSpecifier!"
[config]="field.config.formFieldConfig"
[value]="field.value"
+ [componentName]="field.config.componentName"
(valueChange)="
handleFieldValueChange(field.config.model!, $event)
"
diff --git a/libs/feature/editor/src/lib/fields.config.ts b/libs/feature/editor/src/lib/fields.config.ts
index e787e34bc0..d64e1eb89f 100644
--- a/libs/feature/editor/src/lib/fields.config.ts
+++ b/libs/feature/editor/src/lib/fields.config.ts
@@ -26,6 +26,32 @@ export const RECORD_UNIQUE_IDENTIFIER_FIELD: EditorField = {
hidden: true,
}
+export const CONSTRAINTS_SHORTCUTS: EditorField = {
+ componentName: 'form-field-constraints-shortcuts',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.field.constraintsShortcuts'),
+ },
+}
+
+export const LEGAL_CONSTRAINTS_FIELD: EditorField = {
+ model: 'legalConstraints',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.field.legalConstraints'),
+ },
+}
+export const SECURITY_CONSTRAINTS_FIELD: EditorField = {
+ model: 'securityConstraints',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.field.securityConstraints'),
+ },
+}
+export const OTHER_CONSTRAINTS_FIELD: EditorField = {
+ model: 'otherConstraints',
+ formFieldConfig: {
+ labelKey: marker('editor.record.form.field.otherConstraints'),
+ },
+}
+
export const RECORD_LICENSE_FIELD: EditorField = {
model: 'licenses',
formFieldConfig: {
@@ -191,7 +217,13 @@ export const CLASSIFICATION_SECTION: EditorSection = {
export const USE_AND_ACCESS_CONDITIONS_SECTION: EditorSection = {
labelKey: marker('editor.record.form.section.useAndAccessConditions.label'),
hidden: false,
- fields: [RECORD_LICENSE_FIELD],
+ fields: [
+ RECORD_LICENSE_FIELD,
+ CONSTRAINTS_SHORTCUTS,
+ LEGAL_CONSTRAINTS_FIELD,
+ SECURITY_CONSTRAINTS_FIELD,
+ OTHER_CONSTRAINTS_FIELD,
+ ],
}
export const DATA_MANAGERS_SECTION: EditorSection = {
@@ -240,14 +272,30 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
*************** LICENSES **************
************************************************************
*/
-export const OPEN_DATA_LICENSES: string[] = [
+export const AVAILABLE_LICENSES: string[] = [
+ 'cc-by',
+ 'cc-by-sa',
+ 'cc-zero',
'etalab',
'etalab-v2',
'odbl',
'odc-by',
'pddl',
+ 'unknown',
]
+export const OPEN_DATA_LICENSE = 'etalab'
+
+marker('editor.record.form.license.cc-by')
+marker('editor.record.form.license.cc-by-sa')
+marker('editor.record.form.license.cc-zero')
+marker('editor.record.form.license.etalab')
+marker('editor.record.form.license.etalab-v2')
+marker('editor.record.form.license.odbl')
+marker('editor.record.form.license.odc-by')
+marker('editor.record.form.license.pddl')
+marker('editor.record.form.license.unknown')
+
export const MAX_UPLOAD_SIZE_MB = 10
/************************************************************
*************** SPATIAL SCOPE ************
diff --git a/libs/feature/editor/src/lib/models/editor-config.model.ts b/libs/feature/editor/src/lib/models/editor-config.model.ts
index 90ba1f2097..d4fcc83afe 100644
--- a/libs/feature/editor/src/lib/models/editor-config.model.ts
+++ b/libs/feature/editor/src/lib/models/editor-config.model.ts
@@ -23,14 +23,21 @@ export type FieldModelSpecifier =
| OnlineLinkResourceSpecifier
| DatasetDistributionsSpecifier
-export interface EditorField {
- // configuration of the form field used as presentation
- formFieldConfig: FormFieldConfig
+export type FormFieldComponentName = 'form-field-constraints-shortcuts'
+export interface EditorFieldIdentification {
// name of the target field in the record; will not change the record directly if not defined
model?: CatalogRecordKeys
modelSpecifier?: FieldModelSpecifier
+ // if no model is given, a component can be shown instead
+ componentName?: FormFieldComponentName
+}
+
+export interface EditorField extends EditorFieldIdentification {
+ // configuration of the form field used as presentation
+ formFieldConfig: FormFieldConfig
+
// grid column span; if unspecified, full width will be used
gridColumnSpan?: number
diff --git a/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.html b/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.html
index 02f47bcf0b..66d6a41b88 100644
--- a/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.html
+++ b/libs/ui/inputs/src/lib/check-toggle/check-toggle.component.html
@@ -1,4 +1,7 @@
-
diff --git a/libs/ui/inputs/src/lib/file-input/file-input.component.ts b/libs/ui/inputs/src/lib/file-input/file-input.component.ts
index 88efe3b12f..225b1e1f3b 100644
--- a/libs/ui/inputs/src/lib/file-input/file-input.component.ts
+++ b/libs/ui/inputs/src/lib/file-input/file-input.component.ts
@@ -89,7 +89,8 @@ export class FileInputComponent {
this.handleDropFiles(Array.from((event.target as HTMLInputElement).files))
}
- handleUrlChange(url: string) {
+ handleUrlChange(url: string | null) {
+ if (!url) return
this.urlChange.emit(url)
}
diff --git a/libs/ui/inputs/src/lib/image-input/image-input.component.html b/libs/ui/inputs/src/lib/image-input/image-input.component.html
index c943a01a9d..f17df3c221 100644
--- a/libs/ui/inputs/src/lib/image-input/image-input.component.html
+++ b/libs/ui/inputs/src/lib/image-input/image-input.component.html
@@ -140,7 +140,7 @@
diff --git a/libs/ui/inputs/src/lib/url-input/url-input.component.html b/libs/ui/inputs/src/lib/url-input/url-input.component.html
index 87f9a3879e..5d31d70a4e 100644
--- a/libs/ui/inputs/src/lib/url-input/url-input.component.html
+++ b/libs/ui/inputs/src/lib/url-input/url-input.component.html
@@ -4,9 +4,9 @@
class="gn-ui-text-input px-[var(--text-padding)]"
[ngClass]="extraClass"
type="url"
- [value]="value"
- (input)="handleInput()"
- (keydown.enter)="handleChange(input)"
+ [value]="inputValue"
+ (input)="handleInput($event)"
+ (keydown.enter)="handleUpload(input)"
[placeholder]="placeholder"
[attr.aria-label]="placeholder"
[disabled]="disabled"
@@ -21,14 +21,11 @@
diff --git a/libs/ui/inputs/src/lib/url-input/url-input.component.spec.ts b/libs/ui/inputs/src/lib/url-input/url-input.component.spec.ts
index ba96445896..722e8c6b5b 100644
--- a/libs/ui/inputs/src/lib/url-input/url-input.component.spec.ts
+++ b/libs/ui/inputs/src/lib/url-input/url-input.component.spec.ts
@@ -34,72 +34,138 @@ describe('UrlInputComponent', () => {
inputEl = fixture.nativeElement.querySelector('input')
button = fixture.debugElement.query(By.directive(ButtonComponent))
})
- it('emits the value on a button click event', () => {
- let emitted
- component.valueChange.subscribe((v) => (emitted = v))
- inputEl.value = 'Aaabcd'
- button.triggerEventHandler('buttonClick', null)
- expect(emitted).toBe('Aaabcd')
- })
- it('does not the value on an input event', () => {
- let emitted = null
- component.valueChange.subscribe((v) => (emitted = v))
- inputEl.value = 'Aaabcd'
- inputEl.dispatchEvent(new Event('input'))
- expect(emitted).toBe(null)
- })
- it('emits the value on a enter press event', () => {
- let emitted
- component.valueChange.subscribe((v) => (emitted = v))
- inputEl.value = 'Aaabcd'
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- expect(emitted).toBe('Aaabcd')
+
+ it('shows an empty input if given a nullish url', () => {
+ component.value = null
+ fixture.detectChanges()
+ expect(inputEl.value).toEqual('')
})
- it('can emit multiple equal values', () => {
- let emittedCount = 0
- component.valueChange.subscribe(() => emittedCount++)
- inputEl.value = 'http://bla'
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- inputEl.value = 'http://bla'
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- inputEl.value = 'http://bla'
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- expect(emittedCount).toBe(3)
+
+ describe('uploadClick', () => {
+ it('emits the value on a button click event', () => {
+ let emitted
+ component.uploadClick.subscribe((v) => (emitted = v))
+ inputEl.value = 'http://aaa.com/bcd'
+ button.triggerEventHandler('buttonClick', null)
+ expect(emitted).toBe('http://aaa.com/bcd')
+ })
+ it('does not emit the value on an input event', () => {
+ let emitted = null
+ component.uploadClick.subscribe((v) => (emitted = v))
+ inputEl.value = 'http://aaa.com/bcd'
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emitted).toBe(null)
+ })
+ it('emits the value on a enter press event', () => {
+ let emitted
+ component.uploadClick.subscribe((v) => (emitted = v))
+ inputEl.value = 'http://aaa.com/bcd'
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ expect(emitted).toBe('http://aaa.com/bcd')
+ })
+ it('can emit multiple equal values', () => {
+ let emittedCount = 0
+ component.uploadClick.subscribe(() => emittedCount++)
+ inputEl.value = 'http://bla'
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ inputEl.value = 'http://bla'
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ inputEl.value = 'http://bla'
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ expect(emittedCount).toBe(3)
+ })
+ it('does not emit empty values', () => {
+ let emitted = null
+ component.uploadClick.subscribe((v) => (emitted = v))
+ inputEl.value = ''
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ expect(emitted).toBe(null)
+ inputEl.value = 'http://bla'
+ inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
+ expect(emitted).toBe('http://bla')
+ })
})
- it('does not emit empty values', () => {
- let emitted = null
- component.valueChange.subscribe((v) => (emitted = v))
- inputEl.value = ''
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- expect(emitted).toBe(null)
- inputEl.value = 'http://bla'
- inputEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'enter' }))
- expect(emitted).toBe('http://bla')
+ describe('valueChange', () => {
+ it('does not the value on a button click event', () => {
+ let emitted = null
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = 'http://aaa.com/bcd'
+ button.triggerEventHandler('buttonClick', null)
+ expect(emitted).toBe(null)
+ })
+ it('emits the value on an input event', () => {
+ let emitted = null
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = 'http://aaa.com/bcd'
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emitted).toBe('http://aaa.com/bcd')
+ })
+ it('does not emit the value if not a valid URL', () => {
+ let emitted = null
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = 'blargz'
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emitted).toBe(null)
+ })
+ it('emits null if the input is cleared', () => {
+ let emitted = undefined
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = ''
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emitted).toBe(null)
+ })
})
describe('button', () => {
it('is disabled if parent set it as disabled', () => {
component.disabled = true
inputEl.value = ''
+ inputEl.dispatchEvent(new Event('input'))
fixture.detectChanges()
expect(button.componentInstance.disabled).toBe(true)
})
it('is disabled if value is empty', () => {
inputEl.value = ''
+ inputEl.dispatchEvent(new Event('input'))
fixture.detectChanges()
expect(button.componentInstance.disabled).toBe(true)
})
- it('is disabled if asking for parseable URL and value is not an URL', () => {
- component.urlCanParse = true
+ it('is disabled if value is not an URL', () => {
inputEl.value = 'hello'
+ inputEl.dispatchEvent(new Event('input'))
fixture.detectChanges()
expect(button.componentInstance.disabled).toBe(true)
})
it('is not disabled otherwise', () => {
- inputEl.value = 'hello'
+ inputEl.value = 'http://hello.org'
+ inputEl.dispatchEvent(new Event('input'))
fixture.detectChanges()
expect(button.componentInstance.disabled).toBeFalsy()
})
})
+
+ describe('input value', () => {
+ it('changes if the component input resolves to a different url', () => {
+ inputEl.value = 'http://aaa.com/1234'
+ inputEl.dispatchEvent(new Event('input'))
+ component.value = 'http://aaa.com/bcd'
+ fixture.detectChanges()
+ expect(inputEl.value).toEqual('http://aaa.com/bcd')
+ })
+ it('does not change if the component input is different that the current value but resolves to the same url', () => {
+ inputEl.value = 'http://aaa.com/1234 5678'
+ inputEl.dispatchEvent(new Event('input'))
+ component.value = 'http://aaa.com/1234%205678'
+ fixture.detectChanges()
+ expect(inputEl.value).toEqual('http://aaa.com/1234 5678')
+ })
+ it('does not change if both the component input and the current input are not valid urls', () => {
+ inputEl.value = 'blargz'
+ inputEl.dispatchEvent(new Event('input'))
+ component.value = undefined
+ fixture.detectChanges()
+ expect(inputEl.value).toEqual('blargz')
+ })
+ })
})
})
diff --git a/libs/ui/inputs/src/lib/url-input/url-input.component.stories.ts b/libs/ui/inputs/src/lib/url-input/url-input.component.stories.ts
index 47e8e6be1e..c19b4e7de5 100644
--- a/libs/ui/inputs/src/lib/url-input/url-input.component.stories.ts
+++ b/libs/ui/inputs/src/lib/url-input/url-input.component.stories.ts
@@ -5,37 +5,54 @@ export default {
title: 'Inputs/UrlInputComponent',
component: UrlInputComponent,
decorators: [],
+ argTypes: {
+ valueChange: {
+ action: 'valueChange',
+ },
+ uploadClick: {
+ action: 'uploadClick',
+ },
+ },
} as Meta
export const Primary: StoryObj = {
args: {
- value: '',
+ value: 'http://aaa.org/bbb',
+ placeholder: 'write a URL here',
disabled: false,
- },
- argTypes: {
- valueChange: {
- action: 'valueChange',
- },
+ showUploadButton: true,
},
}
export const WithCustomStyle: StoryObj = {
args: {
- value: '',
+ value: 'http://aaa.org/bbb',
disabled: false,
placeholder: 'https://mysite.org/file',
},
- argTypes: {
- valueChange: {
- action: 'valueChange',
- },
- },
render: (args) => ({
props: args,
template: `
-
+
`,
}),
}
+
+export const WithoutUploadButton: StoryObj = {
+ args: {
+ value: null,
+ disabled: false,
+ placeholder: 'https://mysite.org/file',
+ showUploadButton: false,
+ },
+ render: (args) => ({
+ props: args,
+ template: `
+
+ `,
+ }),
+}
diff --git a/libs/ui/inputs/src/lib/url-input/url-input.component.ts b/libs/ui/inputs/src/lib/url-input/url-input.component.ts
index 6a7a4a609b..d725c4bc1b 100644
--- a/libs/ui/inputs/src/lib/url-input/url-input.component.ts
+++ b/libs/ui/inputs/src/lib/url-input/url-input.component.ts
@@ -1,15 +1,13 @@
import {
+ ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
+ EventEmitter,
Input,
- OnChanges,
Output,
- SimpleChanges,
} from '@angular/core'
import { CommonModule } from '@angular/common'
import { ButtonComponent } from '../button/button.component'
-import { filter } from 'rxjs/operators'
-import { Subject } from 'rxjs'
import {
NgIconComponent,
provideIcons,
@@ -29,34 +27,54 @@ import { iconoirArrowUp, iconoirLink } from '@ng-icons/iconoir'
size: '1.5em',
}),
],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class UrlInputComponent implements OnChanges {
- @Input() value = ''
+export class UrlInputComponent {
+ @Input() set value(v: string) {
+ // we're making sure to only update the input if the URL representation of it has changed; otherwise we keep it identical
+ // to avoid glitches when starting to write a URL and having some characters added/replaced automatically
+ if (!v || !this.isValidUrl(v)) return
+ if (
+ this.isValidUrl(this.inputValue) &&
+ new URL(v).toString() === new URL(this.inputValue).toString()
+ )
+ return
+ this.inputValue = v
+ this.cd.markForCheck()
+ }
@Input() extraClass = ''
@Input() placeholder = 'https://'
@Input() disabled: boolean
- @Input() urlCanParse?: boolean
- rawChange = new Subject()
- @Output() valueChange = this.rawChange.pipe(filter((v) => !!v))
+ @Input() showUploadButton = true
+
+ /**
+ * This will emit null if the field is emptied
+ */
+ @Output() valueChange = new EventEmitter()
+ @Output() uploadClick = new EventEmitter()
+
+ inputValue = ''
constructor(private cd: ChangeDetectorRef) {}
- ngOnChanges(changes: SimpleChanges): void {
- if (changes.value) {
- console.log('changes.value', changes.value)
+ handleInput(event: Event) {
+ const value = (event.target as HTMLInputElement).value
+ this.inputValue = value
+ if (!value || !this.isValidUrl(value)) {
+ this.valueChange.next(null)
+ return
}
- }
-
- handleInput() {
this.cd.markForCheck()
+ this.valueChange.next(value)
}
- handleChange(element: HTMLInputElement) {
+ handleUpload(element: HTMLInputElement) {
const value = element.value
- this.rawChange.next(value)
+ if (!value || !this.isValidUrl(value)) return
+ this.uploadClick.next(value)
}
- URLcanParse(url: string): boolean {
+ isValidUrl(url: string): boolean {
try {
new URL(url)
return true
diff --git a/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html b/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html
index cf21fabf64..1004d61e6d 100644
--- a/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html
+++ b/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html
@@ -1,6 +1,6 @@
-
{{ label }}
+
{{ label }}