Skip to content

Commit

Permalink
feat(core/forms): add image field
Browse files Browse the repository at this point in the history
To be used for image file upload in forms, with live preview
  • Loading branch information
trik committed May 25, 2020
1 parent 6840281 commit 14dfa1c
Show file tree
Hide file tree
Showing 16 changed files with 266 additions and 18 deletions.
14 changes: 14 additions & 0 deletions src/core/forms/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ ng_module(
),
assets = [
":file-field.css",
":image-field.css",
":read-only-field.css",
":read-only-file-field.css",
":read-only-image-field.css",
":read-only-table-field.css",
] + glob(["**/*.html"]),
module_name = "@ajf/core/forms",
Expand Down Expand Up @@ -49,6 +51,12 @@ sass_binary(
deps = [],
)

sass_binary(
name = "image_field_scss",
src = "image-field.scss",
deps = [],
)

sass_binary(
name = "read_only_field_scss",
src = "read-only-field.scss",
Expand All @@ -61,6 +69,12 @@ sass_binary(
deps = [],
)

sass_binary(
name = "read_only_image_field_scss",
src = "read-only-image-field.scss",
deps = [],
)

sass_binary(
name = "read_only_table_field_scss",
src = "read-only-table-field.scss",
Expand Down
6 changes: 6 additions & 0 deletions src/core/forms/forms-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ import {AjfFieldIsValidPipe} from './field-is-valid';
import {AjfFileFieldComponent} from './file-field';
import {AjfFormRendererService} from './form-renderer';
import {AjfGetTableCellControlPipe} from './get-table-cell-control';
import {AjfImageFieldComponent} from './image-field';
import {AjfIncrementPipe} from './increment';
import {AjfIsCellEditablePipe} from './is-cell-editable';
import {AjfIsRepeatingSlideInstancePipe} from './is-repeating-slide';
import {AjfNodeCompleteNamePipe} from './node-complete-name';
import {AjfRangePipe} from './range';
import {AjfReadOnlyFieldComponent} from './read-only-field';
import {AjfReadOnlyFileFieldComponent} from './read-only-file-field';
import {AjfReadOnlyImageFieldComponent} from './read-only-image-field';
import {AjfReadOnlyTableFieldComponent} from './read-only-table-field';
import {AjfTableRowClass} from './table-row-class';
import {AjfTableVisibleColumnsPipe} from './table-visible-columns';
Expand All @@ -64,13 +66,15 @@ import {AjfValidationService} from './validation-service';
AjfFieldIsValidPipe,
AjfFileFieldComponent,
AjfGetTableCellControlPipe,
AjfImageFieldComponent,
AjfIncrementPipe,
AjfIsCellEditablePipe,
AjfIsRepeatingSlideInstancePipe,
AjfNodeCompleteNamePipe,
AjfRangePipe,
AjfReadOnlyFieldComponent,
AjfReadOnlyFileFieldComponent,
AjfReadOnlyImageFieldComponent,
AjfReadOnlyTableFieldComponent,
AjfTableRowClass,
AjfTableVisibleColumnsPipe,
Expand All @@ -94,13 +98,15 @@ import {AjfValidationService} from './validation-service';
AjfFieldIsValidPipe,
AjfFileFieldComponent,
AjfGetTableCellControlPipe,
AjfImageFieldComponent,
AjfIncrementPipe,
AjfIsCellEditablePipe,
AjfIsRepeatingSlideInstancePipe,
AjfNodeCompleteNamePipe,
AjfRangePipe,
AjfReadOnlyFieldComponent,
AjfReadOnlyFileFieldComponent,
AjfReadOnlyImageFieldComponent,
AjfReadOnlyTableFieldComponent,
AjfTableRowClass,
AjfTableVisibleColumnsPipe,
Expand Down
5 changes: 5 additions & 0 deletions src/core/forms/image-field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ajf-file-input *ngIf="control|async as ctrl" accept="image/*" [formControl]="ctrl!">
<div ajfFilePreview class="ajf-image-preview">
<img [src]="imageUrl|async">
</div>
</ajf-file-input>
6 changes: 6 additions & 0 deletions src/core/forms/image-field.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ajf-image-field {
img {
min-width: 32px;
min-height: 32px;
}
}
69 changes: 69 additions & 0 deletions src/core/forms/image-field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @license
* Copyright (C) Gnucoop soc. coop.
*
* This file is part of the Advanced JSON forms (ajf).
*
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Advanced JSON forms (ajf).
* If not, see http://www.gnu.org/licenses/.
*
*/

import {AjfFile} from '@ajf/core/file-input';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Inject,
ViewEncapsulation
} from '@angular/core';
import {FormControl} from '@angular/forms';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
import {Observable} from 'rxjs';
import {filter, map, shareReplay, startWith, switchMap} from 'rxjs/operators';

import {AjfBaseFieldComponent} from './base-field';
import {AjfFormRendererService} from './form-renderer';
import {AJF_WARNING_ALERT_SERVICE, AjfWarningAlertService} from './warning-alert-service';

@Component({
selector: 'ajf-image-field',
templateUrl: 'image-field.html',
styleUrls: ['image-field.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class AjfImageFieldComponent extends AjfBaseFieldComponent {
readonly imageUrl: Observable<SafeResourceUrl>;

constructor(
cdr: ChangeDetectorRef, service: AjfFormRendererService,
@Inject(AJF_WARNING_ALERT_SERVICE) was: AjfWarningAlertService, domSanitizer: DomSanitizer) {
super(cdr, service, was);
const fileStream = this.control.pipe(
filter(control => control != null),
switchMap(control => {
control = control as FormControl;
return control.valueChanges.pipe(
startWith(control.value),
);
}),
filter(value => value != null),
shareReplay(1),
) as Observable<AjfFile>;
this.imageUrl = fileStream.pipe(
map(file => domSanitizer.bypassSecurityTrustResourceUrl(file.content)),
);
}
}
1 change: 1 addition & 0 deletions src/core/forms/interface/fields/field-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ export enum AjfFieldType {
Geolocation,
Barcode,
File,
Image,
LENGTH
}
28 changes: 28 additions & 0 deletions src/core/forms/interface/fields/image-field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @license
* Copyright (C) Gnucoop soc. coop.
*
* This file is part of the Advanced JSON forms (ajf).
*
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Advanced JSON forms (ajf).
* If not, see http://www.gnu.org/licenses/.
*
*/

import {AjfField} from './field';
import {AjfFieldType} from './field-type';

export interface AjfImageField extends AjfField {
fieldType: AjfFieldType.Image;
}
2 changes: 2 additions & 0 deletions src/core/forms/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ export * from './get-table-cell-control';
export * from './get-type-name';
export * from './increment';
export * from './input-field';
export * from './image-field';
export * from './is-cell-editable';
export * from './is-repeating-slide';
export * from './node-complete-name';
export * from './range';
export * from './read-only-file-field';
export * from './read-only-image-field';
export * from './search-alert-threshold';
export * from './serializers/attachments-origin-serializer';
export * from './serializers/choices-origin-serializer';
Expand Down
1 change: 1 addition & 0 deletions src/core/forms/read-only-image-field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<img [src]="imageUrl|async">
Empty file.
69 changes: 69 additions & 0 deletions src/core/forms/read-only-image-field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @license
* Copyright (C) Gnucoop soc. coop.
*
* This file is part of the Advanced JSON forms (ajf).
*
* Advanced JSON forms (ajf) is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Advanced JSON forms (ajf) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Advanced JSON forms (ajf).
* If not, see http://www.gnu.org/licenses/.
*
*/

import {AjfFile} from '@ajf/core/file-input';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Inject,
ViewEncapsulation
} from '@angular/core';
import {FormControl} from '@angular/forms';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
import {Observable} from 'rxjs';
import {filter, map, shareReplay, startWith, switchMap} from 'rxjs/operators';

import {AjfBaseFieldComponent} from './base-field';
import {AjfFormRendererService} from './form-renderer';
import {AJF_WARNING_ALERT_SERVICE, AjfWarningAlertService} from './warning-alert-service';

@Component({
selector: 'ajf-read-only-image-field',
templateUrl: 'read-only-image-field.html',
styleUrls: ['read-only-image-field.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class AjfReadOnlyImageFieldComponent extends AjfBaseFieldComponent {
readonly imageUrl: Observable<SafeResourceUrl>;

constructor(
cdr: ChangeDetectorRef, service: AjfFormRendererService,
@Inject(AJF_WARNING_ALERT_SERVICE) was: AjfWarningAlertService, domSanitizer: DomSanitizer) {
super(cdr, service, was);
const fileStream = this.control.pipe(
filter(control => control != null),
switchMap(control => {
control = control as FormControl;
return control.valueChanges.pipe(
startWith(control.value),
);
}),
filter(value => value != null),
shareReplay(1),
) as Observable<AjfFile>;
this.imageUrl = fileStream.pipe(
map(file => domSanitizer.bypassSecurityTrustResourceUrl(file.content)),
);
}
}
26 changes: 18 additions & 8 deletions src/dev-app/ion-forms/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,24 @@ export const formSchema: any = {
name: 'files',
label: 'File upload fields',
nodeType: 3,
nodes: [{
id: 801,
parent: 8,
name: 'file',
label: 'Generic file',
nodeType: 0,
fieldType: 14,
}]
nodes: [
{
id: 801,
parent: 8,
name: 'file',
label: 'Generic file',
nodeType: 0,
fieldType: 14,
},
{
id: 802,
parent: 801,
name: 'image',
label: 'Image file',
nodeType: 0,
fieldType: 15,
},
]
},
]
};
26 changes: 18 additions & 8 deletions src/dev-app/mat-forms/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,24 @@ export const formSchema: any = {
name: 'files',
label: 'File upload fields',
nodeType: 3,
nodes: [{
id: 801,
parent: 8,
name: 'file',
label: 'Generic file',
nodeType: 0,
fieldType: 14,
}]
nodes: [
{
id: 801,
parent: 8,
name: 'file',
label: 'Generic file',
nodeType: 0,
fieldType: 14,
},
{
id: 802,
parent: 801,
name: 'image',
label: 'Image file',
nodeType: 0,
fieldType: 15,
},
]
},
]
};
6 changes: 6 additions & 0 deletions src/ionic/forms/field-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import {
AjfFieldService as CoreService,
AjfFieldType,
AjfFileFieldComponent,
AjfImageFieldComponent,
AjfReadOnlyFieldComponent,
AjfReadOnlyFileFieldComponent,
AjfReadOnlyImageFieldComponent,
AjfReadOnlyTableFieldComponent
} from '@ajf/core/forms';
import {Injectable} from '@angular/core';
Expand Down Expand Up @@ -104,5 +106,9 @@ export class AjfFieldService extends CoreService {
component: AjfFileFieldComponent,
readOnlyComponent: AjfReadOnlyFileFieldComponent
};
this.componentsMap[AjfFieldType.Image] = {
component: AjfImageFieldComponent,
readOnlyComponent: AjfReadOnlyImageFieldComponent
};
}
}
6 changes: 6 additions & 0 deletions src/material/forms/field-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import {
AjfFieldService as CoreService,
AjfFieldType,
AjfFileFieldComponent,
AjfImageFieldComponent,
AjfReadOnlyFieldComponent,
AjfReadOnlyFileFieldComponent,
AjfReadOnlyImageFieldComponent,
AjfReadOnlyTableFieldComponent
} from '@ajf/core/forms';
import {Injectable} from '@angular/core';
Expand Down Expand Up @@ -100,5 +102,9 @@ export class AjfFieldService extends CoreService {
component: AjfFileFieldComponent,
readOnlyComponent: AjfReadOnlyFileFieldComponent
};
this.componentsMap[AjfFieldType.Image] = {
component: AjfImageFieldComponent,
readOnlyComponent: AjfReadOnlyImageFieldComponent
};
}
}

0 comments on commit 14dfa1c

Please sign in to comment.