Upgraded to Angular v21

Removed tailwind

Moved to vitest from karma/jasmine
This commit is contained in:
2026-01-28 07:18:05 +00:00
parent e0766c5a2e
commit ca94f8f57e
19 changed files with 1656 additions and 2698 deletions

View File

@ -10,6 +10,7 @@ trim_trailing_whitespace = true
[*.ts] [*.ts]
quote_type = single quote_type = single
ij_typescript_use_double_quotes = false
[*.md] [*.md]
max_line_length = off max_line_length = off

2
bookie/.gitignore vendored
View File

@ -30,6 +30,7 @@ speed-measure-plugin*.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
!.vscode/mcp.json
.history/* .history/*
# Miscellaneous # Miscellaneous
@ -40,6 +41,7 @@ speed-measure-plugin*.json
/libpeerconnection.log /libpeerconnection.log
testem.log testem.log
/typings /typings
__screenshots__/
# System files # System files
.DS_Store .DS_Store

View File

@ -1,5 +0,0 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View File

@ -4,4 +4,12 @@ module.exports = {
singleQuote: true, singleQuote: true,
bracketSpacing: true, bracketSpacing: true,
printWidth: 120, printWidth: 120,
overrides: [
{
files: '*.html',
options: {
parser: 'angular',
},
},
],
}; };

View File

@ -23,13 +23,16 @@
"outputPath": { "outputPath": {
"base": "../frontend" "base": "../frontend"
}, },
"index": "src/index.html", "browser": "src/main.ts",
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "sass", "inlineStyleLanguage": "sass",
"assets": ["src/favicon.ico", "src/assets"], "assets": [
"styles": ["src/styles.sass"], {
"scripts": [], "glob": "**/*",
"browser": "src/main.ts" "input": "public"
}
],
"styles": ["src/styles.sass"]
}, },
"configurations": { "configurations": {
"production": { "production": {
@ -41,8 +44,8 @@
}, },
{ {
"type": "anyComponentStyle", "type": "anyComponentStyle",
"maximumWarning": "3kb", "maximumWarning": "4kb",
"maximumError": "6kb" "maximumError": "8kb"
} }
], ],
"outputHashing": "all" "outputHashing": "all"
@ -50,8 +53,7 @@
"development": { "development": {
"optimization": false, "optimization": false,
"extractLicenses": false, "extractLicenses": false,
"sourceMap": true, "sourceMap": true
"namedChunks": true
} }
}, },
"defaultConfiguration": "production" "defaultConfiguration": "production"
@ -71,21 +73,8 @@
}, },
"defaultConfiguration": "development" "defaultConfiguration": "development"
}, },
"extract-i18n": {
"builder": "@angular/build:extract-i18n",
"options": {
"buildTarget": "bookie:build"
}
},
"test": { "test": {
"builder": "@angular/build:karma", "builder": "@angular/build:unit-test"
"options": {
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "sass",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["@angular/material/prebuilt-themes/azure-blue.css", "src/styles.sass"],
"scripts": []
}
}, },
"lint": { "lint": {
"builder": "@angular-eslint/builder:lint", "builder": "@angular-eslint/builder:lint",

View File

@ -1,28 +1,29 @@
// @ts-check // @ts-check
const eslint = require('@eslint/js'); const eslint = require('@eslint/js');
const { defineConfig } = require('eslint/config');
const tseslint = require('typescript-eslint'); const tseslint = require('typescript-eslint');
const angular = require('angular-eslint'); const angular = require('angular-eslint');
const eslintConfigPrettier = require('eslint-config-prettier'); const eslintConfigPrettier = require('eslint-config-prettier');
const unusedImports = require('eslint-plugin-unused-imports'); const unusedImports = require('eslint-plugin-unused-imports');
const perfectionist = require('eslint-plugin-perfectionist'); const perfectionist = require('eslint-plugin-perfectionist');
module.exports = tseslint.config( module.exports = defineConfig([
{ {
files: ['**/*.ts'], files: ['**/*.ts'],
ignores: ['**/*.spec.ts'],
extends: [ extends: [
eslint.configs.recommended, eslint.configs.recommended,
...tseslint.configs.recommended, tseslint.configs.recommended,
...tseslint.configs.stylistic, tseslint.configs.stylistic,
...angular.configs.tsRecommended, angular.configs.tsRecommended,
eslintConfigPrettier, eslintConfigPrettier,
], ],
languageOptions: { languageOptions: {
parserOptions: { parserOptions: {
project: './tsconfig.json', // <-- REQUIRED project: './tsconfig.app.json', // <-- REQUIRED
tsconfigRootDir: __dirname, tsconfigRootDir: __dirname,
}, },
}, },
processor: angular.processInlineTemplates, processor: angular.processInlineTemplates,
plugins: { plugins: {
unusedImports: unusedImports, unusedImports: unusedImports,
@ -69,10 +70,7 @@ module.exports = tseslint.config(
}, },
{ {
files: ['**/*.html'], files: ['**/*.html'],
extends: [ extends: [angular.configs.templateRecommended, angular.configs.templateAccessibility],
...angular.configs.templateRecommended,
// ...angular.configs.templateAccessibility,
],
rules: {}, rules: {},
}, },
); ]);

View File

@ -7,56 +7,42 @@
"build": "ng build", "build": "ng build",
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development"
"eslint": "eslint",
"prettier": "prettier",
"husky": "husky"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/cdk": "^20.0.4", "@angular/cdk": "^21.1.1",
"@angular/common": "^20.0.6", "@angular/common": "^21.1.1",
"@angular/compiler": "^20.0.6", "@angular/compiler": "^21.1.1",
"@angular/core": "^20.0.6", "@angular/core": "^21.1.1",
"@angular/forms": "^20.0.6", "@angular/forms": "^21.1.1",
"@angular/material": "^20.0.4", "@angular/material": "^21.1.1",
"@angular/material-moment-adapter": "^20.0.4", "@angular/material-moment-adapter": "^21.1.1",
"@angular/platform-browser": "^20.0.6", "@angular/platform-browser": "^21.1.1",
"@angular/platform-browser-dynamic": "^20.0.6", "@angular/platform-browser-dynamic": "^21.1.1",
"@angular/router": "^20.0.6", "@angular/router": "^21.1.1",
"mathjs": "^14.0.1", "mathjs": "^15.1.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"rxjs": "~7.8.0", "rxjs": "~7.8.0",
"tslib": "^2.6.0" "tslib": "^2.6.0"
}, },
"devDependencies": { "devDependencies": {
"@angular/build": "^20.0.5", "@angular/build": "^21.1.1",
"@angular/cli": "^20.0.5", "@angular/cli": "^21.1.1",
"@angular/compiler-cli": "^20.0.6", "@angular/compiler-cli": "^21.1.1",
"@angular/language-service": "^20.0.6", "angular-eslint": "^21.1.0",
"@tailwindcss/postcss": "^4.1.11",
"@types/jasmine": "~5.1.4",
"angular-eslint": "^20.1.1",
"autoprefixer": "^10.4.19",
"eslint": "^9.28.0", "eslint": "^9.28.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.5",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-perfectionist": "^5.4.0",
"eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-unused-imports": "^4.1.4",
"husky": "^9.1.7", "husky": "^9.1.7",
"jasmine-core": "^5.5.0",
"karma": "^6.4.3",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "^2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"lint-staged": "^16.1.2", "lint-staged": "^16.1.2",
"postcss": "^8.5.6",
"prettier": "^3.4.2", "prettier": "^3.4.2",
"standard-version": "^9.5.0", "standard-version": "^9.5.0",
"tailwindcss": "^4.1.11", "typescript": "~5.9.3",
"typescript": "~5.8.3", "typescript-eslint": "^8.33.1",
"typescript-eslint": "^8.33.1" "vitest": "^4.0.8"
}, },
"husky": { "husky": {
"hooks": { "hooks": {

View File

@ -2,9 +2,9 @@ import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { Observable, of as observableOf } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { PagedResult } from 'src/app/core/paged-result';
import { Customer } from '../../core/customer'; import { Customer } from '../../core/customer';
import { PagedResult } from '../../core/paged-result';
export class CustomerListDatasource extends DataSource<Customer> { export class CustomerListDatasource extends DataSource<Customer> {
constructor( constructor(

View File

@ -9,9 +9,9 @@ import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table'; import { MatTableModule } from '@angular/material/table';
import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { debounceTime, distinctUntilChanged, Observable } from 'rxjs'; import { debounceTime, distinctUntilChanged, Observable } from 'rxjs';
import { PagedResult } from 'src/app/core/paged-result';
import { Customer } from '../../core/customer'; import { Customer } from '../../core/customer';
import { PagedResult } from '../../core/paged-result';
import { CustomerListDatasource } from './customer-list-datasource'; import { CustomerListDatasource } from './customer-list-datasource';
@Component({ @Component({
@ -65,7 +65,7 @@ export class CustomerListComponent implements OnInit, AfterViewInit {
} }
this.route.data.subscribe((value) => { this.route.data.subscribe((value) => {
const data = value as { data: PagedResult<Customer> }; const data = value as { data: PagedResult<Customer> };
data.data.items.forEach((c) => (c.discounts = c.discounts.filter((d) => d.discount !== 0))); data.data.items.forEach((c: Customer) => (c.discounts = c.discounts.filter((d) => d.discount !== 0)));
this.data = data.data; this.data = data.data;
this.dataSource = new CustomerListDatasource(this.data, this.paginator, this.sort); this.dataSource = new CustomerListDatasource(this.data, this.paginator, this.sort);
this.cdr.detectChanges(); this.cdr.detectChanges();

View File

@ -25,6 +25,7 @@
<mat-nested-tree-node *matTreeNodeDef="let node" class="mat-tree-node" [class.leaf-node]="!hasChild(0, node)"> <mat-nested-tree-node *matTreeNodeDef="let node" class="mat-tree-node" [class.leaf-node]="!hasChild(0, node)">
<li class="mat-tree-node"> <li class="mat-tree-node">
<!-- use a disabled button to provide padding for tree leaf --> <!-- use a disabled button to provide padding for tree leaf -->
<!-- eslint-disable-next-line @angular-eslint/template/elements-content -->
<button mat-icon-button disabled></button> <button mat-icon-button disabled></button>
<mat-checkbox <mat-checkbox
class="checklist-leaf-node" class="checklist-leaf-node"

View File

@ -7,8 +7,8 @@ import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/materia
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MenuCategory } from 'src/app/core/menu-category';
import { MenuCategory } from '../../core/menu-category';
import { StockKeepingUnit } from '../../core/product'; import { StockKeepingUnit } from '../../core/product';
@Component({ @Component({

View File

@ -7,7 +7,8 @@ import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/materia
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { Regime } from 'src/app/core/regime';
import { Regime } from '../../core/regime';
@Component({ @Component({
selector: 'app-bill-number', selector: 'app-bill-number',

View File

@ -6,8 +6,8 @@ import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { Regime } from 'src/app/core/regime';
import { Regime } from '../../core/regime';
import { Table } from '../../core/table'; import { Table } from '../../core/table';
import { BillNumberComponent } from '../bill-number/bill-number.component'; import { BillNumberComponent } from '../bill-number/bill-number.component';

View File

@ -9,8 +9,8 @@ import { MatSelectModule } from '@angular/material/select';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { round } from 'mathjs'; import { round } from 'mathjs';
import { Regime } from 'src/app/core/regime';
import { Regime } from '../../core/regime';
import { Tax } from '../../core/tax'; import { Tax } from '../../core/tax';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { TaxService } from '../tax.service'; import { TaxService } from '../tax.service';

View File

@ -1,8 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,ts}'],
theme: {
extend: {},
},
plugins: [],
};

View File

@ -5,6 +5,6 @@
"outDir": "../frontend", "outDir": "../frontend",
"types": [] "types": []
}, },
"files": ["src/main.ts"], "include": ["src/**/*.ts"],
"include": ["src/**/*.d.ts"] "exclude": ["src/**/*.spec.ts"]
} }

View File

@ -1,8 +1,8 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{ {
"compileOnSave": false, "compileOnSave": false,
"compilerOptions": { "compilerOptions": {
"baseUrl": "./",
"outDir": "../frontend", "outDir": "../frontend",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"strict": true, "strict": true,
@ -11,21 +11,25 @@
"noImplicitReturns": true, "noImplicitReturns": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "isolatedModules": true,
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true, "experimentalDecorators": true,
"moduleResolution": "bundler",
"importHelpers": true, "importHelpers": true,
"target": "ES2022", "target": "ES2022",
"module": "ES2022", "module": "preserve"
"useDefineForClassFields": false,
"lib": ["ES2022", "dom"]
}, },
"angularCompilerOptions": { "angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false, "enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true, "strictInjectionParameters": true,
"strictInputAccessModifiers": true, "strictInputAccessModifiers": true,
"strictTemplates": true "strictTemplates": true
} },
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
} }

View File

@ -3,7 +3,7 @@
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "./out-tsc/spec", "outDir": "./out-tsc/spec",
"types": ["jasmine"] "types": ["vitest/globals"]
}, },
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"] "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
} }

File diff suppressed because it is too large Load Diff