Change all usage of op-form-field` to spot-form-field

* `op-form-field` was used both as a BEM block as well as a component.
  This commit removes usages of `op-form-field` in both instances.
* It changes all usages of `opFormBinding` to `spotFormBinding`.
* It removes all old files related to `op-form-field`.
pull/11330/head
Benjamin Bädorf 3 years ago
parent c5313bee41
commit c1d0e02629
No known key found for this signature in database
GPG Key ID: 069CA2D117AB5CCF
  1. 2
      frontend/src/app/features/invite-user-modal/invite-user.component.sass
  2. 6
      frontend/src/app/features/invite-user-modal/message/message.component.html
  3. 2
      frontend/src/app/features/invite-user-modal/principal/principal-search.component.ts
  4. 10
      frontend/src/app/features/invite-user-modal/principal/principal.component.html
  5. 18
      frontend/src/app/features/invite-user-modal/project-selection/project-selection.component.html
  6. 2
      frontend/src/app/features/invite-user-modal/role/role-search.component.ts
  7. 12
      frontend/src/app/features/invite-user-modal/role/role.component.html
  8. 16
      frontend/src/app/features/invite-user-modal/summary/summary.component.html
  9. 4
      frontend/src/app/features/projects/components/new-project/new-project.component.html
  10. 8
      frontend/src/app/shared/components/dynamic-forms/components/dynamic-field-wrapper/dynamic-field-wrapper.component.html
  11. 24
      frontend/src/app/shared/components/forms/checkbox-field/checkbox-field.component.html
  12. 4
      frontend/src/app/shared/components/forms/checkbox-field/checkbox-field.component.ts
  13. 24
      frontend/src/app/shared/components/forms/form-field/form-binding.directive.ts
  14. 7
      frontend/src/app/shared/components/forms/form-field/form-field.children.sass
  15. 56
      frontend/src/app/shared/components/forms/form-field/form-field.component.html
  16. 78
      frontend/src/app/shared/components/forms/form-field/form-field.component.ts
  17. 53
      frontend/src/app/shared/components/forms/form-field/form-field.sass
  18. 2
      frontend/src/app/shared/components/forms/form.sass
  19. 1
      frontend/src/app/shared/components/forms/index.sass
  20. 6
      frontend/src/app/shared/shared.module.ts
  21. 22
      frontend/src/app/spot/components/form-field/form-field.component.html
  22. 10
      frontend/src/app/spot/components/form-field/form-field.component.ts
  23. 1
      frontend/src/app/spot/styles/sass/components/form-field.sass
  24. 20
      modules/github_integration/frontend/module/git-actions-menu/git-actions-menu.template.html
  25. 2
      spec/features/projects/attribute_help_texts_spec.rb
  26. 4
      spec/support/components/users/invite_user_modal.rb
  27. 2
      spec/support/form_fields/form_field.rb

@ -6,5 +6,5 @@
height: 100% height: 100%
flex-grow: 1 flex-grow: 1
.op-form-field + .op-form-field .spot-form-field + .spot-form-field
margin-top: 1rem margin-top: 1rem

@ -7,8 +7,8 @@
<div class="spot-divider"></div> <div class="spot-divider"></div>
<div class="spot-modal--body op-form"> <div class="spot-modal--body op-form">
<op-form-field [label]="text.label"> <spot-form-field [label]="text.label">
<p class="op-form-field--description" slot="description"> <p class="spot-form-field--description" slot="description">
{{ text.description() }} {{ text.description() }}
</p> </p>
<textarea <textarea
@ -18,7 +18,7 @@
#input #input
autofocus> autofocus>
</textarea> </textarea>
</op-form-field> </spot-form-field>
</div> </div>
<div class="spot-modal--footer spot-action-bar"> <div class="spot-modal--footer spot-action-bar">

@ -42,7 +42,7 @@ interface NgSelectPrincipalOption {
templateUrl: './principal-search.component.html', templateUrl: './principal-search.component.html',
}) })
export class PrincipalSearchComponent extends UntilDestroyedMixin implements OnInit { export class PrincipalSearchComponent extends UntilDestroyedMixin implements OnInit {
@Input('opFormBinding') principalControl:FormControl; @Input('spotFormBinding') principalControl:FormControl;
@Input() type:PrincipalType; @Input() type:PrincipalType;

@ -6,14 +6,14 @@
<div class="spot-divider"></div> <div class="spot-divider"></div>
<div class="spot-modal--body op-form"> <div class="spot-modal--body spot-container">
<op-form-field <spot-form-field
[label]="textLabel" [label]="textLabel"
required required
> >
<op-ium-principal-search <op-ium-principal-search
*ngIf="!(hasPrincipalSelected && isNewPrincipal)" *ngIf="!(hasPrincipalSelected && isNewPrincipal)"
[opFormBinding]="principalControl" [spotFormBinding]="principalControl"
[type]="type" [type]="type"
[project]="project" [project]="project"
slot="input" slot="input"
@ -46,12 +46,12 @@
<div <div
slot="errors" slot="errors"
class="op-form-field--error" class="spot-form-field--error"
*ngIf="principalControl?.touched && principalControl?.invalid" *ngIf="principalControl?.touched && principalControl?.invalid"
> >
{{ text.required[type] }} {{ text.required[type] }}
</div> </div>
</op-form-field> </spot-form-field>
<op-dynamic-form <op-dynamic-form
*ngIf="isNewPrincipal && type === PrincipalType.User && userDynamicFieldConfig.schema" *ngIf="isNewPrincipal && type === PrincipalType.User && userDynamicFieldConfig.schema"

@ -6,8 +6,8 @@
<div class="spot-divider"></div> <div class="spot-divider"></div>
<div class="spot-modal--body op-form"> <div class="spot-modal--body spot-container">
<op-form-field <spot-form-field
[label]="text.project.label" [label]="text.project.label"
required required
> >
@ -28,7 +28,7 @@
<div <div
slot="errors" slot="errors"
class="op-form-field--error" class="spot-form-field--error"
*ngIf="projectControl.errors?.required" *ngIf="projectControl.errors?.required"
> >
{{ text.project.required }} {{ text.project.required }}
@ -36,14 +36,14 @@
<div <div
slot="errors" slot="errors"
class="op-form-field--error" class="spot-form-field--error"
*ngIf="projectControl.errors?.lackingPermission" *ngIf="projectControl.errors?.lackingPermission"
> >
{{ text.project.lackingPermission }} {{ text.project.lackingPermission }}
</div> </div>
</op-form-field> </spot-form-field>
<op-form-field> <spot-form-field>
<op-option-list <op-option-list
[options]="typeOptions" [options]="typeOptions"
formControlName="type" formControlName="type"
@ -52,14 +52,14 @@
<div <div
*ngIf="projectAndTypeForm?.dirty && typeControl?.invalid" *ngIf="projectAndTypeForm?.dirty && typeControl?.invalid"
class="op-form-field--errors" class="spot-form-field--errors"
slot="errors" slot="errors"
> >
<div class="op-form-field--error"> <div class="spot-form-field--error">
{{ text.type.required }} {{ text.type.required }}
</div> </div>
</div> </div>
</op-form-field> </spot-form-field>
</div> </div>
<div class="spot-modal--footer spot-action-bar"> <div class="spot-modal--footer spot-action-bar">

@ -19,7 +19,7 @@ import { ApiV3FilterBuilder } from 'core-app/shared/helpers/api-v3/api-v3-filter
templateUrl: './role-search.component.html', templateUrl: './role-search.component.html',
}) })
export class RoleSearchComponent extends UntilDestroyedMixin implements OnInit { export class RoleSearchComponent extends UntilDestroyedMixin implements OnInit {
@Input('opFormBinding') roleControl:FormControl; @Input('spotFormBinding') roleControl:FormControl;
public input$ = new Subject<string|null>(); public input$ = new Subject<string|null>();

@ -6,29 +6,29 @@
<div class="spot-divider"></div> <div class="spot-divider"></div>
<div class="spot-modal--body op-form"> <div class="spot-modal--body spot-container">
<op-form-field <spot-form-field
[label]="text.label()" [label]="text.label()"
required required
> >
<p <p
class="op-form-field--description" class="spot-form-field--description"
slot="description" slot="description"
[innerHtml]="text.description()" [innerHtml]="text.description()"
></p> ></p>
<op-ium-role-search <op-ium-role-search
[opFormBinding]="roleControl" [spotFormBinding]="roleControl"
slot="input" slot="input"
></op-ium-role-search> ></op-ium-role-search>
<div <div
slot="errors" slot="errors"
class="op-form-field--error" class="spot-form-field--error"
*ngIf="roleControl?.touched && roleControl?.invalid" *ngIf="roleControl?.touched && roleControl?.invalid"
> >
{{ text.required }} {{ text.required }}
</div> </div>
</op-form-field> </spot-form-field>
</div> </div>
<div class="spot-modal--footer spot-action-bar"> <div class="spot-modal--footer spot-action-bar">

@ -7,24 +7,24 @@
<div class="spot-divider"></div> <div class="spot-divider"></div>
<div class="spot-modal--body op-form"> <div class="spot-modal--body spot-container">
<op-form-field [label]="text.projectLabel"> <op-form-field [label]="text.projectLabel">
<p slot="input">{{ project.name }}</p> <p slot="input">{{ project.name }}</p>
</op-form-field> </spot-form-field>
<div class="op-ium-summary__row"> <div class="op-ium-summary__row">
<op-form-field [label]="text.principalLabel[type]"> <spot-form-field [label]="text.principalLabel[type]">
<p slot="input">{{ principal?.name }}</p> <p slot="input">{{ principal?.name }}</p>
</op-form-field> </spot-form-field>
<op-form-field [label]="text.roleLabel()"> <spot-form-field [label]="text.roleLabel()">
<p slot="input">{{ role.name }}</p> <p slot="input">{{ role.name }}</p>
</op-form-field> </spot-form-field>
</div> </div>
<op-form-field <spot-form-field
[label]="text.messageLabel" [label]="text.messageLabel"
*ngIf="type !== PrincipalType.Placeholder && message" *ngIf="type !== PrincipalType.Placeholder && message"
> >
<p slot="input" class="op-ium-summary-message">{{ message }}</p> <p slot="input" class="op-ium-summary-message">{{ message }}</p>
</op-form-field> </spot-form-field>
</div> </div>
<div class="spot-modal--footer spot-action-bar"> <div class="spot-modal--footer spot-action-bar">

@ -3,7 +3,7 @@
[formGroup]="templateForm" [formGroup]="templateForm"
> >
<div [ngClass]="{ 'op-highlighted-input': true, 'op-highlighted-input_active': !!templateControl?.value }"> <div [ngClass]="{ 'op-highlighted-input': true, 'op-highlighted-input_active': !!templateControl?.value }">
<op-form-field <spot-form-field
[label]="text.use_template" [label]="text.use_template"
data-qa-field-name="use_template" data-qa-field-name="use_template"
> >
@ -16,7 +16,7 @@
slot="input" slot="input"
> >
</ng-select> </ng-select>
</op-form-field> </spot-form-field>
</div> </div>
</form> </form>

@ -1,4 +1,4 @@
<op-form-field <spot-form-field
*ngIf="field.type !== 'booleanInput'" *ngIf="field.type !== 'booleanInput'"
[control]="field?.formControl" [control]="field?.formControl"
[label]="to?.label" [label]="to?.label"
@ -13,11 +13,11 @@
<ng-container #fieldComponent slot="input"></ng-container> <ng-container #fieldComponent slot="input"></ng-container>
<formly-validation-message <formly-validation-message
class="op-form-field--error" class="spot-form-field--error"
[field]="field" [field]="field"
slot="errors" slot="errors"
></formly-validation-message> ></formly-validation-message>
</op-form-field> </spot-form-field>
<op-checkbox-field <op-checkbox-field
*ngIf="field.type === 'booleanInput'" *ngIf="field.type === 'booleanInput'"
@ -33,7 +33,7 @@
<ng-container #fieldComponent slot="input"></ng-container> <ng-container #fieldComponent slot="input"></ng-container>
<formly-validation-message <formly-validation-message
class="op-form-field--error" class="spot-form-field--error"
[field]="field" [field]="field"
slot="errors" slot="errors"
></formly-validation-message> ></formly-validation-message>

@ -1,7 +1,7 @@
<ng-container *ngIf="!hidden"> <ng-container *ngIf="!hidden">
<label class="op-form-field--label-wrap op-checkbox-field--label-wrap"> <label class="spot-form-field--label-wrap op-checkbox-field--label-wrap">
<div <div
class="op-form-field--input op-checkbox-field--input" class="spot-form-field--input op-checkbox-field--input"
[attr.aria-describedby]="describedByID" [attr.aria-describedby]="describedByID"
> >
<ng-content select="[slot=input]"></ng-content> <ng-content select="[slot=input]"></ng-content>
@ -9,34 +9,30 @@
<div <div
*ngIf="label" *ngIf="label"
class="op-form-field--label op-checkbox-field--label" class="spot-form-field--label op-checkbox-field--label"
> >
<span <span
*ngIf="showErrorMessage" *ngIf="showErrorMessage"
class="Hidden for sighted" class="Hidden for sighted"
>Invalid</span> >Invalid</span>
{{ label }} {{ label }}
<span *ngIf="required" class="op-form-field--label-indicator">*</span> <span *ngIf="required" class="spot-form-field--label-indicator">*</span>
<attribute-help-text <attribute-help-text
[attribute]="helpTextAttribute" [attribute]="helpTextAttribute"
[attributeScope]="helpTextAttributeScope" [attributeScope]="helpTextAttributeScope"
></attribute-help-text> ></attribute-help-text>
</div> </div>
<div
class="op-form-field--description op-checkbox-field--description"
[id]="descriptionID"
>
<ng-content select="[slot=description]"></ng-content>
</div>
</label> </label>
<div class="op-form-field--help-text"> <div
<ng-content select="[slot=help-text]"></ng-content> class="spot-form-field--description"
[id]="descriptionID"
>
<ng-content select="[slot=description]"></ng-content>
</div> </div>
<div <div
class="op-form-field--errors" class="spot-form-field--errors"
*ngIf="showErrorMessage" *ngIf="showErrorMessage"
[id]="errorsID" [id]="errorsID"
> >

@ -16,11 +16,11 @@ import {
templateUrl: './checkbox-field.component.html', templateUrl: './checkbox-field.component.html',
}) })
export class OpCheckboxFieldComponent { export class OpCheckboxFieldComponent {
@HostBinding('class.op-form-field') className = true; @HostBinding('class.spot-form-field') className = true;
@HostBinding('class.op-checkbox-field') classNameCheckbox = true; @HostBinding('class.op-checkbox-field') classNameCheckbox = true;
@HostBinding('class.op-form-field_invalid') get errorClassName():boolean { @HostBinding('class.spot-form-field_invalid') get errorClassName():boolean {
return this.showErrorMessage; return this.showErrorMessage;
} }

@ -1,24 +0,0 @@
import { Directive, forwardRef, Input } from '@angular/core';
import {
FormArray, FormControl, FormGroup, NgControl,
} from '@angular/forms';
export const formControlBinding:any = {
provide: NgControl,
useExisting: forwardRef(() => OpFormBindingDirective),
};
@Directive({
selector: '[opFormBinding]',
providers: [formControlBinding],
exportAs: 'ngForm',
})
export class OpFormBindingDirective extends NgControl {
@Input('opFormBinding') form!:FormControl|FormGroup|FormArray;
get control():FormControl|FormGroup|FormArray {
return this.form;
}
viewToModelUpdate():void {}
}

@ -1,7 +0,0 @@
.op-form-field_invalid
.ng-select-container,
.op-input,
.op-option-list--item,
.document-editor__editable-container,
.ck.ck-toolbar
border-color: var(--content-form-error-color)

@ -1,56 +0,0 @@
<ng-container *ngIf="!hidden">
<label class="op-form-field--label-wrap">
<div class="op-form-field--label">
<span
*ngIf="showErrorMessage"
class="hidden-for-sighted"
>
{{ text.invalid }}
</span>
{{ label }}
<span *ngIf="required" class="op-form-field--label-indicator">*</span>
<attribute-help-text
[attribute]="helpTextAttribute"
[attributeScope]="helpTextAttributeScope"
></attribute-help-text>
</div>
<ng-container *ngIf="!noWrapLabel">
<ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
</ng-container>
</label>
<ng-container *ngIf="noWrapLabel">
<ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
</ng-container>
<div class="op-form-field--help-text">
<ng-content select="[slot=help-text]"></ng-content>
</div>
<div
class="op-form-field--errors"
*ngIf="showErrorMessage"
[id]="errorsID"
>
<ng-content select="[slot=errors]"></ng-content>
</div>
</ng-container>
<ng-template #inputTemplate>
<div
class="op-form-field--description"
[id]="descriptionID"
>
<ng-content select="[slot=description]"></ng-content>
</div>
<div
class="op-form-field--input"
[attr.aria-describedby]="describedByID"
>
<ng-content select="[slot=input]"></ng-content>
</div>
</ng-template>

@ -1,78 +0,0 @@
import {
Component, ContentChild, HostBinding, Input, Optional,
} from '@angular/core';
import { AbstractControl, FormGroupDirective, NgControl } from '@angular/forms';
import { I18nService } from 'core-app/core/i18n/i18n.service';
@Component({
selector: 'op-form-field',
templateUrl: './form-field.component.html',
})
export class OpFormFieldComponent {
@HostBinding('class.op-form-field') className = true;
@HostBinding('class.op-form-field_invalid') get errorClassName() {
return this.showErrorMessage;
}
@Input() label = '';
@Input() noWrapLabel = false;
@Input() required = false;
@Input() hidden = false;
@Input() showValidationErrorOn:'change' | 'blur' | 'submit' | 'never' = 'submit';
@Input() control?:AbstractControl;
@Input() helpTextAttribute?:string;
@Input() helpTextAttributeScope?:string;
@ContentChild(NgControl) ngControl:NgControl;
internalID = `op-form-field-${+new Date()}`;
text = {
invalid: this.I18n.t('js.label_invalid'),
};
get errorsID() {
return `${this.internalID}-errors`;
}
get descriptionID() {
return `${this.internalID}-description`;
}
get describedByID() {
return this.showErrorMessage ? this.errorsID : this.descriptionID;
}
get formControl():AbstractControl|undefined|null {
return this.ngControl?.control || this.control;
}
get showErrorMessage():boolean {
if (!this.formControl) {
return false;
}
if (this.showValidationErrorOn === 'submit') {
return this.formControl.invalid && this._formGroupDirective?.submitted;
} if (this.showValidationErrorOn === 'blur') {
return this.formControl.invalid && this.formControl.touched;
} if (this.showValidationErrorOn === 'change') {
return this.formControl.invalid && this.formControl.dirty;
}
return false;
}
constructor(
@Optional() private _formGroupDirective:FormGroupDirective,
readonly I18n:I18nService,
) {}
}

@ -1,53 +0,0 @@
@import 'form-field.children'
.op-form-field
display: flex
flex-direction: column
line-height: 1.6rem
// This is a fix for the formly-forms, which render the wrapper around a non-visible input
&:empty
display: none
&--label,
&--description,
&--input,
&--help-text
margin-bottom: 0.5rem
&--label-wrap
display: flex
flex-direction: column
margin: 0
&--label
font-size: 1rem
font-weight: bold
&-indicator
color: var(--primary-color)
&_invalid &--label
color: var(--content-form-error-color)
&--description,
&--help-text
font-size: 12px
&--description *:last-child
margin-bottom: 0
&--errors
display: flex
flex-direction: column
&--error
color: var(--content-form-error-color)
margin-bottom: 1rem
font-size: 0.8rem
&--description,
&--help-text,
&--errors
&:empty
display: none

@ -17,7 +17,7 @@
&--section-header, &--section-header,
> .op-form--fieldset, > .op-form--fieldset,
> .op-form--field, > .op-form--field,
> .op-form-field, > .spot-form-field,
> .op-checkbox-field, > .op-checkbox-field,
> .op-option-list, > .op-option-list,
> .op-highlighted-input, > .op-highlighted-input,

@ -1,4 +1,3 @@
@import './form-field/form-field'
@import './checkbox-field/checkbox-field' @import './checkbox-field/checkbox-field'
@import './form' @import './form'
@import './fieldset' @import './fieldset'

@ -79,8 +79,6 @@ import { ShowSectionDropdownComponent } from './components/hide-section/show-sec
import { SlideToggleComponent } from './components/slide-toggle/slide-toggle.component'; import { SlideToggleComponent } from './components/slide-toggle/slide-toggle.component';
import { DynamicBootstrapModule } from './components/dynamic-bootstrap/dynamic-bootstrap.module'; import { DynamicBootstrapModule } from './components/dynamic-bootstrap/dynamic-bootstrap.module';
import { OpCheckboxFieldComponent } from './components/forms/checkbox-field/checkbox-field.component'; import { OpCheckboxFieldComponent } from './components/forms/checkbox-field/checkbox-field.component';
import { OpFormFieldComponent } from './components/forms/form-field/form-field.component';
import { OpFormBindingDirective } from './components/forms/form-field/form-binding.directive';
import { OpOptionListComponent } from './components/option-list/option-list.component'; import { OpOptionListComponent } from './components/option-list/option-list.component';
import { OpSidemenuComponent } from './components/sidemenu/sidemenu.component'; import { OpSidemenuComponent } from './components/sidemenu/sidemenu.component';
import { OpProjectIncludeComponent } from './components/project-include/project-include.component'; import { OpProjectIncludeComponent } from './components/project-include/project-include.component';
@ -194,8 +192,6 @@ export function bootstrapModule(injector:Injector):void {
SlideToggleComponent, SlideToggleComponent,
OpCheckboxFieldComponent, OpCheckboxFieldComponent,
OpFormFieldComponent,
OpFormBindingDirective,
OpOptionListComponent, OpOptionListComponent,
OpSidemenuComponent, OpSidemenuComponent,
OpProjectIncludeComponent, OpProjectIncludeComponent,
@ -255,8 +251,6 @@ export function bootstrapModule(injector:Injector):void {
SlideToggleComponent, SlideToggleComponent,
OpCheckboxFieldComponent, OpCheckboxFieldComponent,
OpFormFieldComponent,
OpFormBindingDirective,
OpOptionListComponent, OpOptionListComponent,
OpSidemenuComponent, OpSidemenuComponent,
OpProjectIncludeComponent, OpProjectIncludeComponent,

@ -3,10 +3,14 @@
<div class="spot-form-field--label"> <div class="spot-form-field--label">
<span <span
*ngIf="showErrorMessage" *ngIf="showErrorMessage"
class="Hidden for sighted" class="hidden-for-sighted"
>Invalid</span> >
{{ text.invalid }}
</span>
{{ label }} {{ label }}
<span *ngIf="required" class="spot-form-field--label-indicator">*</span> <span *ngIf="required" class="spot-form-field--label-indicator">*</span>
<attribute-help-text <attribute-help-text
[attribute]="helpTextAttribute" [attribute]="helpTextAttribute"
[attributeScope]="helpTextAttributeScope" [attributeScope]="helpTextAttributeScope"
@ -22,11 +26,8 @@
<ng-container *ngTemplateOutlet="inputTemplate"></ng-container> <ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
</ng-container> </ng-container>
<div <div class="spot-form-field--help-text">
class="spot-form-field--description" <ng-content select="[slot=help-text]"></ng-content>
[id]="descriptionID"
>
<ng-content select="[slot=description]"></ng-content>
</div> </div>
<div <div
@ -39,6 +40,13 @@
</ng-container> </ng-container>
<ng-template #inputTemplate> <ng-template #inputTemplate>
<div
class="spot-form-field--description"
[id]="descriptionID"
>
<ng-content select="[slot=description]"></ng-content>
</div>
<div <div
class="spot-form-field--input" class="spot-form-field--input"
[attr.aria-describedby]="describedByID" [attr.aria-describedby]="describedByID"

@ -2,6 +2,7 @@ import {
Component, ContentChild, HostBinding, Input, Optional, Component, ContentChild, HostBinding, Input, Optional,
} from '@angular/core'; } from '@angular/core';
import { AbstractControl, FormGroupDirective, NgControl } from '@angular/forms'; import { AbstractControl, FormGroupDirective, NgControl } from '@angular/forms';
import { I18nService } from 'core-app/core/i18n/i18n.service';
@Component({ @Component({
selector: 'spot-form-field', selector: 'spot-form-field',
@ -22,18 +23,22 @@ export class SpotFormFieldComponent {
@Input() hidden = false; @Input() hidden = false;
@Input() showValidationErrorOn:'change' | 'blur' | 'submit' | 'never' = 'submit';
@Input() control?:AbstractControl; @Input() control?:AbstractControl;
@Input() helpTextAttribute?:string; @Input() helpTextAttribute?:string;
@Input() helpTextAttributeScope?:string; @Input() helpTextAttributeScope?:string;
@Input() showValidationErrorOn:'change' | 'blur' | 'submit' | 'never' = 'submit';
@ContentChild(NgControl) ngControl:NgControl; @ContentChild(NgControl) ngControl:NgControl;
internalID = `spot-form-field-${+new Date()}`; internalID = `spot-form-field-${+new Date()}`;
text = {
invalid: this.I18n.t('js.label_invalid'),
};
get errorsID() { get errorsID() {
return `${this.internalID}-errors`; return `${this.internalID}-errors`;
} }
@ -68,5 +73,6 @@ export class SpotFormFieldComponent {
constructor( constructor(
@Optional() private _formGroupDirective:FormGroupDirective, @Optional() private _formGroupDirective:FormGroupDirective,
readonly I18n:I18nService,
) {} ) {}
} }

@ -42,6 +42,7 @@
margin-bottom: 1rem margin-bottom: 1rem
font-size: 0.8rem font-size: 0.8rem
&--label,
&--description, &--description,
&--errors &--errors
&:empty &:empty

@ -1,16 +1,18 @@
<div class="git-actions-menu dropdown-relative dropdown -overflow-in-view dropdown-anchor-right"> <div class="git-actions-menu dropdown-relative dropdown -overflow-in-view dropdown-anchor-right">
<h3 class="title">{{text.title}}</h3> <h3 class="title">{{text.title}}</h3>
<div class="copy-wrapper op-form-field" *ngFor="let snippet of snippets"> <div class="copy-wrapper spot-form-field" *ngFor="let snippet of snippets">
<label class="op-form-field--label-wrap"> <label class="spot-form-field--label-wrap">
<div class="op-form-field--label">{{ snippet.name }}</div> <div class="spot-form-field--label">{{ snippet.name }}</div>
<div class="op-form-field--input"> <div class="spot-form-field--input">
<input type="text" class="copy-content op-input" readonly="true" [value]="snippet.textToCopy()"> <input type="text" class="copy-content op-input" readonly="true" [value]="snippet.textToCopy()">
<button class="button copy-button" <button
type="button" class="button copy-button"
[attr.aria-label]="text.copyButtonHelpText" type="button"
(click)="onCopyButtonClick(snippet)"> [attr.aria-label]="text.copyButtonHelpText"
<op-icon icon-classes="button--icon icon-copy"></op-icon> (click)="onCopyButtonClick(snippet)"
>
<span class="spot-icon spot-icon_copy"></span>
</button> </button>
<div class="copy-result-message" *ngIf="showCopyResult && snippet.id === copiedSnippetId" [textContent]="lastCopyResult"></div> <div class="copy-result-message" *ngIf="showCopyResult && snippet.id === copiedSnippetId" [textContent]="lastCopyResult"></div>
</div> </div>

@ -89,7 +89,7 @@ describe 'Project attribute help texts', type: :feature, js: true do
page.find('.op-fieldset--legend', text: 'ADVANCED SETTINGS').click page.find('.op-fieldset--legend', text: 'ADVANCED SETTINGS').click
expect(page).to have_selector('.op-form-field--label attribute-help-text', wait: 10) expect(page).to have_selector('.spot-form-field--label attribute-help-text', wait: 10)
# Open help text modal # Open help text modal
modal.open! modal.open!

@ -183,14 +183,14 @@ module Components
def expect_error_displayed(message) def expect_error_displayed(message)
within_modal do within_modal do
expect(page) expect(page)
.to have_selector('.op-form-field--error', text: message) .to have_selector('.spot-form-field--error', text: message)
end end
end end
def expect_help_displayed(message) def expect_help_displayed(message)
within_modal do within_modal do
expect(page) expect(page)
.to have_selector('.op-form-field--help-text', text: message) .to have_selector('.spot-form-field--help-text', text: message)
end end
end end
end end

@ -16,7 +16,7 @@ module FormFields
def expect_required def expect_required
expect(field_container) expect(field_container)
.to have_selector '.op-form-field--label-indicator', text: '*' .to have_selector '.spot-form-field--label-indicator', text: '*'
end end
def field_container def field_container

Loading…
Cancel
Save