ngx-los
v9.2.1
Published
[![npm version](https://badge.fury.io/js/ngx-los.svg)](https://badge.fury.io/js/ngx-los)
Downloads
99
Readme
ngx-los
Contenido
- Iniciando proyecto en Angular
- Requisitos
- Instalación
- SCSS
- HTML
- Configuración de enviroments
- Configuración de Angular CLI
- Configuración de package.json
- Configuración de Suscripciones de Graphql
- Configuración de Sentry
- Redux
- Errores de Graphql
- AppModule
- AppComponent HTML
- AppComponent TS
Iniciar proyecto en Angular
Para iniciar un proyecto que contenga la seguridad de LOS es necesario contar con la versión 9 de Angular, para validar que versión tienes instalada es necesario teclear en consola lo siguiente:
ng version
Se tendrá que mostrar en pantalla la versión de Angular CLI y tendrá que ser la 9 mas estable.
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.1.3
Node: 12.16.1
OS: win32 x64
Angular: 9.1.3
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
------------------------------------------------------------
@angular-devkit/architect 0.901.3
@angular-devkit/build-angular 0.901.3
@angular-devkit/build-ng-packagr 0.901.3
@angular-devkit/build-optimizer 0.901.3
@angular-devkit/build-webpack 0.901.3
@angular-devkit/core 9.1.3
@angular-devkit/schematics 9.1.3
@angular/cdk 9.2.1
@angular/flex-layout 9.0.0-beta.29
@angular/material 9.2.1
@ngtools/webpack 9.1.3
@schematics/angular 9.1.3
@schematics/update 0.901.3
ng-packagr 9.1.1
rxjs 6.5.5
typescript 3.8.3
webpack 4.42.0
Confirmando que tenemos la versión 9 mas estable, procedemos a crear el proyecto con el siguiente comando.
ng new [Nombre-aplicación] --style=scss
Nota: El nombre de las aplicaciones debe ser escrito en minúsculas y separadas por un signo de menos (-) en caso de ser dos palabras. Agregamos el argumento --style=scss para indicarle que queremos usar scss en nuestro proyecto
Creará la plantilla base de Angular necesaria para trabajar e instalará todos las dependencias de npm.
CREATE nombre-aplicacion/angular.json (3742 bytes)
CREATE nombre-aplicacion/package.json (1293 bytes)
CREATE nombre-aplicacion/README.md (1033 bytes)
CREATE nombre-aplicacion/tsconfig.json (489 bytes)
CREATE nombre-aplicacion/tslint.json (3125 bytes)
CREATE nombre-aplicacion/.editorconfig (274 bytes)
CREATE nombre-aplicacion/.gitignore (631 bytes)
CREATE nombre-aplicacion/browserslist (429 bytes)
CREATE nombre-aplicacion/karma.conf.js (1029 bytes)
CREATE nombre-aplicacion/tsconfig.app.json (210 bytes)
CREATE nombre-aplicacion/tsconfig.spec.json (270 bytes)
CREATE nombre-aplicacion/src/favicon.ico (948 bytes)
CREATE nombre-aplicacion/src/index.html (302 bytes)
CREATE nombre-aplicacion/src/main.ts (372 bytes)
CREATE nombre-aplicacion/src/polyfills.ts (2835 bytes)
CREATE nombre-aplicacion/src/styles.scss (80 bytes)
CREATE nombre-aplicacion/src/test.ts (753 bytes)
CREATE nombre-aplicacion/src/assets/.gitkeep (0 bytes)
CREATE nombre-aplicacion/src/environments/environment.prod.ts (51 bytes)
CREATE nombre-aplicacion/src/environments/environment.ts (662 bytes)
CREATE nombre-aplicacion/src/app/app.module.ts (314 bytes)
CREATE nombre-aplicacion/src/app/app.component.html (25725 bytes)
CREATE nombre-aplicacion/src/app/app.component.spec.ts (975 bytes)
CREATE nombre-aplicacion/src/app/app.component.ts (222 bytes)
CREATE nombre-aplicacion/src/app/app.component.scss (0 bytes)
CREATE nombre-aplicacion/e2e/protractor.conf.js (808 bytes)
CREATE nombre-aplicacion/e2e/tsconfig.json (214 bytes)
CREATE nombre-aplicacion/e2e/src/app.e2e-spec.ts (650 bytes)
CREATE nombre-aplicacion/e2e/src/app.po.ts (301 bytes)
- Installing packages...
√ Packages installed successfully.
Successfully initialized git.
Una vez finalice con la leyenda de Successfully initialized git.
tendremos listo nuestra plantilla base de Angular 9 lista para hacer la instalación de nuestra plantilla de seguridad.
Requisitos
Una vez creado el proyecto es necesario realizar la instalación de Angular Material mediante el siguiente comando.
ng add @angular/material
El proceso de instalación nos pedirá seleccionar un tema por defecto, seleccionamos Indigo/Pink. También nos preguntará si queremos establecer globalmente la tipografía de Angular Material, ademas de las animaciones del navegador, aceptamos ambas.
Skipping installation: Package already installed
? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink[ Preview: https://material.angular.io?theme=indigo-pink ]
? Set up global Angular Material typography styles? Yes
? Set up browser animations for Angular Material? Yes
```bash
Installing packages for tooling via npm.
Installed packages for tooling via npm.
UPDATE package.json (1357 bytes)
- Installing packages...
√ Packages installed successfully.
UPDATE src/app/app.module.ts (423 bytes)
UPDATE angular.json (3908 bytes)
UPDATE src/index.html (496 bytes)
UPDATE src/styles.scss (181 bytes)
(Opcional) Para verficar que se realizo la instalacion correctamente podemos mostrar un componente de Angular material en pantalla realizando la importacion del modulo corresponiente del componente que queremos usar, en este caso un
mat-slider
import { MatSliderModule } from '@angular/material/slider';
…
@NgModule ({....
imports: [...,
MatSliderModule,
…]
})
Agregamos el tag <mat-slider>
a nuestro app.component.html como sigue:
<mat-slider min="1" max="100" step="1" value="1"></mat-slider>
Ejecutamos nuestra aplicacion con el comando ng serve
ingresa en el explorador a la direccio http://localhost:4200
Deberias ver el componente mat-slider en pantalla.
Instalación
Para la instalación comenzaremos con la siguiente instrucción dentro del proyecto vacío.
npm i ngx-los
SCSS
Es necesario configurar el SCSS para heredar todos los temas diseñados para la plantilla, buscamos el archivo de estilos de capas localizado en src/styles.scss
y agregamos la siguiente línea.
@import "~ngx-los/theme.scss";
HTML
En la seccion <head>
agregamos la siguiente linea de codigo html
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons|Assistant|ZCOOL+XiaoWei"
rel="stylesheet"
/>
El cuerpo <body>
lo dejaremos de la siguiente manera.
<body>
<app-root>
<div class="app-loading">
<div class="logo"></div>
<svg class="spinner" viewBox="25 25 50 50">
<circle
class="path"
cx="50"
cy="50"
r="20"
fill="none"
stroke-width="2"
stroke-miterlimit="10"
/>
</svg>
</div>
</app-root>
</body>
Esto para dejar un "loading" cuando la pagina aun se este cargando.
Configuración de enviroments
Nota: Nota: Los archivos de ambiente deben hacer referencia al archivo package.json para realizar la importación del mismo es necesario agregar la siguiente configuracion en el archivo tsconfig.json.
{
"compilerOptions": {
...
"resolveJsonModule": true,
}
}
Para hacer la configuración de ambientes es necesario tener la siguiente estructura en los archivos localizados en src/enviroments/enviroment.ts
y src/enviroments/enviroment.prod.ts
con su respectiva información de ambiente.
El archivo tiene que contener lo siguiente
import * as packagejson from "../../package.json";
export const environment = {
production: false,
app: {
id: "",
version: packagejson.version,
commit: "{COMMIT}",
branch: "{BRANCH}",
clientId: "",
clientSecret: "",
urls: [
{
key: "oauth",
value: "http://host/url_endpoint_token",
},
{
key: "login",
value: "host/url_login",
},
],
sentry: {
dsn: "http://url_sentry",
showReportDialog: false,
},
},
template: {
storageName: "storage-name",
graphql: {
uri: "host/url_endpoint_graphql",
subscriptions: {
enabled: true,
uri: "ws://url_endpoint_graphql_subscriptions",
},
},
},
header: {
title: "Titulo de Apliacion",
theme: "nombre-tema",
darkTheme: false,
colorThemeVisible: true,
fullScreenVisible: true,
wishHappyBirthday: true,
},
sidemenu: {
menuOpen: true,
menuOpenApps: false,
selectRoomsVisible: true,
},
};
| Llave | Descripción |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| production
| Saber si el ambiente es producción
|
| urls
| Contiene todas las URLs necesarias para el proyecto
|
| urls.auth
| Validar credenciales de acceso
|
| urls.auth.host
| URL para validar credenciales de acceso
|
| urls.auth.path.token
| End point para solicitar el token de acceso
|
| urls.auth.path.userChangePassword
| End point para que el usuario pueda cambiar su contraseña
|
| app.id
| Id de la aplicación
|
| app.version
| Version de la aplicacion obtenida del archivo package.json
|
| app.commit
| Id de commit del Git (este campo lo remplaza automaticamente gitlab)
|
| app.branch
| Branch de Git (este campo lo remplaza automaticamente gitlab)
|
| app.clientId
| Identificador client de la aplicacion
|
| app.clientSecret
| Secreto de aplicación cliente
|
| app.urls
| Arreglo con las urls que usara la aplicacion
|
| app.urls[indice].key
| llave para accesar al elemento en el arreglo
|
| app.urls[indice].value
| valor de la url
|
| app.sentry.dsn
| (Data Source Name) es la URL que representa la configuracion requerida por sentry
|
| app.showReportDialog
| Indica si se debe mostrar el dialog de feedback de usuario cuando se presenta un error
|
| template.storageName
| Nombre de la llave que se usara para guardar el token de la aplicacion en el storage
|
| template.graphql.subscriptions.enabled
| Indica si el socket de suscripciones estara habilitado
|
| template.graphql.subscriptions.uri
| url del socket de suscripciónes de graphql
|
| template.graphql.uri
| url del endpoint de graphql que usará el template
|
| header.title
| Titulo de la aplicación
|
| header.theme
| Tema que usara por default nuestra aplicacion
|
| header.darkTheme
| Indica si la aplicacion usara el tema osucuro
|
| header.colorThemeVisible
| Indica si se mostrara visible la opcion para cambiar tema
|
| header.fullScreenVisible
| Indica si se mostrara visible la opcion para cambiar a pantalla completa
|
| header.wishHappyBirthday
| Indica si se mostrara una felicitacion cuando el empleado cumpla año
|
| sidemenu.menuOpen
| Indica si al ingresar al sistema el menu se mostrara abierto
|
| sidemenu.menuOpenApps
| Indica si al ingresar al sistema los menus de aplicaciones se mostraran abierto
|
| sidemenu.selectRoomsVisible
| Indica si al ingresar al sistema la aplicación mostrara el combo de salas a las que se tiene acceso
|
Es necesario también realizar una copia del archivo src/enviroments/enviroment.prod.ts
y renombrarlos de la siguiente manera src/enviroments/enviroment.dev.ts
y src/enviroments/enviroment.qa.ts
.
Configuración de Angular CLI
Abrimos el archivo angular.json ubicado en la raiz del proyecto,
a continuación ubicamos la siguiente propiedad projects/[nombre-proyecto]/architect/build/configurations
y agregamos la siguiente configuracion
"dev": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
]
},
"qa": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.qa.ts"
}
]
}
Configuración de package.json
Abrimos el archivo package.json ubicado en la raiz del proyecto,
en la propiedad scripts
agregamos la siguientes tareas:
"build:qa": "ng build --prod --configuration=qa",
"build:dev": "ng build --prod --configuration=dev",
Una vez realizado el paso anterior podremos compilar nuestra aplicación apuntando a cualquiera de los ambientes previamente definidos, por ejemplo la siguiente instruccion de terminal compiará la aplicacion para el ambiente dev
:
npm run build:dev
Suscripciónes de Graphql
En nuestro archivos environment ubicamos la propiedad template/graphql
y agregamos la siguiente sub propiedad:
subscriptions: {
enabled: true,
uri: 'ws://url_subscriptions'
}
Sentry
En nuestro archivos environment ubicamos la propiedad template/graphql/app
y agregamos la siguiente sub propiedad:
sentry: {
dsn: 'http://url_dsn',
showReportDialog: false,
}
Redux
Para hacer la configuración de Redux es necesario crear un archivo en la siguiente estructura src/app/app.redux.ts
con el siguiente contenido
import * as Template from "ngx-los";
import * as Auth from "ngx-los-auth";
export const reducers = {
auth: Auth.authReducers,
app: Template.appReducers,
room: Auth.roomReducers,
header: Template.headerReducers,
sidemenu: Template.sideMenuReducers,
footer: Template.footerReducers,
};
Manejo de errores de graphql
Es necesario crear el siguiente archivo: src/app/app.error.ts
import { HttpErrorResponse } from '@angular/common/http';
import { MatSnackBar } from '@angular/material/snack-bar';
import { onError } from 'apollo-link-error';
import { GraphQLError } from 'graphql';
import { environment } from '../environments/environment';
const getToken = (storageName) => {
const authStorage = localStorage.getItem(storageName);
if (authStorage) {
return JSON.parse(authStorage).access_token;
}
return '';
};
const hasErrorMessage = (grapqhlErrors: GraphQLError[], name: string): boolean => {
let hasError = false;
for (const error of grapqhlErrors) {
const messageError = typeof error.message === 'object' ? (error.message as any).error : error.message;
if (messageError === name) {
hasError = true;
}
}
return hasError;
};
const hasStatusCode = (grapqhlErrors: GraphQLError[], statusCode: number): boolean => {
let hasError = false;
for (const error of grapqhlErrors) {
const code: number = typeof error.message === 'object' ? (error.message as any).statusCode as number : Number(error.message);
if (code === statusCode) {
hasError = true;
}
}
return hasError;
};
const validateAuth = (graphqlErrors) => {
let message = '';
if (hasStatusCode(graphqlErrors, 401)) {
const token = getToken('los-auth');
if (token) {
message = 'No tienes los permisos necesarios para hacer esta acción';
} else {
const hash = '/login';
if (window.location.hash.indexOf(hash) > -1) {
} else {
const redirectUrl = window.location.href;
setTimeout(() => {
window.location.href = `${getUrl(environment.app.urls, 'login')}?URL_Ref=${redirectUrl}`;
}, 3000);
}
message = 'No has iniciado sesión, serás redireccionado en 3 segundos';
}
}
return message;
};
export function errorLink(snack: MatSnackBar) {
return onError((error) => {
let message = '';
if (error.graphQLErrors) {
message = validateAuth(error.graphQLErrors);
}
if (error.networkError) {
const networkError: HttpErrorResponse = error.networkError as HttpErrorResponse;
if (networkError.status === 0) {
message = 'Revisa la conexión con el servidor de GraphQL';
}
if (networkError.status === 404) {
message = 'Servidor de GraphQL no encontrado';
}
}
if (message) {
snack.open(message, '', { duration: 3000, panelClass: 'snackbar-error' });
}
});
}
const getUrl = (urls: any[], key: string) => {
const item = urls.find(x => x.key === key);
if (item) {
return item.value;
} else {
return '';
}
};
// ###### Escribe aquí tus funciones
// Code...
// ######
AppModule
import { MatPasswordStrengthModule } from "@angular-material-extensions/password-strength";
import { HttpClientModule } from "@angular/common/http";
import { NgModule } from "@angular/core";
import { MatButtonModule } from "@angular/material/button";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { StoreModule } from "@ngrx/store";
import { StoreDevtoolsModule } from "@ngrx/store-devtools";
import { ApolloBoostModule } from "apollo-angular-boost";
import { LosTemplateModule } from "ngx-los";
import { LosAuthModule } from "ngx-los-auth";
import { environment } from "../environments/environment";
import { errorLink } from "../app/app.error";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { reducers } from "./app.redux";
const options = {
storageName: environment.template.storageName,
graphql: {
uri: environment.template.graphql.uri,
subscriptions: environment.template.graphql.subscriptions,
errorLink,
},
sentry: environment.app.sentry,
};
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
ApolloBoostModule,
HttpClientModule,
LosTemplateModule.forRoot(options),
LosAuthModule.forRoot(options),
StoreModule.forRoot(
{ ...reducers },
{
runtimeChecks: {
strictStateImmutability: false,
strictActionImmutability: false,
},
}
),
StoreDevtoolsModule.instrument({
maxAge: 25,
logOnly: environment.production,
}),
MatButtonModule,
MatPasswordStrengthModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
AppComponent HTML
Localizamos el archivo src/app/app.component.html
borramos su contenido y dejamos la siguiente configuración.
<los-header></los-header>
<los-side-menu></los-side-menu>
<los-footer></los-footer>
AppComponent TS
Localizamos el archivo src/app/app.component.ts
dejamos la siguiente configuración.
import { Component, OnInit } from '@angular/core';
import { LosAppService, LosHeaderService, LosSideMenuService } from 'ngx-los';
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(
private losAppService: LosAppService,
private losHeaderService: LosHeaderService,
private losSideMenuService: LosSideMenuService,
) { }
async ngOnInit() {
this.losAppService.set(environment.app);
this.losHeaderService.set(environment.header);
this.losSideMenuService.set(environment.sidemenu);
}
}