diff --git a/README.md b/README.md index 9384f14af..6cd2a2542 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,6 @@ - Unit tests with Jest instead of Karma & Jasmine. - e2e tests with Cypress instead of Protractor. - PWA -- i18n - Dynamic titles and content meta tags. - TailwindCSS + Autoprefixer + PurgeCSS setup. - Dark mode and theme configuration. @@ -62,9 +61,8 @@ ``` Types of pages -+ = main page -- = response page - = regular page +public: everybody can see them +private: only logged in users can see them ``` - General @@ -236,7 +234,6 @@ yarn remove tailwindcss autoprefixer postcss ```console ├───app │ ├───@core -│ │ ├───core │ │ ├───directives │ │ │ └───click-outside │ │ ├───guards @@ -252,34 +249,36 @@ yarn remove tailwindcss autoprefixer postcss │ │ ├───footer │ │ ├───header │ │ └───layout -│ └───pages -│ ├───+auth -│ │ ├───forgot-password -│ │ ├───forgot-password-email-sent -│ │ ├───password-reset -│ │ ├───password-reset-failed -│ │ ├───password-reset-succeeded -│ │ ├───sign-in -│ │ ├───sign-up -│ │ └───_services -│ ├───+home -│ ├───+settings -│ │ ├───account -│ │ ├───appearance -│ │ ├───billing -│ │ ├───blocked-users -│ │ ├───notifications -│ │ ├───security -│ │ └───security-log -│ ├───+user -│ │ ├───my-profile -│ │ └───overview -│ ├───dashboard -│ └───_not-found +│ ├───pages +│ │ ├───private +│ │ │ ├───dashboard +│ │ │ ├───settings +│ │ │ │ ├───account +│ │ │ │ ├───appearance +│ │ │ │ ├───billing +│ │ │ │ ├───blocked-users +│ │ │ │ ├───notifications +│ │ │ │ ├───security +│ │ │ │ └───security-log +│ │ │ └───user +│ │ │ ├───my-profile +│ │ │ └───overview +│ │ └───public +│ │ ├───auth +│ │ │ ├───forgot-password +│ │ │ ├───forgot-password-email-sent +│ │ │ ├───password-reset +│ │ │ ├───password-reset-failed +│ │ │ ├───password-reset-succeeded +│ │ │ ├───sign-in +│ │ │ ├───sign-up +│ │ │ └───_services +│ │ ├───home +│ │ └───not-found +│ └───router ├───assets -├───environments -├───public │ └───icons +├───environments └───theme ├───01-base ├───02-components @@ -288,18 +287,14 @@ yarn remove tailwindcss autoprefixer postcss ## 🧙‍♂️ Commands -| Command | Description | NPM | Yarn | Background command | -| ------------- | ------------------------------------------------- | --------------------- | ------------------ | --------------------------------------------------------------- | -| ng | See available commands | npm run ng | yarn ng | ng | -| dev | Run your app in development mode & open app | npm run dev | yarn dev | ng serve -o | -| start | Run your app in development mode | npm start | yarn start | ng serve | -| start:es | Run your app in development mode in spanish | npm run start:es | yarn start:es | ng serve -c=es --port 4201 | -| build | Build your app | npm run build | yarn build | ng build | -| build:prod | Build your app ready for production | npm run build:prod | yarn build:prod | ng build --prod --build-optimizer --aot --stats-json | -| build:i18n | Build your multilingual app ready for production | npm run build:i18n | yarn build:i18n | ng build --prod --build-optimizer --aot --stats-json --localize | -| test | Run your unit tests | npm run test | yarn test | ng test | -| test:coverage | Run your unit tests & generates a coverage report | npm run test:coverage | yarn test:coverage | ng test --coverage | -| lint | Use ESLint to lint your app | npm run lint | yarn lint | ng lint | -| e2e | Run your e2e tests | npm run e2e | yarn e2e | ng e2e | -| i18n:extract | Extract i18n messages from i18n directives | npm run extract | yarn extract | ng extract-i18n --output-path locale --ivy | -| analyze | Open webpack-bundle-analyzer | npm run analyze | yarn analyze | webpack-bundle-analyzer dist/angular-boilerplate/stats.json | +| Command | Description | NPM | Yarn | Background command | +| ------------- | ------------------------------------------------- | --------------------- | ------------------ | ----------------------------------------------------------- | +| ng | See available commands | npm run ng | yarn ng | ng | +| start | Run your app in development mode | npm start | yarn start | ng serve | +| build | Build your app | npm run build | yarn build | ng build | +| build:prod | Build your app ready for production | npm run build:prod | yarn build:prod | ng build --prod --build-optimizer --aot --stats-json | +| test:unit | Run your unit tests | npm run test | yarn test | ng test | +| test:e2e | Run your e2e tests | npm run e2e | yarn e2e | ng e2e | +| test:coverage | Run your unit tests & generates a coverage report | npm run test:coverage | yarn test:coverage | ng test --coverage | +| lint | Use ESLint to lint your app | npm run lint | yarn lint | ng lint | +| analyze | Open webpack-bundle-analyzer | npm run analyze | yarn analyze | webpack-bundle-analyzer dist/angular-boilerplate/stats.json | diff --git a/angular.json b/angular.json index f1e30244b..a98e4b5d6 100644 --- a/angular.json +++ b/angular.json @@ -32,11 +32,9 @@ "assets": [ "src/favicon.ico", "src/assets", - "src/public" - ], - "styles": [ - "src/theme/styles.scss" + "src/manifest.webmanifest" ], + "styles": ["src/theme/styles.scss"], "scripts": [] }, "configurations": { @@ -68,11 +66,6 @@ ], "serviceWorker": true, "ngswConfigPath": "ngsw-config.json" - }, - "es": { - "localize": [ - "es" - ] } } }, @@ -84,40 +77,27 @@ "configurations": { "production": { "browserTarget": "angular-boilerplate:build:production" - }, - "es": { - "browserTarget": "angular-boilerplate:build:es" } } }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-boilerplate:build" - } - }, "test": { "builder": "@angular-builders/jest:run", "options": { "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.spec.json", "assets": [ - "src/public/favicon.ico", - "src/assets" - ], - "styles": [ - "src/theme/styles.scss" + "src/favicon.ico", + "src/assets", + "src/manifest.webmanifest" ], + "styles": ["src/theme/styles.scss"], "scripts": [] } }, "lint": { "builder": "@angular-eslint/builder:lint", "options": { - "lintFilePatterns": [ - "src/**/*.ts", - "src/**/*.html" - ] + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] } }, "e2e": { @@ -157,14 +137,8 @@ } } } - }, - "i18n": { - "sourceLocale": "en-US", - "locales": { - "es": "locale/messages.es.xlf" - } } } }, "defaultProject": "angular-boilerplate" -} \ No newline at end of file +} diff --git a/locale/messages.es.xlf b/locale/messages.es.xlf deleted file mode 100644 index 5671ee0b1..000000000 --- a/locale/messages.es.xlf +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - Repository - Repositorio - - src/app/@components/header/header.component.html - 13 - - - - Built in planet 🌎 by YOUR_NAME - Construído en el planeta 🌎 por TU_NOMBRE - - src/app/@components/footer/footer.component.html - 2,3 - - - - 👋 Welcome to Angular Boilerplate! - 👋 ¡Te damos la bienvenida a Angular Boilerplate! - - src/app/@containers/home/home.page.html - 4 - - - - ⚒️ Start building your SPA easily. ⚒️ - ⚒️ Comienza a crear tu SPA fácilmente. ⚒️ - - src/app/@containers/home/home.page.html - 6 - - - - - diff --git a/locale/messages.xlf b/locale/messages.xlf deleted file mode 100644 index df187d485..000000000 --- a/locale/messages.xlf +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Repository - - src/app/@components/header/header.component.html - 13 - - - - Built in planet 🌎 by YOUR_NAME - - - src/app/@components/footer/footer.component.html - 2,3 - - - - 👋 Welcome to Angular Boilerplate. - - src/app/@containers/home/home.page.html - 4 - - - - ⚒️ Start building your SPA easily. ⚒️ - - src/app/@containers/home/home.page.html - 5 - - - - - diff --git a/package.json b/package.json index 96eaccec4..00d22789f 100644 --- a/package.json +++ b/package.json @@ -5,17 +5,13 @@ "private": true, "scripts": { "ng": "ng", - "dev": "ng serve -o", "start": "ng serve", - "start:es": "ng serve -c=es --port 4201", "build": "ng build", "build:prod": "set NODE_ENV=production&& ng build --prod --build-optimizer --aot --stats-json", - "build:i18n": "set NODE_ENV=production&& ng build --prod --build-optimizer --aot --stats-json --localize", - "test": "ng test", + "test:unit": "ng test", + "test:e2e": "ng e2e", "test:coverage": "ng test --coverage", "lint": "ng lint", - "e2e": "ng e2e", - "i18n:extract": "ng extract-i18n --output-path locale --ivy", "analyze": "webpack-bundle-analyzer dist/angular-boilerplate/stats.json" }, "dependencies": { @@ -48,7 +44,7 @@ "@cypress/webpack-preprocessor": "5.7.0", "@types/jasmine": "~3.6.9", "@types/jest": "26.0.23", - "@types/node": "^14.14.39", + "@types/node": "^14.14.39", "@typescript-eslint/eslint-plugin": "4.22.0", "@typescript-eslint/parser": "4.22.0", "autoprefixer": "^10.2.5", diff --git a/src/app/@core/guards/auth.guard.ts b/src/app/@core/guards/auth.guard.ts index 9f90b0768..aeec93927 100644 --- a/src/app/@core/guards/auth.guard.ts +++ b/src/app/@core/guards/auth.guard.ts @@ -6,7 +6,7 @@ import { RouterStateSnapshot, UrlTree, } from '@angular/router'; -import { AuthService } from '@app/pages/+auth/_services/auth.service'; +import { AuthService } from '@app/pages/public/auth/_services/auth.service'; import { Path } from '@core/structs'; import { Observable } from 'rxjs'; diff --git a/src/app/@core/guards/no-auth.guard.ts b/src/app/@core/guards/no-auth.guard.ts index 1a585f5c0..5a35af1e3 100644 --- a/src/app/@core/guards/no-auth.guard.ts +++ b/src/app/@core/guards/no-auth.guard.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { CanActivate, Router, UrlTree } from '@angular/router'; -import { AuthService } from '@app/pages/+auth/_services/auth.service'; +import { AuthService } from '@app/pages/public/auth/_services/auth.service'; import { Path } from '@core/structs'; import { Observable } from 'rxjs'; @@ -18,7 +18,7 @@ export class NoAuthGuard implements CanActivate { const isLoggedIn = this.authService.isLoggedIn; if (isLoggedIn) { - this.router.navigate([Path.App]); + this.router.navigate([Path.Dashboard]); return false; } diff --git a/src/app/@core/structs/path.enum.ts b/src/app/@core/structs/path.enum.ts index 91a3ed120..6a58c377c 100644 --- a/src/app/@core/structs/path.enum.ts +++ b/src/app/@core/structs/path.enum.ts @@ -4,7 +4,6 @@ export enum Path { NotFound = '404', // Auth - Auth = '', SignIn = 'sign-in', SignUp = 'sign-up', ForgotPassword = 'forgot-password', @@ -14,8 +13,7 @@ export enum Path { PasswordResetSucceeded = 'password-reset-succeeded', // App base url - App = 'app', - Dashboard = '', + Dashboard = 'dashboard', // Settings Settings = 'settings', diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 7265346be..44c0fc7fd 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,184 +1,15 @@ import { NgModule } from '@angular/core'; -import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; -import { AuthGuard, NoAuthGuard } from '@core/guards'; -import { Path } from '@core/structs'; -import { NotFoundModule } from '@pages/_not-found/not-found.module'; - -const routes: Routes = [ - // ===== Uncomment if Path.Home is different from empty ===== - // { path: '', redirectTo: Path.Home, pathMatch: 'full' }, - - // Public - { - path: Path.Home, - loadChildren: () => - import('@pages/+home/home.module').then((m) => m.HomeModule), - }, - - // Auth - { - path: Path.Auth, - canActivate: [NoAuthGuard], - children: [ - { - path: Path.SignIn, - loadChildren: () => - import('@pages/+auth/sign-in/sign-in.module').then( - (m) => m.SignInModule, - ), - }, - { - path: Path.SignUp, - loadChildren: () => - import('@pages/+auth/sign-up/sign-up.module').then( - (m) => m.SignUpModule, - ), - }, - { - path: Path.ForgotPassword, - loadChildren: () => - import('@pages/+auth/forgot-password/forgot-password.module').then( - (m) => m.ForgotPasswordModule, - ), - }, - { - path: Path.ForgotPassword, - loadChildren: () => - import( - '@pages/+auth/forgot-password-email-sent/forgot-password-email-sent.module' - ).then((m) => m.ForgotPasswordEmailSentModule), - }, - { - path: Path.PasswordReset, - loadChildren: () => - import('@pages/+auth/password-reset/password-reset.module').then( - (m) => m.PasswordResetModule, - ), - }, - { - path: Path.PasswordResetSucceeded, - loadChildren: () => - import( - '@pages/+auth/password-reset-succeeded/password-reset-succeeded.module' - ).then((m) => m.PasswordResetSucceededModule), - }, - { - path: Path.PasswordResetFailed, - loadChildren: () => - import( - '@pages/+auth/password-reset-failed/password-reset-failed.module' - ).then((m) => m.PasswordResetFailedModule), - }, - ], - }, - - // App - { - path: Path.App, - canActivate: [AuthGuard], - children: [ - { - path: Path.Dashboard, - loadChildren: () => - import('@pages/dashboard/dashboard.module').then( - (m) => m.DashboardModule, - ), - }, - ], - }, - { - path: Path.Settings, - canActivate: [AuthGuard], - children: [ - { - path: Path.SettingsAccount, - loadChildren: () => - import('@pages/+settings/account/account.module').then( - (m) => m.AccountModule, - ), - }, - { - path: Path.SettingsAppearance, - loadChildren: () => - import('@pages/+settings/appearance/appearance.module').then( - (m) => m.AppearanceModule, - ), - }, - { - path: Path.SettingsBilling, - loadChildren: () => - import('@pages/+settings/billing/billing.module').then( - (m) => m.BillingModule, - ), - }, - { - path: Path.SettingsBlockedUsers, - loadChildren: () => - import('@pages/+settings/blocked-users/blocked-users.module').then( - (m) => m.BlockedUsersModule, - ), - }, - { - path: Path.SettingsNotifications, - loadChildren: () => - import('@pages/+settings/notifications/notifications.module').then( - (m) => m.NotificationsModule, - ), - }, - { - path: Path.SettingsSecurity, - loadChildren: () => - import('@pages/+settings/security/security.module').then( - (m) => m.SecurityModule, - ), - }, - { - path: Path.SettingsSecurityLog, - loadChildren: () => - import('@pages/+settings/security-log/security-log.module').then( - (m) => m.SecurityLogModule, - ), - }, - ], - }, - { - path: Path.Users, - canActivate: [AuthGuard], - children: [ - { - path: Path.UsersProfile, - loadChildren: () => - import('@pages/+user/my-profile/my-profile.module').then( - (m) => m.MyProfileModule, - ), - }, - { - path: Path.UsersOverview, - loadChildren: () => - import('@pages/+user/overview/overview.module').then( - (m) => m.OverviewModule, - ), - }, - ], - }, - - // Not found page (must go at the bottom) - { - path: '**', - loadChildren: () => - import('@pages/_not-found/not-found.module').then( - (m) => m.NotFoundModule, - ), - component: NotFoundModule, - }, -]; +import { PreloadAllModules, RouterModule } from '@angular/router'; +import { PRIVATE_ROUTES, PUBLIC_ROUTES, WILDCARD_ROUTE } from '@router/index'; @NgModule({ imports: [ - RouterModule.forRoot(routes, { - preloadingStrategy: PreloadAllModules, - relativeLinkResolution: 'legacy', - }), + RouterModule.forRoot( + [...PUBLIC_ROUTES, ...PRIVATE_ROUTES, WILDCARD_ROUTE], + { + preloadingStrategy: PreloadAllModules, + }, + ), ], exports: [RouterModule], }) diff --git a/src/app/app.component.html b/src/app/app.component.html index bad3f4018..982a5256d 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,9 +1,7 @@ -
- - - + + + - - - -
+ + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 71f1ec857..e047d7dfc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { AuthService } from '@app/pages/+auth/_services/auth.service'; import { SeoService } from '@core/services/seo'; import { ThemeService } from '@core/services/theme'; import { Path } from '@core/structs'; import { Observable } from 'rxjs'; +import { AuthService } from './pages/public/auth/_services/auth.service'; @Component({ selector: 'app-root', diff --git a/src/app/components/footer/footer.component.html b/src/app/components/footer/footer.component.html index 1adbf1656..c4b40bbd0 100644 --- a/src/app/components/footer/footer.component.html +++ b/src/app/components/footer/footer.component.html @@ -1,6 +1,5 @@ diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index 7d6f61111..74a8df6b6 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -1,4 +1,6 @@ -
+