From 12d0aaff1a78ba8d3750fa23027e6f58f9196e28 Mon Sep 17 00:00:00 2001 From: Johan Compagner Date: Tue, 20 Feb 2024 15:49:36 +0100 Subject: [PATCH] SVY-18890 upgrade to angular 17.x and also change the builder to the "application" (esbuild) builder moved to the new application builder had to change how dynamic lazy imports work (import(`${variable}xxx`)) for angular locales we just now copy them and include it our self through a dynamc variable import (this works because they are esm modules by itself already anyway) the problem could be that users can get a error in the console because that specific locale doesn't have a file, for example you need to use "nl-NL" instead of just "nl" Luxon is hardcoded now, so the dynamic imports just written out. This is because https://github.com/evanw/esbuild/issues/700 esbuild still doesn't do that under the hood. Same for the default calendar component (tempus-dominus) locales, those are also now hardcoded for now --- .../node/angular.json | 31 +++--- .../src/lib/calendar/calendar.ts | 46 ++++++--- .../node/src/ngclient/locale.service.ts | 94 ++++++++++++++++--- .../node/src/styles.css | 6 +- .../node/tsconfig.json | 1 - .../eclipse/ngclient/ui/IndexPageFilter.java | 2 +- .../ngclient/ui/WebPackagesListener.java | 11 ++- 7 files changed, 145 insertions(+), 46 deletions(-) diff --git a/com.servoy.eclipse.ngclient.ui/node/angular.json b/com.servoy.eclipse.ngclient.ui/node/angular.json index a53315f3c2..d28e67d87f 100644 --- a/com.servoy.eclipse.ngclient.ui/node/angular.json +++ b/com.servoy.eclipse.ngclient.ui/node/angular.json @@ -9,7 +9,7 @@ "projectType": "application", "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-devkit/build-angular:application", "options": { "preserveSymlinks": true, "sourceMap": { @@ -17,29 +17,38 @@ "styles": true, "vendor": false }, - "outputPath": "dist/app", + "outputPath": { + "base": "dist/app" + }, "index": "src/index.html", - "main": "src/main.ts", "tsConfig": "src/tsconfig.app.json", - "polyfills": "src/polyfills.ts", + "polyfills": [ + "src/polyfills.ts" + ], "assets": [ "src/assets", - "src/favicon.ico" + "src/favicon.ico", + { + "glob": "*.mjs", + "input": "../node_modules/@angular/common/locales", + "output": "/locales/angular" + } ], "styles": [ "@fortawesome/fontawesome-free/css/all.css", "src/styles.css" ], "scripts": [], - "vendorChunk": true, "extractLicenses": false, - "buildOptimizer": false, "optimization": false, - "namedChunks": true + "namedChunks": true, + "browser": "src/main.ts" }, "configurations": { "production": { - "outputPath": "dist/app", + "outputPath": { + "base": "dist/app" + }, "budgets": [ { "type": "anyComponentStyle", @@ -60,8 +69,6 @@ "sourceMap": false, "namedChunks": false, "extractLicenses": true, - "vendorChunk": false, - "buildOptimizer": true, "fileReplacements": [ { "replace": "src/environments/environment.ts", @@ -70,9 +77,7 @@ ] }, "development": { - "buildOptimizer": false, "optimization": false, - "vendorChunk": true, "extractLicenses": false, "sourceMap": true, "namedChunks": true diff --git a/com.servoy.eclipse.ngclient.ui/node/projects/servoydefault/src/lib/calendar/calendar.ts b/com.servoy.eclipse.ngclient.ui/node/projects/servoydefault/src/lib/calendar/calendar.ts index c69127bd1f..ae572a41b1 100644 --- a/com.servoy.eclipse.ngclient.ui/node/projects/servoydefault/src/lib/calendar/calendar.ts +++ b/com.servoy.eclipse.ngclient.ui/node/projects/servoydefault/src/lib/calendar/calendar.ts @@ -216,22 +216,42 @@ export class ServoyDefaultCalendar extends ServoyDefaultBaseField 0) { + let language = locale.toLowerCase(); + if (index > 0 && language !== 'ar-sa' && language !== 'sr-latn') { language = locale.substring(0, index); } language = language.toLowerCase(); - import(`@eonasdan/tempus-dominus/dist/locales/${language}.js`).then( - (module: { localization: { [key: string]: string | number} }) => { - const copy = Object.assign({}, module.localization); - copy.startOfTheWeek = this.config.localization.startOfTheWeek; - copy.hourCycle = this.config.localization.hourCycle; - this.config.localization = copy; - if (this.picker !== null) this.picker.updateOptions(this.config); - }, - () => { + + const moduleLoader = (module: { default: { localization: { [key: string]: string | number} }}) => { + const copy = Object.assign({}, module.default.localization); + copy.startOfTheWeek = this.config.localization.startOfTheWeek; + copy.hourCycle = this.config.localization.hourCycle; + this.config.localization = copy; + if (this.picker) this.picker.updateOptions(this.config); + } + const errorHandler = () => { this.log.info('Locale ' + locale + ' for calendar not found, default to english'); - }); + } + switch(language) { + case 'ar-sa': import('@eonasdan/tempus-dominus/dist/locales/ar-SA.js').then(moduleLoader,errorHandler); break; + case 'ar': import('@eonasdan/tempus-dominus/dist/locales/ar.js').then(moduleLoader,errorHandler); break; + case 'ca': import('@eonasdan/tempus-dominus/dist/locales/ca.js').then(moduleLoader,errorHandler); break; + case 'cs': import('@eonasdan/tempus-dominus/dist/locales/cs.js').then(moduleLoader,errorHandler); break; + case 'de': import('@eonasdan/tempus-dominus/dist/locales/de.js').then(moduleLoader,errorHandler); break; + case 'es': import('@eonasdan/tempus-dominus/dist/locales/es.js').then(moduleLoader,errorHandler); break; + case 'fi': import('@eonasdan/tempus-dominus/dist/locales/fi.js').then(moduleLoader,errorHandler); break; + case 'fr': import('@eonasdan/tempus-dominus/dist/locales/fr.js').then(moduleLoader,errorHandler); break; + case 'hr': import('@eonasdan/tempus-dominus/dist/locales/hr.js').then(moduleLoader,errorHandler); break; + case 'hy': import('@eonasdan/tempus-dominus/dist/locales/hy.js').then(moduleLoader,errorHandler); break; + case 'it': import('@eonasdan/tempus-dominus/dist/locales/it.js').then(moduleLoader,errorHandler); break; + case 'nl': import('@eonasdan/tempus-dominus/dist/locales/nl.js').then(moduleLoader,errorHandler); break; + case 'pl': import('@eonasdan/tempus-dominus/dist/locales/pl.js').then(moduleLoader,errorHandler); break; + case 'ro': import('@eonasdan/tempus-dominus/dist/locales/ro.js').then(moduleLoader,errorHandler); break; + case 'ru': import('@eonasdan/tempus-dominus/dist/locales/ru.js').then(moduleLoader,errorHandler); break; + case 'sl': import('@eonasdan/tempus-dominus/dist/locales/sl.js').then(moduleLoader,errorHandler); break; + case 'sr': import('@eonasdan/tempus-dominus/dist/locales/sr.js').then(moduleLoader,errorHandler); break; + case 'sr-latn': import('@eonasdan/tempus-dominus/dist/locales/sr-Latn.js').then(moduleLoader,errorHandler); break; + case 'tr': import('@eonasdan/tempus-dominus/dist/locales/tr.js').then(moduleLoader,errorHandler); break; + } } - } diff --git a/com.servoy.eclipse.ngclient.ui/node/src/ngclient/locale.service.ts b/com.servoy.eclipse.ngclient.ui/node/src/ngclient/locale.service.ts index 652f6f0f0d..a54bf10594 100644 --- a/com.servoy.eclipse.ngclient.ui/node/src/ngclient/locale.service.ts +++ b/com.servoy.eclipse.ngclient.ui/node/src/ngclient/locale.service.ts @@ -69,34 +69,102 @@ export class LocaleService { private setNumbroLocale(localeId: string, tryOnlyLanguage: boolean): Promise { if (numbro.language() === localeId) return Promise.resolve(); - return import(`numbro/languages/${localeId}`).then(module => { + + const moduleLoader = (module: { default: numbro.NumbroLanguage }) => { numbro.registerLanguage(module.default); numbro.setLanguage(localeId); - }).catch(e => { - const index = localeId.indexOf('-'); - if (index === -1) { - return this.setNumbroLocale(this.makeFullLocale(localeId), false); - } else if (tryOnlyLanguage) { - return this.setNumbroLocale(localeId.substring(0, index), false); - } else { + } + const errorHandler = () => { this.log.warn('numbro locale for ' + localeId + ' didn\'t resolve, fallback to default en-US'); + } + switch(localeId) { + case 'bg': return import('numbro/languages/bg.js').then(moduleLoader,errorHandler); + case 'cs-CZ': return import('numbro/languages/cs-CZ.js').then(moduleLoader,errorHandler); + case 'da-DK': return import('numbro/languages/da-DK.js').then(moduleLoader,errorHandler); + case 'de-AT': return import('numbro/languages/de-AT.js').then(moduleLoader,errorHandler); + case 'de-CH': return import('numbro/languages/de-CH.js').then(moduleLoader,errorHandler); + case 'de-DE': return import('numbro/languages/de-DE.js').then(moduleLoader,errorHandler); + case 'de-LI': return import('numbro/languages/de-LI.js').then(moduleLoader,errorHandler); + case 'el': return import('numbro/languages/el.js').then(moduleLoader,errorHandler); + case 'en-AU': return import('numbro/languages/en-AU.js').then(moduleLoader,errorHandler); + case 'en-GB': return import('numbro/languages/en-GB.js').then(moduleLoader, errorHandler); + case 'en-IE': return import('numbro/languages/en-IE.js').then(moduleLoader, errorHandler); + case 'en-NZ': return import('numbro/languages/en-NZ.js').then(moduleLoader, errorHandler); + case 'en-ZA': return import('numbro/languages/en-ZA.js').then(moduleLoader, errorHandler); + case 'es-AR': return import('numbro/languages/es-AR.js').then(moduleLoader, errorHandler); + case 'es-CL': return import('numbro/languages/es-CL.js').then(moduleLoader, errorHandler); + case 'es-CO': return import('numbro/languages/es-CO.js').then(moduleLoader, errorHandler); + case 'es-CR': return import('numbro/languages/es-CR.js').then(moduleLoader, errorHandler); + case 'es-ES': return import('numbro/languages/es-ES.js').then(moduleLoader, errorHandler); + case 'es-MX': return import('numbro/languages/es-MX.js').then(moduleLoader, errorHandler); + case 'es-NI': return import('numbro/languages/es-NI.js').then(moduleLoader, errorHandler); + case 'es-PE': return import('numbro/languages/es-PE.js').then(moduleLoader, errorHandler); + case 'es-PR': return import('numbro/languages/es-PR.js').then(moduleLoader, errorHandler); + case 'es-SV': return import('numbro/languages/es-SV.js').then(moduleLoader, errorHandler); + case 'et-EE': return import('numbro/languages/et-EE.js').then(moduleLoader, errorHandler); + case 'fa-IR': return import('numbro/languages/fa-IR.js').then(moduleLoader, errorHandler); + case 'fi-FI': return import('numbro/languages/fi-FI.js').then(moduleLoader, errorHandler); + case 'fil-PH': return import('numbro/languages/fil-PH.js').then(moduleLoader, errorHandler); + case 'fr-CA': return import('numbro/languages/fr-CA.js').then(moduleLoader, errorHandler); + case 'fr-CH': return import('numbro/languages/fr-CH.js').then(moduleLoader, errorHandler); + case 'fr-FR': return import('numbro/languages/fr-FR.js').then(moduleLoader, errorHandler); + case 'he-IL': return import('numbro/languages/he-IL.js').then(moduleLoader, errorHandler); + case 'hu-HU': return import('numbro/languages/hu-HU.js').then(moduleLoader, errorHandler); + case 'id': return import('numbro/languages/id.js').then(moduleLoader, errorHandler); + case 'it-CH': return import('numbro/languages/it-CH.js').then(moduleLoader, errorHandler); + case 'it-IT': return import('numbro/languages/it-IT.js').then(moduleLoader, errorHandler); + case 'ja-JP': return import('numbro/languages/ja-JP.js').then(moduleLoader, errorHandler); + case 'ko-KR': return import('numbro/languages/ko-KR.js').then(moduleLoader, errorHandler); + case 'lv-LV': return import('numbro/languages/lv-LV.js').then(moduleLoader, errorHandler); + case 'nb-NO': return import('numbro/languages/nb-NO.js').then(moduleLoader, errorHandler); + case 'nb': return import('numbro/languages/nb.js').then(moduleLoader, errorHandler); + case 'nl-BE': return import('numbro/languages/nl-BE.js').then(moduleLoader, errorHandler); + case 'nl-NL': return import('numbro/languages/nl-NL.js').then(moduleLoader, errorHandler); + case 'nn': return import('numbro/languages/nn.js').then(moduleLoader, errorHandler); + case 'pl-PL': return import('numbro/languages/pl-PL.js').then(moduleLoader, errorHandler); + case 'pt-BR': return import('numbro/languages/pt-BR.js').then(moduleLoader, errorHandler); + case 'pt-PT': return import('numbro/languages/pt-PT.js').then(moduleLoader, errorHandler); + case 'ro-RO': return import('numbro/languages/ro-RO.js').then(moduleLoader, errorHandler); + case 'ro': return import('numbro/languages/ro.js').then(moduleLoader, errorHandler); + case 'ru-RU': return import('numbro/languages/ru-RU.js').then(moduleLoader, errorHandler); + case 'ru-UA': return import('numbro/languages/ru-UA.js').then(moduleLoader, errorHandler); + case 'sk-SK': return import('numbro/languages/sk-SK.js').then(moduleLoader, errorHandler); + case 'sl': return import('numbro/languages/sl.js').then(moduleLoader, errorHandler); + case 'sr-Cyrl-RS': return import('numbro/languages/sr-Cyrl-RS.js').then(moduleLoader, errorHandler); + case 'sv-SE': return import('numbro/languages/sv-SE.js').then(moduleLoader, errorHandler); + case 'th-TH': return import('numbro/languages/th-TH.js').then(moduleLoader, errorHandler); + case 'tr-TR': return import('numbro/languages/tr-TR.js').then(moduleLoader, errorHandler); + case 'uk-UA': return import('numbro/languages/uk-UA.js').then(moduleLoader, errorHandler); + case 'zh-CN': return import('numbro/languages/zh-CN.js').then(moduleLoader, errorHandler); + case 'zh-MO': return import('numbro/languages/zh-MO.js').then(moduleLoader, errorHandler); + case 'zh-SG': return import('numbro/languages/zh-SG.js').then(moduleLoader, errorHandler); + case 'zh-TW': return import('numbro/languages/zh-TW.js').then(moduleLoader, errorHandler); + default: { + const index = localeId.indexOf('-'); + if (index > 0 && tryOnlyLanguage) { + return this.setNumbroLocale(localeId.split('-')[0], false); + } + else if (index < 0) { + return this.setNumbroLocale(this.makeFullLocale(localeId), false); + } + break; } - }); + } } - + private setAngularLocale(language: string, country: string) { // angular locales are either or - const localeId = country !== undefined && country.length > 0 ? language.toLowerCase() + '-' + country.toUpperCase() : language.toLowerCase(); return new Promise((resolve, reject) => { - import( - `@/../../node_modules/@angular/common/locales/${localeId}.mjs`).then( + return import( + `/locales/angular/${localeId}.mjs?localeid=${localeId}`).then( module => { registerLocaleData(module.default, localeId); resolve(localeId); }, () => { - import(`@/../../node_modules/@angular/common/locales/${language.toLowerCase()}.mjs`).then(module => { + import(`/locales/angular/${language.toLowerCase()}.mjs?localeid=${language.toLowerCase()}`).then(module => { registerLocaleData(module.default, localeId.split('-')[0]); resolve(language.toLowerCase()); }, reject); diff --git a/com.servoy.eclipse.ngclient.ui/node/src/styles.css b/com.servoy.eclipse.ngclient.ui/node/src/styles.css index c23a51452d..39e8526cda 100644 --- a/com.servoy.eclipse.ngclient.ui/node/src/styles.css +++ b/com.servoy.eclipse.ngclient.ui/node/src/styles.css @@ -1,8 +1,8 @@ /* You can add global styles to this file, and also import other style files */ @import "assets/bootstrap-window/bootstrap-window.css"; -@import "~@ag-grid-community/styles/ag-grid.css"; -@import "~@ag-grid-community/styles/agGridClassicFont.css"; -@import "~@ag-grid-community/styles/ag-theme-alpine.css"; +@import "@ag-grid-community/styles/ag-grid.css"; +@import "@ag-grid-community/styles/agGridClassicFont.css"; +@import "@ag-grid-community/styles/ag-theme-alpine.css"; @import "assets/styles/servoy.css"; @import "assets/listformcomponent/listformcomponent.css"; diff --git a/com.servoy.eclipse.ngclient.ui/node/tsconfig.json b/com.servoy.eclipse.ngclient.ui/node/tsconfig.json index 3f02871d66..53fbdcc16e 100644 --- a/com.servoy.eclipse.ngclient.ui/node/tsconfig.json +++ b/com.servoy.eclipse.ngclient.ui/node/tsconfig.json @@ -1,7 +1,6 @@ { "compileOnSave": false, "compilerOptions": { - "downlevelIteration": true, "importHelpers": true, "module": "es2020", "sourceMap": true, diff --git a/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/IndexPageFilter.java b/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/IndexPageFilter.java index 859e1c04ee..3ffdfbb4bc 100644 --- a/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/IndexPageFilter.java +++ b/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/IndexPageFilter.java @@ -82,7 +82,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo File projectFolder = Activator.getInstance().getSolutionProjectFolder(); if (projectFolder != null) { - distFolder = new File(projectFolder, "dist/app"); + distFolder = new File(projectFolder, "dist/app/browser"); indexFile = new File(distFolder, "index.html"); } String solutionName = getSolutionNameFromURI(Paths.get(requestURI).normalize()); diff --git a/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/WebPackagesListener.java b/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/WebPackagesListener.java index 7c944ada06..5c59dae86b 100644 --- a/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/WebPackagesListener.java +++ b/com.servoy.eclipse.ngclient.ui/src/com/servoy/eclipse/ngclient/ui/WebPackagesListener.java @@ -249,7 +249,7 @@ protected IStatus run(IProgressMonitor monitor) boolean sourceChanged = false; if (ng2Services.size() > 0 || componentPackageSpecToReader.size() > 0) { - File distIndexFile = new File(projectFolder, "dist/app/index.html"); + File distIndexFile = new File(projectFolder, "dist/app/browser/index.html"); sourceChanged = !distIndexFile.exists(); if (sourceChanged) { @@ -930,6 +930,13 @@ else if (packageReader instanceof DirPackageReader) File packagesFolder = new File(projectFolder, "packages"); File packageFolder = new File(packagesFolder, packageName); + // quicly check tsconfig.json to get rid of warnings + File tsconfig = new File(packagesFolder, "tsconfig.json"); + if (!tsconfig.exists()) + { + FileUtils.copyFile(new File(projectFolder, "tsconfig.json"), tsconfig); + } + JSONObject sourcePathJson = null; String sourcePathContents = FileUtils.readFileToString(sourcePath.getLocation().toFile(), "UTF8"); sourcePathJson = new JSONObject(sourcePathContents); @@ -1306,7 +1313,7 @@ public static void exportNG2ToWar(ING2WarExportModel model) // create the production build new PackageCheckerJob("production_build", distributionSource, model.getModel()).run(model.getProgressMonitor()); // copy the production build - File distFolder = new File(distributionSource, "dist/app"); + File distFolder = new File(distributionSource, "dist/app/browser"); if (distFolder.exists()) { FileUtils.copyDirectory(distFolder, model.getExportLocation(), (path) -> !path.getName().equals("index.html"));