@flusys/ng-shared 1.0.0-beta → 1.1.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -1
- package/fesm2022/flusys-ng-shared.mjs +166 -91
- package/fesm2022/flusys-ng-shared.mjs.map +1 -1
- package/package.json +2 -2
- package/types/flusys-ng-shared.d.ts +316 -36
package/README.md
CHANGED
|
@@ -110,6 +110,77 @@ interface IDropDown {
|
|
|
110
110
|
}
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
#### User Select Interfaces
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface IUserSelectFilter {
|
|
117
|
+
page: number;
|
|
118
|
+
pageSize: number;
|
|
119
|
+
search: string;
|
|
120
|
+
[key: string]: unknown;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### File Select Interfaces
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface IFileBasicInfo {
|
|
130
|
+
id: string;
|
|
131
|
+
name: string;
|
|
132
|
+
contentType: string;
|
|
133
|
+
size: string;
|
|
134
|
+
url: string | null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface IFileUploadOptions {
|
|
138
|
+
storageConfigId?: string;
|
|
139
|
+
folderPath?: string;
|
|
140
|
+
maxWidth?: number;
|
|
141
|
+
maxHeight?: number;
|
|
142
|
+
quality?: number;
|
|
143
|
+
compress?: boolean;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface IUploadedFile {
|
|
147
|
+
name: string;
|
|
148
|
+
key: string;
|
|
149
|
+
size: number;
|
|
150
|
+
contentType: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
interface IFileSelectFilter {
|
|
154
|
+
page: number;
|
|
155
|
+
pageSize: number;
|
|
156
|
+
search: string;
|
|
157
|
+
contentTypes?: string[];
|
|
158
|
+
folderId?: string;
|
|
159
|
+
[key: string]: unknown;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type LoadFilesFn = (filter: IFileSelectFilter) => Observable<IListResponse<IFileBasicInfo>>;
|
|
163
|
+
type UploadFileFn = (file: File, options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile>>;
|
|
164
|
+
type GetFileUrlsFn = (fileIds: string[]) => Observable<ISingleResponse<IFileBasicInfo[]>>;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**File Type Filters (Constants):**
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { FILE_TYPE_FILTERS, getAcceptString, isFileTypeAllowed, getFileIconClass, formatFileSize } from '@flusys/ng-shared';
|
|
171
|
+
|
|
172
|
+
FILE_TYPE_FILTERS.IMAGES // ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
|
|
173
|
+
FILE_TYPE_FILTERS.DOCUMENTS // ['application/pdf', 'application/msword', ...]
|
|
174
|
+
FILE_TYPE_FILTERS.VIDEOS // ['video/mp4', 'video/webm', ...]
|
|
175
|
+
FILE_TYPE_FILTERS.AUDIO // ['audio/mpeg', 'audio/wav', ...]
|
|
176
|
+
FILE_TYPE_FILTERS.ALL // [] (allows all)
|
|
177
|
+
|
|
178
|
+
getAcceptString(['image/*']) // 'image/*'
|
|
179
|
+
isFileTypeAllowed(file, ['image/*']) // true/false
|
|
180
|
+
getFileIconClass('image/png') // 'pi pi-image'
|
|
181
|
+
formatFileSize('1024') // '1 KB'
|
|
182
|
+
```
|
|
183
|
+
|
|
113
184
|
### Response Interfaces
|
|
114
185
|
|
|
115
186
|
Type-safe interfaces matching FLUSYS_NEST backend response DTOs.
|
|
@@ -539,6 +610,176 @@ export class MyComponent {
|
|
|
539
610
|
|
|
540
611
|
**Computed signals:** `selectedValueDisplay` (display text), `isSelectAll` (all items selected)
|
|
541
612
|
|
|
613
|
+
### UserSelectComponent
|
|
614
|
+
|
|
615
|
+
Single user selection with lazy loading. Uses `USER_PROVIDER` internally or accepts custom `loadUsers` function.
|
|
616
|
+
|
|
617
|
+
- **Selector:** `lib-user-select`
|
|
618
|
+
- **Supports:** Template-driven, reactive forms, signal forms
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
@Component({
|
|
622
|
+
imports: [UserSelectComponent],
|
|
623
|
+
template: `
|
|
624
|
+
<!-- Simple usage - uses USER_PROVIDER internally -->
|
|
625
|
+
<lib-user-select
|
|
626
|
+
[(value)]="selectedUserId"
|
|
627
|
+
[isEditMode]="true"
|
|
628
|
+
/>
|
|
629
|
+
|
|
630
|
+
<!-- With custom loadUsers function -->
|
|
631
|
+
<lib-user-select
|
|
632
|
+
[(value)]="selectedUserId"
|
|
633
|
+
[isEditMode]="true"
|
|
634
|
+
[loadUsers]="customLoadUsers"
|
|
635
|
+
/>
|
|
636
|
+
`,
|
|
637
|
+
})
|
|
638
|
+
export class MyComponent {
|
|
639
|
+
readonly selectedUserId = signal<string | null>(null);
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
**Inputs:**
|
|
644
|
+
|
|
645
|
+
| Input | Type | Default | Description |
|
|
646
|
+
| ----- | ---- | ------- | ----------- |
|
|
647
|
+
| `isEditMode` | `boolean` | required | Enable/disable editing |
|
|
648
|
+
| `placeHolder` | `string` | `'Select User'` | Placeholder text |
|
|
649
|
+
| `filterActive` | `boolean` | `true` | Filter active users only |
|
|
650
|
+
| `additionalFilters` | `Record<string, unknown>` | `{}` | Extra filter params |
|
|
651
|
+
| `pageSize` | `number` | `20` | Page size for pagination |
|
|
652
|
+
| `loadUsers` | `LoadUsersFn` | - | Custom user loading function |
|
|
653
|
+
|
|
654
|
+
**Model:** `value` - Two-way bound selected user ID (`string | null`)
|
|
655
|
+
|
|
656
|
+
**Outputs:** `userSelected` (IUserBasicInfo | null), `onError` (Error)
|
|
657
|
+
|
|
658
|
+
### UserMultiSelectComponent
|
|
659
|
+
|
|
660
|
+
Multiple user selection with lazy loading. Uses `USER_PROVIDER` internally or accepts custom `loadUsers` function.
|
|
661
|
+
|
|
662
|
+
- **Selector:** `lib-user-multi-select`
|
|
663
|
+
- **Supports:** Template-driven, reactive forms, signal forms
|
|
664
|
+
|
|
665
|
+
```typescript
|
|
666
|
+
@Component({
|
|
667
|
+
imports: [UserMultiSelectComponent],
|
|
668
|
+
template: `
|
|
669
|
+
<lib-user-multi-select
|
|
670
|
+
[(value)]="selectedUserIds"
|
|
671
|
+
[isEditMode]="true"
|
|
672
|
+
/>
|
|
673
|
+
`,
|
|
674
|
+
})
|
|
675
|
+
export class MyComponent {
|
|
676
|
+
readonly selectedUserIds = signal<string[] | null>(null);
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**Inputs:** Same as `UserSelectComponent`.
|
|
681
|
+
|
|
682
|
+
**Model:** `value` - Two-way bound selected user IDs (`string[] | null`)
|
|
683
|
+
|
|
684
|
+
**Outputs:** `usersSelected` (IUserBasicInfo[]), `onError` (Error)
|
|
685
|
+
|
|
686
|
+
### FileUploaderComponent
|
|
687
|
+
|
|
688
|
+
Drag & drop file upload with type filtering. Pass your own `uploadFile` function.
|
|
689
|
+
|
|
690
|
+
- **Selector:** `lib-file-uploader`
|
|
691
|
+
|
|
692
|
+
```typescript
|
|
693
|
+
@Component({
|
|
694
|
+
imports: [FileUploaderComponent],
|
|
695
|
+
template: `
|
|
696
|
+
<!-- Single image upload -->
|
|
697
|
+
<lib-file-uploader
|
|
698
|
+
[uploadFile]="uploadFile"
|
|
699
|
+
[acceptTypes]="['image/*']"
|
|
700
|
+
[multiple]="false"
|
|
701
|
+
(fileUploaded)="onFileUploaded($event)"
|
|
702
|
+
/>
|
|
703
|
+
|
|
704
|
+
<!-- Multiple document upload -->
|
|
705
|
+
<lib-file-uploader
|
|
706
|
+
[uploadFile]="uploadFile"
|
|
707
|
+
[acceptTypes]="FILE_TYPE_FILTERS.DOCUMENTS"
|
|
708
|
+
[multiple]="true"
|
|
709
|
+
[maxFiles]="5"
|
|
710
|
+
(filesUploaded)="onFilesUploaded($event)"
|
|
711
|
+
/>
|
|
712
|
+
`,
|
|
713
|
+
})
|
|
714
|
+
export class MyComponent {
|
|
715
|
+
readonly uploadService = inject(UploadService);
|
|
716
|
+
|
|
717
|
+
readonly uploadFile: UploadFileFn = (file, options) =>
|
|
718
|
+
this.uploadService.uploadSingleFile(file, options);
|
|
719
|
+
}
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**Inputs:**
|
|
723
|
+
|
|
724
|
+
| Input | Type | Default | Description |
|
|
725
|
+
| ----- | ---- | ------- | ----------- |
|
|
726
|
+
| `uploadFile` | `UploadFileFn` | required | Upload function |
|
|
727
|
+
| `acceptTypes` | `string[]` | `[]` | Allowed MIME types |
|
|
728
|
+
| `multiple` | `boolean` | `false` | Allow multiple files |
|
|
729
|
+
| `maxFiles` | `number` | `10` | Max files for multiple |
|
|
730
|
+
| `maxSizeMb` | `number` | `10` | Max file size in MB |
|
|
731
|
+
| `uploadOptions` | `IFileUploadOptions` | `{}` | Upload options |
|
|
732
|
+
| `disabled` | `boolean` | `false` | Disable uploader |
|
|
733
|
+
| `showPreview` | `boolean` | `true` | Show selected files preview |
|
|
734
|
+
| `autoUpload` | `boolean` | `true` | Upload immediately on selection |
|
|
735
|
+
|
|
736
|
+
**Outputs:** `fileUploaded` (IUploadedFile), `filesUploaded` (IUploadedFile[]), `onError` (Error), `fileSelected` (File[])
|
|
737
|
+
|
|
738
|
+
### FileSelectorDialogComponent
|
|
739
|
+
|
|
740
|
+
Dialog to browse and select existing files with filtering.
|
|
741
|
+
|
|
742
|
+
- **Selector:** `lib-file-selector-dialog`
|
|
743
|
+
|
|
744
|
+
```typescript
|
|
745
|
+
@Component({
|
|
746
|
+
imports: [FileSelectorDialogComponent],
|
|
747
|
+
template: `
|
|
748
|
+
<lib-file-selector-dialog
|
|
749
|
+
[(visible)]="showFileSelector"
|
|
750
|
+
[loadFiles]="loadFiles"
|
|
751
|
+
[acceptTypes]="['image/*']"
|
|
752
|
+
[multiple]="false"
|
|
753
|
+
(fileSelected)="onFileSelected($event)"
|
|
754
|
+
/>
|
|
755
|
+
`,
|
|
756
|
+
})
|
|
757
|
+
export class MyComponent {
|
|
758
|
+
readonly showFileSelector = signal(false);
|
|
759
|
+
readonly fileService = inject(FileManagerApiService);
|
|
760
|
+
|
|
761
|
+
readonly loadFiles: LoadFilesFn = (filter) =>
|
|
762
|
+
this.fileService.getAll(filter.search, {
|
|
763
|
+
pagination: { currentPage: filter.page, pageSize: filter.pageSize },
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
**Inputs:**
|
|
769
|
+
|
|
770
|
+
| Input | Type | Default | Description |
|
|
771
|
+
| ----- | ---- | ------- | ----------- |
|
|
772
|
+
| `loadFiles` | `LoadFilesFn` | required | File loading function |
|
|
773
|
+
| `header` | `string` | `'Select File'` | Dialog header |
|
|
774
|
+
| `acceptTypes` | `string[]` | `[]` | Allowed MIME types |
|
|
775
|
+
| `multiple` | `boolean` | `false` | Allow multiple selection |
|
|
776
|
+
| `maxSelection` | `number` | `10` | Max files for multiple |
|
|
777
|
+
| `pageSize` | `number` | `20` | Page size for pagination |
|
|
778
|
+
|
|
779
|
+
**Model:** `visible` - Two-way bound dialog visibility (`boolean`)
|
|
780
|
+
|
|
781
|
+
**Outputs:** `fileSelected` (IFileBasicInfo), `filesSelected` (IFileBasicInfo[]), `closed` (void), `onError` (Error)
|
|
782
|
+
|
|
542
783
|
---
|
|
543
784
|
|
|
544
785
|
## 5. Directives
|
|
@@ -805,6 +1046,58 @@ interface IUserPermissionProvider {
|
|
|
805
1046
|
}
|
|
806
1047
|
```
|
|
807
1048
|
|
|
1049
|
+
#### IProfileUploadProvider / `PROFILE_UPLOAD_PROVIDER`
|
|
1050
|
+
|
|
1051
|
+
Profile picture upload for ng-auth profile page. Implemented by ng-storage.
|
|
1052
|
+
|
|
1053
|
+
```typescript
|
|
1054
|
+
interface IProfileUploadResult {
|
|
1055
|
+
id: string; // File manager ID (UUID)
|
|
1056
|
+
name: string; // Original file name
|
|
1057
|
+
key: string; // Storage key/path
|
|
1058
|
+
size: number; // File size in bytes
|
|
1059
|
+
contentType: string; // MIME type
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
interface IProfileUploadOptions {
|
|
1063
|
+
folderPath?: string;
|
|
1064
|
+
compress?: boolean;
|
|
1065
|
+
maxWidth?: number;
|
|
1066
|
+
maxHeight?: number;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
interface IProfileUploadProvider {
|
|
1070
|
+
uploadProfilePicture(
|
|
1071
|
+
file: File,
|
|
1072
|
+
options?: IProfileUploadOptions
|
|
1073
|
+
): Observable<ISingleResponse<IProfileUploadResult>>;
|
|
1074
|
+
}
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
#### IProfilePermissionProvider / `PROFILE_PERMISSION_PROVIDER`
|
|
1078
|
+
|
|
1079
|
+
User permission queries for ng-auth profile page. Implemented by ng-iam.
|
|
1080
|
+
|
|
1081
|
+
```typescript
|
|
1082
|
+
interface IProfileRoleInfo {
|
|
1083
|
+
id: string;
|
|
1084
|
+
name: string;
|
|
1085
|
+
description?: string | null;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
interface IProfileActionInfo {
|
|
1089
|
+
id: string;
|
|
1090
|
+
code: string;
|
|
1091
|
+
name: string;
|
|
1092
|
+
description?: string | null;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
interface IProfilePermissionProvider {
|
|
1096
|
+
getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
|
|
1097
|
+
getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
|
|
1098
|
+
}
|
|
1099
|
+
```
|
|
1100
|
+
|
|
808
1101
|
### Usage in Consuming Packages
|
|
809
1102
|
|
|
810
1103
|
```typescript
|
|
@@ -931,6 +1224,10 @@ export const appConfig: ApplicationConfig = {
|
|
|
931
1224
|
| `IconComponent` | `lib-icon` | Flexible icon renderer |
|
|
932
1225
|
| `LazySelectComponent` | `lib-lazy-select` | Lazy-loading dropdown |
|
|
933
1226
|
| `LazyMultiSelectComponent` | `lib-lazy-multi-select`| Lazy-loading multi-select |
|
|
1227
|
+
| `UserSelectComponent` | `lib-user-select` | Single user selector |
|
|
1228
|
+
| `UserMultiSelectComponent` | `lib-user-multi-select`| Multiple user selector |
|
|
1229
|
+
| `FileUploaderComponent` | `lib-file-uploader` | Drag & drop file upload |
|
|
1230
|
+
| `FileSelectorDialogComponent` | `lib-file-selector-dialog` | File browser dialog |
|
|
934
1231
|
|
|
935
1232
|
### Directives
|
|
936
1233
|
|
|
@@ -964,6 +1261,14 @@ export const appConfig: ApplicationConfig = {
|
|
|
964
1261
|
| `IMessageResponse` | Message-only response |
|
|
965
1262
|
| `IErrorResponse` | Error with validation details |
|
|
966
1263
|
| `ILogicNode` | Permission logic tree (AND/OR nodes) |
|
|
1264
|
+
| `IUserSelectFilter` | User select filter params |
|
|
1265
|
+
| `LoadUsersFn` | User loading function type |
|
|
1266
|
+
| `IFileBasicInfo` | Basic file info for selectors |
|
|
1267
|
+
| `IFileUploadOptions`| Upload options (compression, etc.) |
|
|
1268
|
+
| `IUploadedFile` | Uploaded file response |
|
|
1269
|
+
| `IFileSelectFilter` | File select filter params |
|
|
1270
|
+
| `LoadFilesFn` | File loading function type |
|
|
1271
|
+
| `UploadFileFn` | File upload function type |
|
|
967
1272
|
|
|
968
1273
|
### Injection Tokens
|
|
969
1274
|
|
|
@@ -972,6 +1277,8 @@ export const appConfig: ApplicationConfig = {
|
|
|
972
1277
|
| `USER_PROVIDER` | `IUserProvider` | User list for IAM |
|
|
973
1278
|
| `COMPANY_API_PROVIDER` | `ICompanyApiProvider` | Company list for IAM |
|
|
974
1279
|
| `USER_PERMISSION_PROVIDER` | `IUserPermissionProvider` | User permission queries |
|
|
1280
|
+
| `PROFILE_UPLOAD_PROVIDER` | `IProfileUploadProvider` | Profile picture upload (ng-storage) |
|
|
1281
|
+
| `PROFILE_PERMISSION_PROVIDER` | `IProfilePermissionProvider` | User permissions for profile (ng-iam) |
|
|
975
1282
|
|
|
976
1283
|
## See Also
|
|
977
1284
|
|
|
@@ -982,5 +1289,5 @@ export const appConfig: ApplicationConfig = {
|
|
|
982
1289
|
|
|
983
1290
|
---
|
|
984
1291
|
|
|
985
|
-
**Last Updated:** 2026-02-
|
|
1292
|
+
**Last Updated:** 2026-02-16
|
|
986
1293
|
**Angular Version:** 21
|