mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-1381] improving the style for form reflecting UX spec (#2256)
* [ADF-1381] improving the style for form reflecting UX spec * [ADF-1381] fix error message icon * [ADF-1381] added more spec details to form widgets * [ADF-1381] fixed wrong check * [ADF-1381] removed wrong added deep into scss * [ADF-1381] applied changes due the peer review * [ADF-1381] missed whitespace
This commit is contained in:
@@ -14,5 +14,6 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
||||
|
@@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
.mat-input-placeholder {
|
||||
top: 2.5em !important;
|
||||
top: 2.2em !important;
|
||||
}
|
||||
|
||||
.mat-focused {
|
||||
|
@@ -24,6 +24,7 @@ export class GroupUserModel {
|
||||
firstName: string;
|
||||
id: string;
|
||||
lastName: string;
|
||||
userImageUrl: string;
|
||||
|
||||
constructor(json?: any) {
|
||||
if (json) {
|
||||
|
@@ -14,6 +14,7 @@
|
||||
<button class="adf-date-widget-button" mdSuffix [mdDatepickerToggle]="datePicker" [disabled]="field.readOnly"></button>
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
<md-datepicker #datePicker [touchUi]="true" [startAt]="startAt" (selectedChanged)="onDateChanged($event)"></md-datepicker>
|
||||
</div>
|
||||
|
||||
|
@@ -11,4 +11,5 @@
|
||||
[id]="opt.id">{{opt.name}}</md-option>
|
||||
</md-select>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
@@ -11,4 +11,8 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-dropdown-required-message .adf-error-text-container{
|
||||
margin-top: -2px !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -62,4 +62,5 @@
|
||||
(cancel)="onCancelChanges()">
|
||||
</row-editor>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
@@ -3,4 +3,7 @@
|
||||
<div class="adf-error-text">{{error}}</div>
|
||||
<i class="material-icons adf-error-icon">warning</i>
|
||||
</div>
|
||||
<div *ngIf="required" [@transitionMessages]="_subscriptAnimationState">
|
||||
<div class="adf-error-text">{{required}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,3 +1,5 @@
|
||||
.adf-error-text-container {
|
||||
margin-top: 0 !important;
|
||||
margin-top: -16px !important;
|
||||
position: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { AfterViewInit, Component, Input, ViewEncapsulation } from '@angular/core';
|
||||
import { AfterViewInit, Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { baseHost , WidgetComponent } from './../widget.component';
|
||||
|
||||
@@ -38,11 +38,14 @@ import { baseHost , WidgetComponent } from './../widget.component';
|
||||
host: baseHost,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ErrorWidgetComponent extends WidgetComponent implements AfterViewInit {
|
||||
export class ErrorWidgetComponent extends WidgetComponent implements AfterViewInit, OnChanges {
|
||||
|
||||
@Input()
|
||||
error: string;
|
||||
|
||||
@Input()
|
||||
required: string;
|
||||
|
||||
_subscriptAnimationState: string = '';
|
||||
|
||||
constructor(public formService: FormService) {
|
||||
@@ -53,4 +56,11 @@ export class ErrorWidgetComponent extends WidgetComponent implements AfterViewIn
|
||||
this._subscriptAnimationState = 'enter';
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['required']) {
|
||||
this.required = changes.required.currentValue;
|
||||
this._subscriptAnimationState = 'enter';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<div class="adf-group-widget {{field.className}}"
|
||||
[class.is-dirty]="value"
|
||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="typehead-div" *ngIf="field.isVisible">
|
||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="functional-group-div" *ngIf="field.isVisible">
|
||||
<md-input-container>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label>
|
||||
<input mdInput
|
||||
@@ -15,11 +15,12 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
<div class="adf-typeahead-autocomplete mat-elevation-z2" *ngIf="popupVisible && users.length > 0">
|
||||
<div class="adf-group-autocomplete mat-elevation-z2" *ngIf="popupVisible">
|
||||
<md-option *ngFor="let item of groups"
|
||||
[id]="field.id +'-'+item.id"
|
||||
(click)="onItemClick(item, $event)">
|
||||
<span>{{item.name}}}</span>
|
||||
<span>{{item.name}}</span>
|
||||
</md-option>
|
||||
</div>
|
||||
|
@@ -9,13 +9,14 @@
|
||||
|
||||
&-group-autocomplete {
|
||||
background-color: #fff;
|
||||
position:absolute;
|
||||
position: inherit;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
color: #555;
|
||||
margin: -15px 0 0 0;
|
||||
> ul {
|
||||
> md-option {
|
||||
list-style-type: none;
|
||||
position: static;
|
||||
height: auto;
|
||||
@@ -25,7 +26,7 @@
|
||||
margin: 0;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 2px;
|
||||
> li {
|
||||
> span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
md-autosize
|
||||
type="text"
|
||||
rows="3"
|
||||
[maxlength]="field.maxLength"
|
||||
[id]="field.id"
|
||||
[required]="isRequired()"
|
||||
[(ngModel)]="field.value"
|
||||
@@ -14,6 +15,10 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</textarea>
|
||||
</md-input-container>
|
||||
<div *ngIf="field.maxLength > 0" class="adf-multiline-word-counter">
|
||||
<span>{{field?.value?.length || 0}}/{{field.maxLength}}</span>
|
||||
</div>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
||||
|
@@ -7,4 +7,21 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-multiline-word-counter {
|
||||
float: right;
|
||||
margin-top: -20px !important;
|
||||
min-height: 24px;
|
||||
min-width: 1px;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
overflow: hidden;
|
||||
transition: all .3s cubic-bezier(.55,0,.55,.2);
|
||||
opacity: 1;
|
||||
margin-top: 0;
|
||||
padding-top: 5px;
|
||||
text-align: right;
|
||||
padding-right: 2px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,4 +15,5 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
@@ -1,13 +1,13 @@
|
||||
<div class="adf-people-widget {{field.className}}"
|
||||
[class.is-dirty]="value"
|
||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="typehead-div" *ngIf="field.isVisible">
|
||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="people-widget-content" *ngIf="field.isVisible">
|
||||
<md-input-container>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label>
|
||||
<input mdInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[(ngModel)]="field.value"
|
||||
[(ngModel)]="value"
|
||||
(ngModelChange)="checkVisibility(field)"
|
||||
(keyup)="onKeyUp($event)"
|
||||
(blur)="onBlur()"
|
||||
@@ -15,11 +15,22 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
<div class="adf-typeahead-autocomplete mat-elevation-z2" *ngIf="popupVisible && users.length > 0">
|
||||
<md-option *ngFor="let item of users"
|
||||
[id]="field.id +'-'+item.id"
|
||||
(click)="onItemClick(item, $event)">
|
||||
<span>{{getDisplayName(item)}}</span>
|
||||
<div class="adf-people-autocomplete mat-elevation-z2" *ngIf="popupVisible && users.length > 0">
|
||||
<md-option *ngFor="let user of users"
|
||||
[id]="field.id +'-'+user.id"
|
||||
(click)="onItemClick(user, $event)">
|
||||
<div class="adf-people-widget-row">
|
||||
<div *ngIf="!user.userImage" class="adf-people-widget-pic">
|
||||
{{user.firstName[0]}} {{user.lastName[0]}}
|
||||
</div>
|
||||
<div *ngIf="user.userImage" class="adf-people-widget-image-row">
|
||||
<img class="adf-people-widget-image"
|
||||
[src]="user.userImage"
|
||||
(error)="onErrorImageLoad(user)"/>
|
||||
</div>
|
||||
<span>{{getDisplayName(user)}}</span>
|
||||
</div>
|
||||
</md-option>
|
||||
</div>
|
||||
|
@@ -9,25 +9,58 @@
|
||||
|
||||
&-people-autocomplete {
|
||||
background-color: #fff;
|
||||
position:absolute;
|
||||
position:inherit;
|
||||
max-height: 200px;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
z-index: 5;
|
||||
color: #555;
|
||||
margin: -15px 0 0 0;
|
||||
> ul {
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
> md-option {
|
||||
list-style-type: none;
|
||||
position: static;
|
||||
height: auto;
|
||||
width: auto;
|
||||
min-width: 124px;
|
||||
padding: 8px 0;
|
||||
padding: 8px 0 0 20px;
|
||||
margin: 0;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 2px;
|
||||
> li {
|
||||
> span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-people-widget-pic {
|
||||
background: #ff9800;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
padding: 0px 9px;
|
||||
border-radius: 100px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
font-weight: bolder;
|
||||
font-size: 18px;
|
||||
font-family: Muli;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-people-widget-row {
|
||||
padding: 5px 5px;
|
||||
}
|
||||
|
||||
&-people-widget-image {
|
||||
border-radius: 100px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
&-people-widget-image-row {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
@@ -85,12 +85,18 @@ export class PeopleWidgetComponent extends WidgetComponent implements OnInit {
|
||||
}, 200);
|
||||
}
|
||||
|
||||
onErrorImageLoad(user) {
|
||||
if (user.userImage) {
|
||||
user.userImage = null;
|
||||
}
|
||||
}
|
||||
|
||||
flushValue() {
|
||||
this.popupVisible = false;
|
||||
|
||||
let option = this.users.find(item => {
|
||||
let fullName = this.getDisplayName(item).toLocaleLowerCase();
|
||||
return fullName === this.value.toLocaleLowerCase();
|
||||
return (this.value && fullName === this.value.toLocaleLowerCase());
|
||||
});
|
||||
|
||||
if (option) {
|
||||
|
@@ -17,4 +17,7 @@
|
||||
</md-radio-group>
|
||||
</div>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
||||
|
||||
|
@@ -15,4 +15,5 @@
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
@@ -1,23 +1,26 @@
|
||||
<div class="adf-typeahead-widget {{field.className}}"
|
||||
[class.is-dirty]="value"
|
||||
[class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly" id="typehead-div" *ngIf="field.isVisible">
|
||||
<md-input-container>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}}</label>
|
||||
<input mdInput
|
||||
class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[(ngModel)]="value"
|
||||
(keyup)="onKeyUp($event)"
|
||||
(blur)="onBlur()"
|
||||
[disabled]="field.readOnly"
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
</div>
|
||||
<div class="adf-typeahead-autocomplete mat-elevation-z2" *ngIf="options.length > 0 && popupVisible">
|
||||
<md-option *ngFor="let item of options"
|
||||
(click)="onItemClick(item, $event)">
|
||||
<div class="adf-typeahead-widget-container">
|
||||
<div class="adf-typeahead-widget {{field.className}}"
|
||||
[class.is-dirty]="value"
|
||||
[class.adf-invalid]="!field.isValid"
|
||||
[class.adf-readonly]="field.readOnly"
|
||||
id="typehead-div" *ngIf="field.isVisible">
|
||||
<md-input-container>
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}}</label>
|
||||
<input mdInput class="adf-input"
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[(ngModel)]="value"
|
||||
(keyup)="onKeyUp($event)"
|
||||
(blur)="onBlur()"
|
||||
[disabled]="field.readOnly"
|
||||
placeholder="{{field.placeholder}}">
|
||||
</md-input-container>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
<div class="adf-typeahead-autocomplete mat-elevation-z2" *ngIf="options.length > 0 && popupVisible">
|
||||
<md-option *ngFor="let item of options" (click)="onItemClick(item, $event)">
|
||||
<span>{{item.name}}</span>
|
||||
</md-option>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -3,6 +3,11 @@
|
||||
|
||||
.adf {
|
||||
|
||||
&-typeahead-widget-container {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-typeahead-widget {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -11,11 +16,13 @@
|
||||
background-color: #fff;
|
||||
position:absolute;
|
||||
max-height: 200px;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
z-index: 5;
|
||||
color: #555;
|
||||
margin: -15px 0 0 0;
|
||||
> ul {
|
||||
margin: -10px 0 0 0;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
> md-option {
|
||||
list-style-type: none;
|
||||
position: static;
|
||||
height: auto;
|
||||
@@ -23,10 +30,10 @@
|
||||
min-width: 124px;
|
||||
padding: 8px 0;
|
||||
margin: 0;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 2px;
|
||||
> li {
|
||||
> span {
|
||||
opacity: 1;
|
||||
padding-left: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,5 +28,5 @@
|
||||
(change)="onFileChanged($event)">
|
||||
</div>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
|
||||
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
@@ -83,6 +83,10 @@ export class WidgetComponent implements AfterViewInit {
|
||||
this.field.value !== undefined;
|
||||
}
|
||||
|
||||
isInvalidFieldRequired() {
|
||||
return !this.field.isValid && !this.field.validationSummary && this.isRequired();
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.fieldChanged.emit(this.field);
|
||||
}
|
||||
|
@@ -5,6 +5,9 @@
|
||||
},
|
||||
"PREVIEW": {
|
||||
"IMAGE_NOT_AVAILABLE": "The preview image is not available."
|
||||
},
|
||||
"FIELD": {
|
||||
"REQUIRED" : "*Required"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -477,6 +477,7 @@ describe('Form service', () => {
|
||||
});
|
||||
|
||||
it('should return list of people', (done) => {
|
||||
spyOn(service, 'getUserProfileImageApi').and.returnValue('/app/rest/users/2002/picture');
|
||||
let fakeFilter: string = 'whatever';
|
||||
|
||||
service.getWorkflowUsers(fakeFilter).subscribe(result => {
|
||||
|
@@ -352,13 +352,22 @@ export class FormService {
|
||||
return Observable.fromPromise(this.taskApi.getRestFieldValuesColumn(taskId, field, column)).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
private getUserProfileImageApi(userId: string): string {
|
||||
return this.apiService.getInstance().activiti.userApi.getUserProfilePictureUrl(userId);
|
||||
}
|
||||
|
||||
getWorkflowUsers(filter: string, groupId?: string): Observable<GroupUserModel[]> {
|
||||
let option: any = {filter: filter};
|
||||
if (groupId) {
|
||||
option.groupId = groupId;
|
||||
}
|
||||
return Observable.fromPromise(this.usersWorkflowApi.getUsers(option))
|
||||
.map((response: any) => <GroupUserModel[]> response.data || [])
|
||||
.switchMap((response: any) => <GroupUserModel[]> response.data || [])
|
||||
.map((user: any) => {
|
||||
user.userImage = this.getUserProfileImageApi(user.id);
|
||||
return Observable.of(user);
|
||||
})
|
||||
.combineAll()
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user