Skip to content

Commit d091f9e

Browse files
authored
Merge pull request #9 from Quenary/code-examples
Code examples
2 parents c58f051 + 615548d commit d091f9e

25 files changed

+429
-90
lines changed

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cardholder-pwa",
3-
"version": "0.0.11",
3+
"version": "0.0.12",
44
"scripts": {
55
"ng": "ng",
66
"start": "ng serve --port=4207 --open",

frontend/public/i18n/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"NAME": "Name",
6363
"DESCRIPTION": "Description",
6464
"COLOR": "Color",
65+
"CODE_FORMAT_WARN": "The app now uses different names for code types. Save the card with the new code type.",
6566
"SCAN": {
6667
"PERMISSION_ERROR": "Access to video device is denied or feature is not supported.",
6768
"SELECT_SOURCE": "Select source",
@@ -132,6 +133,7 @@
132133
"HOMEPAGE": "Home page",
133134
"IMAGE_VERSION": "Docker image version",
134135
"BACKEND_VERSION": "API version",
135-
"FRONTEND_VERSION": "Web App version"
136+
"FRONTEND_VERSION": "Web App version",
137+
"EXAMPLES": "Supported codes examples"
136138
}
137139
}

frontend/public/i18n/ru.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"NAME": "Наименование",
6363
"DESCRIPTION": "Описание",
6464
"COLOR": "Цвет",
65+
"CODE_FORMAT_WARN": "Теперь приложение использует другие наименования для типов кодов. Сохраните карточку с новым типом кода.",
6566
"SCAN": {
6667
"PERMISSION_ERROR": "Доступ к видеоустройству запрещен или функция не поддерживается.",
6768
"SELECT_SOURCE": "Выбрать источник",
@@ -132,6 +133,7 @@
132133
"HOMEPAGE": "Домашняя страница",
133134
"IMAGE_VERSION": "Версия Docker-образа",
134135
"BACKEND_VERSION": "Версия API-приложения",
135-
"FRONTEND_VERSION": "Версия WEB-приложения"
136+
"FRONTEND_VERSION": "Версия WEB-приложения",
137+
"EXAMPLES": "Примеры поддерживаемых кодов"
136138
}
137139
}

