Skip to content

Commit

Permalink
IMP-67: Core 16.1: File Upload, Select Field, New form validation (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
A77AY committed Jul 14, 2023
1 parent d98a092 commit fd4e28b
Show file tree
Hide file tree
Showing 53 changed files with 509 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .idea/prettier.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 23 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions projects/ng-core/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Angular Core

Core is a custom library designed to enhance and streamline Angular application development. It provides a set of reusable components, directives, and services that can be easily integrated into your Angular projects.
3 changes: 2 additions & 1 deletion projects/ng-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vality/ng-core",
"version": "16.0.0",
"version": "16.1.1",
"sideEffects": false,
"exports": {
".": {
Expand All @@ -24,6 +24,7 @@
"@angular/material": "^16.0.0",
"@types/lodash-es": "^4.0.0",
"coerce-property": "^15.0.0",
"date-fns": "^2.30.0",
"lodash-es": "^4.0.0",
"rxjs": "^7.0.0",
"utility-types": "^3.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Component, Input } from '@angular/core';
import { booleanAttribute, Component, Input } from '@angular/core';
import { NonNullableFormBuilder } from '@angular/forms';
import { DateAdapter, MAT_DATE_LOCALE, NativeDateAdapter } from '@angular/material/core';
import { coerceBoolean } from 'coerce-property';

import { FormGroupSuperclass, createControlProviders } from '../../utils';

Expand All @@ -17,7 +16,7 @@ import { DateRange } from './types/date-range';
],
})
export class DateRangeFieldComponent extends FormGroupSuperclass<Partial<DateRange>> {
@Input() @coerceBoolean required: boolean | '' = false;
@Input({ transform: booleanAttribute }) required: boolean = false;

control = this.fb.group<Partial<DateRange>>({
start: undefined,
Expand Down
2 changes: 2 additions & 0 deletions projects/ng-core/src/lib/components/date-range-field/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './date-range-field.module';
export * from './date-range-field.component';
export * from './types/date-range';
export * from './utils/is-equal-date-range';
export * from './utils/create-date-range-to-today';
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { subDays, startOfDay, endOfDay } from 'date-fns';

import { DateRange } from '../types/date-range';

export function createDateRangeToToday(minDays: number = 1): DateRange {
return {
/**
* If we take the beginning of the previous day to the end of the current one,
* then it is guaranteed that there will be an interval of one day,
* as a maximum of two days
*/
start: subDays(startOfDay(new Date()), minDays),
end: endOfDay(new Date()),
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { isEqual } from 'date-fns';

import { DateRange } from '../types/date-range';

export function isEqualDateRange(a: DateRange, b: DateRange) {
return isEqual(a.start, b.start) && isEqual(a.end, b.end);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,5 @@ <h2 class="title">{{ title }}</h2>
</div>
</ng-container>

<mat-progress-bar
*ngIf="progress && progress !== 100"
[mode]="progressMode"
[value]="progressValue"
></mat-progress-bar>
<v-progress [progress]="progress"></v-progress>
</div>
12 changes: 0 additions & 12 deletions projects/ng-core/src/lib/components/dialog/dialog.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,6 @@ export class DialogComponent implements Progressable {

@Output() cancel = new EventEmitter<void>();

get progressMode() {
return typeof this.progress === 'number' && this.progress > 1
? 'determinate'
: 'indeterminate';
}

get progressValue(): number {
return this.progressMode === 'determinate'
? (this.progress as number)
: (undefined as never);
}

cancelData = {
status: DialogResponseStatus.Cancelled,
};
Expand Down
2 changes: 2 additions & 0 deletions projects/ng-core/src/lib/components/dialog/dialog.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';

import { ActionsModule } from '../actions';
import { ProgressModule } from '../progress/progress.module';

import { DialogActionsComponent } from './components/dialog-actions/dialog-actions.component';
import { DialogComponent } from './dialog.component';
Expand All @@ -21,6 +22,7 @@ import { DialogService } from './services/dialog.service';
MatIconModule,
MatProgressBarModule,
MatDialogModule,
ProgressModule,
],
providers: [DialogService],
declarations: [DialogComponent, DialogActionsComponent],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="wrapper">
<button mat-button type="button" (click)="fileInput.click()">
{{ label ?? 'Choose File' }}
</button>

<div class="mat-body-2 mat-secondary-text mat-no-margin">
{{ file?.name }}
</div>
</div>

<input #fileInput hidden type="file" (change)="loadFile($event)" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.wrapper {
display: grid;
grid-template-columns: min-content auto;
align-items: center;
grid-gap: 16px;

& > * {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';

import { NotifyLogService } from '../../services';

function hasExtension(fileName: string, extensions: string[]) {
return (
!extensions?.length ||
new RegExp('(' + extensions.join('|').replace(/\./g, '\\.') + ')$').test(fileName)
);
}

@Component({
selector: 'v-file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.scss'],
})
export class FileUploadComponent {
@Input() label?: string;
@Input() extensions: string[] = [];

@Output() upload = new EventEmitter<File | null>();

protected file?: File | null;

constructor(private log: NotifyLogService) {}

loadFile(event: Event) {
const file = (event.target as HTMLInputElement)?.files?.[0] ?? null;
if (!file) {
this.log.error(new Error('File upload error'));
return;
}
if (!hasExtension(file.name, this.extensions)) {
this.log.error(new Error(`Supported file types: ${this.extensions.join(', ')}`));
return;
}
this.file = file;
this.upload.emit(this.file);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';

import { FileUploadComponent } from './file-upload.component';

@NgModule({
declarations: [FileUploadComponent],
exports: [FileUploadComponent],
imports: [CommonModule, MatButtonModule],
})
export class FileUploadModule {}
3 changes: 3 additions & 0 deletions projects/ng-core/src/lib/components/file-upload/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './file-upload.module';
export * from './file-upload.component';
export * from './utils/load-file-content';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Observable } from 'rxjs';

export function loadFileContent(file: File): Observable<string> {
return new Observable((subscriber) => {
if (!file) return file;
const read = new FileReader();
read.readAsBinaryString(file);
read.onloadend = function () {
if (read.error) return subscriber.error(read.error);
else subscriber.next((read.result as string) || '');
subscriber.complete();
};
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
<ng-container *ngIf="isShowMainFilters">
<ng-container *ngTemplateOutlet="dialogData.filters.mainFiltersTemplate"></ng-container>
</ng-container>
<ng-container *ngIf="dialogData.filters.otherFiltersTemplate">
<div *ngIf="dialogData.filters.otherFiltersTemplate" class="other-filters">
<ng-container
*ngTemplateOutlet="dialogData.filters.otherFiltersTemplate"
></ng-container>
</ng-container>
</div>
</div>
</v-dialog>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ $max-columns: 5;
.filters {
display: grid;
grid-template-columns: 1fr;

.other-filters {
display: block !important;
}
}

@for $i from 1 through $max-columns {
Expand Down
2 changes: 2 additions & 0 deletions projects/ng-core/src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export * from './list-field';
export * from './input-field';
export * from './tag';
export * from './error-page';
export * from './select-field';
export * from './file-upload';
3 changes: 3 additions & 0 deletions projects/ng-core/src/lib/components/progress/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './progress.module';
export * from './progress.component';
export * from './utils/get-progress-by-count';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<mat-progress-bar *ngIf="!!mode" [mode]="mode" [value]="value"></mat-progress-bar>
25 changes: 25 additions & 0 deletions projects/ng-core/src/lib/components/progress/progress.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, Input } from '@angular/core';

import { Progressable } from '../../types/progressable';

@Component({
selector: 'v-progress',
templateUrl: './progress.component.html',
})
export class ProgressComponent implements Progressable {
@Input() progress: Progressable['progress'];

get mode() {
return typeof this.progress === 'number' && this.progress <= 1 && this.progress > 0
? 'determinate'
: !!this.progress || this.progress === ''
? 'indeterminate'
: undefined;
}

get value(): number {
return this.mode === 'determinate'
? Math.max(Math.min((1 - (this.progress as number)) * 100, 100), 0)
: (undefined as never);
}
}
12 changes: 12 additions & 0 deletions projects/ng-core/src/lib/components/progress/progress.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatProgressBarModule } from '@angular/material/progress-bar';

import { ProgressComponent } from './progress.component';

@NgModule({
declarations: [ProgressComponent],
imports: [CommonModule, MatProgressBarModule],
exports: [ProgressComponent],
})
export class ProgressModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getProgressByCount(count: number, completedCount: number = Number.MIN_VALUE) {
return 1 - completedCount / count;
}
3 changes: 3 additions & 0 deletions projects/ng-core/src/lib/components/select-field/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './select-field.module';
export * from './select-field.component';
export * from './types/option';
Loading

0 comments on commit fd4e28b

Please sign in to comment.