frontend/src/app/app.component.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ export class AppComponent {
8282
icon: 'admin_panel_settings',
8383
link: '/admin',
8484
},
85-
{
86-
name: translates.ABOUT,
87-
icon: 'info_outlined',
88-
link: '/about',
89-
},
9085
]
9186
: []),
87+
{
88+
name: translates.ABOUT,
89+
icon: 'info_outlined',
90+
link: '/about',
91+
},
9292
{
9393
name: translates.EXIT,
9494
icon: 'logout',

frontend/src/app/app.routes.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const routes: Routes = [
2323
redirectTo: '/cards',
2424
pathMatch: 'full',
2525
},
26+
// UNAUTHORIZED
2627
{
2728
path: 'auth',
2829
title: titleTranslate('NAV.AUTH'),
@@ -37,6 +38,27 @@ export const routes: Routes = [
3738
(c) => c.RegisterComponent
3839
),
3940
},
41+
{
42+
path: 'password-recovery',
43+
title: titleTranslate('NAV.PASSWORD_RECOVERY'),
44+
children: [
45+
{
46+
path: 'request',
47+
loadComponent: () =>
48+
import(
49+
'./features/password-recovery-request/password-recovery-request.component'
50+
).then((c) => c.PasswordRecoveryRequestComponent),
51+
},
52+
{
53+
path: 'submit',
54+
loadComponent: () =>
55+
import(
56+
'./features/password-recovery-submit/password-recovery-submit.component'
57+
).then((c) => c.PasswordRecoverySubmitComponent),
58+
},
59+
],
60+
},
61+
// AUTHORIZED
4062
{
4163
path: 'cards',
4264
canActivate: [authGuard],
@@ -80,36 +102,17 @@ export const routes: Routes = [
80102
import('./features/user/user.component').then((c) => c.UserComponent),
81103
},
82104
{
83-
path: 'password-recovery',
84-
title: titleTranslate('NAV.PASSWORD_RECOVERY'),
85-
children: [
86-
{
87-
path: 'request',
88-
loadComponent: () =>
89-
import(
90-
'./features/password-recovery-request/password-recovery-request.component'
91-
).then((c) => c.PasswordRecoveryRequestComponent),
92-
},
93-
{
94-
path: 'submit',
95-
loadComponent: () =>
96-
import(
97-
'./features/password-recovery-submit/password-recovery-submit.component'
98-
).then((c) => c.PasswordRecoverySubmitComponent),
99-
},
100-
],
105+
path: 'admin',
106+
title: titleTranslate('NAV.ADMIN'),
107+
canActivate: [authGuard, adminGuard, isOnlineGuard],
108+
loadComponent: () =>
109+
import('./features/admin/admin.component').then((c) => c.AdminComponent),
101110
},
102111
{
103112
path: 'about',
104113
title: titleTranslate('NAV.ABOUT'),
114+
canActivate: [authGuard],
105115
loadComponent: () =>
106116
import('./features/about/about.component').then((c) => c.AboutComponent),
107117
},
108-
{
109-
path: 'admin',
110-
title: titleTranslate('NAV.ADMIN'),
111-
canActivate: [authGuard, adminGuard],
112-
loadComponent: () =>
113-
import('./features/admin/admin.component').then((c) => c.AdminComponent),
114-
},
115118
];

frontend/src/app/entities/cards/cards-const.ts

Lines changed: 145 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { BarcodeFormat } from '@zxing/browser';
2-
1+
import type { BarcodeFormat } from '@zxing/browser';
2+
import type bwip from '@bwip-js/browser';
33
/**
44
* Key-key mapping for zxing codes.
55
* Use as main enum of codes of application.
@@ -45,37 +45,154 @@ export const EBarcodeFormat: { [K in keyof typeof BarcodeFormat & string]: K } =
4545
* Zxing to bwip codes map.
4646
* Null values is not supported in bwip.
4747
*/
48-
export const ZxingToBwipMap: Record<keyof typeof BarcodeFormat, string | null> =
49-
{
50-
// 2D barcodes
51-
AZTEC: 'azteccode',
52-
DATA_MATRIX: 'datamatrix',
53-
MAXICODE: null,
54-
PDF_417: 'pdf417',
55-
QR_CODE: 'qrcode',
56-
// 1D barcodes
57-
CODABAR: 'rationalizedCodabar',
58-
CODE_39: 'code39',
59-
CODE_93: 'code93',
60-
CODE_128: 'code128',
61-
EAN_8: 'ean8',
62-
EAN_13: 'ean13',
63-
ITF: 'interleaved2of5',
64-
UPC_A: 'upca',
65-
UPC_E: 'upce',
66-
UPC_EAN_EXTENSION: null,
67-
// RSS formats
68-
RSS_14: 'rss14',
69-
RSS_EXPANDED: 'rssexpanded',
70-
};
48+
export const ZxingToBwipMap: Record<
49+
keyof typeof BarcodeFormat,
50+
(keyof typeof EBwipBcid & keyof typeof bwip) | null
51+
> = {
52+
// 2D barcodes
53+
AZTEC: 'azteccode',
54+
DATA_MATRIX: 'datamatrix',
55+
MAXICODE: 'maxicode',
56+
PDF_417: 'pdf417',
57+
QR_CODE: 'qrcode',
58+
// 1D barcodes
59+
CODABAR: 'rationalizedCodabar',
60+
CODE_39: 'code39',
61+
CODE_93: 'code93',
62+
CODE_128: 'code128',
63+
EAN_8: 'ean8',
64+
EAN_13: 'ean13',
65+
ITF: 'interleaved2of5',
66+
UPC_A: 'upca',
67+
UPC_E: 'upce',
68+
UPC_EAN_EXTENSION: null,
69+
// RSS formats
70+
RSS_14: null,
71+
RSS_EXPANDED: null,
72+
};
7173

7274
/**
7375
* Check if code type is supported
7476
* @param code_type code type
7577
* @returns
7678
*/
7779
export const isValidCodeType = (code_type: string): boolean => {
78-
return (
79-
!!code_type && !!ZxingToBwipMap[code_type as keyof typeof BarcodeFormat]
80-
);
80+
return !!code_type && (code_type in EBwipBcid || code_type in ZxingToBwipMap);
8181
};
82+
83+
/**
84+
* Enum of bwip-js supported codes.
85+
* It is also the
86+
*/
87+
export enum EBwipBcid {
88+
auspost = 'auspost',
89+
azteccode = 'azteccode',
90+
azteccodecompact = 'azteccodecompact',
91+
aztecrune = 'aztecrune',
92+
bc412 = 'bc412',
93+
channelcode = 'channelcode',
94+
codablockf = 'codablockf',
95+
code11 = 'code11',
96+
code128 = 'code128',
97+
code16k = 'code16k',
98+
code2of5 = 'code2of5',
99+
code32 = 'code32',
100+
code39 = 'code39',
101+
code39ext = 'code39ext',
102+
code49 = 'code49',
103+
code93 = 'code93',
104+
code93ext = 'code93ext',
105+
codeone = 'codeone',
106+
coop2of5 = 'coop2of5',
107+
daft = 'daft',
108+
databarexpanded = 'databarexpanded',
109+
databarexpandedcomposite = 'databarexpandedcomposite',
110+
databarexpandedstacked = 'databarexpandedstacked',
111+
databarexpandedstackedcomposite = 'databarexpandedstackedcomposite',
112+
databarlimited = 'databarlimited',
113+
databarlimitedcomposite = 'databarlimitedcomposite',
114+
databaromni = 'databaromni',
115+
databaromnicomposite = 'databaromnicomposite',
116+
databarstacked = 'databarstacked',
117+
databarstackedcomposite = 'databarstackedcomposite',
118+
databarstackedomni = 'databarstackedomni',
119+
databarstackedomnicomposite = 'databarstackedomnicomposite',
120+
databartruncated = 'databartruncated',
121+
databartruncatedcomposite = 'databartruncatedcomposite',
122+
datalogic2of5 = 'datalogic2of5',
123+
datamatrix = 'datamatrix',
124+
datamatrixrectangular = 'datamatrixrectangular',
125+
datamatrixrectangularextension = 'datamatrixrectangularextension',
126+
dotcode = 'dotcode',
127+
ean13 = 'ean13',
128+
ean13composite = 'ean13composite',
129+
ean14 = 'ean14',
130+
ean2 = 'ean2',
131+
ean5 = 'ean5',
132+
ean8 = 'ean8',
133+
ean8composite = 'ean8composite',
134+
flattermarken = 'flattermarken',
135+
'gs1-128' = 'gs1-128',
136+
'gs1-128composite' = 'gs1-128composite',
137+
'gs1-cc' = 'gs1-cc',
138+
gs1datamatrix = 'gs1datamatrix',
139+
gs1datamatrixrectangular = 'gs1datamatrixrectangular',
140+
gs1dldatamatrix = 'gs1dldatamatrix',
141+
gs1dlqrcode = 'gs1dlqrcode',
142+
gs1dotcode = 'gs1dotcode',
143+
gs1northamericancoupon = 'gs1northamericancoupon',
144+
gs1qrcode = 'gs1qrcode',
145+
hanxin = 'hanxin',
146+
hibcazteccode = 'hibcazteccode',
147+
hibccodablockf = 'hibccodablockf',
148+
hibccode128 = 'hibccode128',
149+
hibccode39 = 'hibccode39',
150+
hibcdatamatrix = 'hibcdatamatrix',
151+
hibcdatamatrixrectangular = 'hibcdatamatrixrectangular',
152+
hibcmicropdf417 = 'hibcmicropdf417',
153+
hibcpdf417 = 'hibcpdf417',
154+
hibcqrcode = 'hibcqrcode',
155+
iata2of5 = 'iata2of5',
156+
identcode = 'identcode',
157+
industrial2of5 = 'industrial2of5',
158+
interleaved2of5 = 'interleaved2of5',
159+
isbn = 'isbn',
160+
ismn = 'ismn',
161+
issn = 'issn',
162+
itf14 = 'itf14',
163+
japanpost = 'japanpost',
164+
kix = 'kix',
165+
leitcode = 'leitcode',
166+
mailmark = 'mailmark',
167+
mands = 'mands',
168+
matrix2of5 = 'matrix2of5',
169+
maxicode = 'maxicode',
170+
micropdf417 = 'micropdf417',
171+
microqrcode = 'microqrcode',
172+
msi = 'msi',
173+
onecode = 'onecode',
174+
pdf417 = 'pdf417',
175+
pdf417compact = 'pdf417compact',
176+
pharmacode = 'pharmacode',
177+
pharmacode2 = 'pharmacode2',
178+
planet = 'planet',
179+
plessey = 'plessey',
180+
posicode = 'posicode',
181+
postnet = 'postnet',
182+
pzn = 'pzn',
183+
qrcode = 'qrcode',
184+
rationalizedCodabar = 'rationalizedCodabar',
185+
raw = 'raw',
186+
rectangularmicroqrcode = 'rectangularmicroqrcode',
187+
royalmail = 'royalmail',
188+
sscc18 = 'sscc18',
189+
swissqrcode = 'swissqrcode',
190+
symbol = 'symbol',
191+
telepen = 'telepen',
192+
telepennumeric = 'telepennumeric',
193+
ultracode = 'ultracode',
194+
upca = 'upca',
195+
upcacomposite = 'upcacomposite',
196+
upce = 'upce',
197+
upcecomposite = 'upcecomposite',
198+
}

frontend/src/app/features/about/about.component.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,12 @@
2929
</span>
3030
</mat-list-item>
3131
</mat-list>
32+
<mat-expansion-panel>
33+
<mat-expansion-panel-header>
34+
{{ 'ABOUT.EXAMPLES' | translate }}
35+
</mat-expansion-panel-header>
36+
<ng-template matExpansionPanelContent>
37+
<app-code-examples></app-code-examples>
38+
</ng-template>
39+
</mat-expansion-panel>
3240
</div>

frontend/src/app/features/about/about.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AsyncPipe } from '@angular/common';
2-
import { Component, inject } from '@angular/core';
2+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
33
import {
44
MatList,
55
MatListItem,
@@ -11,6 +11,8 @@ import { SystemApiService } from 'src/app/entities/system/system-api.service';
1111
import { MatIcon } from '@angular/material/icon';
1212
import { catchError, from, of, retry } from 'rxjs';
1313
import { SnackService } from 'src/app/core/services/snack.service';
14+
import { CodeExamplesComponent } from '../code-examples/code-examples.component';
15+
import { MatExpansionModule } from '@angular/material/expansion';
1416

1517
@Component({
1618
selector: 'app-about',
@@ -22,9 +24,12 @@ import { SnackService } from 'src/app/core/services/snack.service';
2224
MatIcon,
2325
MatListItemTitle,
2426
MatListItemIcon,
27+
CodeExamplesComponent,
28+
MatExpansionModule,
2529
],
2630
templateUrl: './about.component.html',
2731
styleUrl: './about.component.scss',
32+
changeDetection: ChangeDetectionStrategy.OnPush,
2833
})
2934
export class AboutComponent {
3035
private readonly systemApiService = inject(SystemApiService);

frontend/src/app/features/admin/admin-settings/admin-settings.component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { AsyncPipe, DatePipe } from '@angular/common';
2-
import { Component, inject, OnInit } from '@angular/core';
2+
import {
3+
ChangeDetectionStrategy,
4+
Component,
5+
inject,
6+
OnInit,
7+
} from '@angular/core';
38
import { MatCheckbox } from '@angular/material/checkbox';
49
import { MatInput } from '@angular/material/input';
510
import { MatTableModule } from '@angular/material/table';
@@ -24,10 +29,11 @@ import { MatTooltip } from '@angular/material/tooltip';
2429
TranslateModule,
2530
DatePipe,
2631
NaiveDatePipe,
27-
MatTooltip
32+
MatTooltip,
2833
],
2934
templateUrl: './admin-settings.component.html',
3035
styleUrl: './admin-settings.component.scss',
36+
changeDetection: ChangeDetectionStrategy.OnPush,
3137
})
3238
export class AdminSettingsComponent implements OnInit {
3339
private readonly adminApiService = inject(AdminApiService);

0 commit comments

Comments
 (0)