File

src/lib/core/service.ts

Constructor

constructor(titleService: Title, noficationService: NotificationsService, componentFactoryResolver: ComponentFactoryResolver, breakpointObserver: BreakpointObserver, titlecasePipe: TitleCasePipe)

Methods

updateMenu
updateMenu(menu: DropdownItem[])

Actualiza el ménu de la aplicación

Parameters :
  • menu

    Items del menú

Returns: void
updateTitle
updateTitle(title: string | PlexTitle[])

Actualiza el título del navegador y breadcrumb

Parameters :
  • title

    Título

Returns: void
updateAppStatus
updateAppStatus(status: any)

Actualiza el estado de la aplicación en el navbar

Parameters :
  • status

    Objeto de estado

Returns: void
updateUserInfo
updateUserInfo(user: any)

Actualiza la información del usuario actual

Parameters :
  • user

    Objeto con datos de usuario

Returns: void
confirm
confirm(params: { content: string; title: string; confirmButtonText: string; cancelButtonText: string; })

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un diálogo de confirmación

Parameters :
  • content

    Texto

  • title

    Título

Returns: void

Devuelve una promise se que resuelve con true/false cuando el diálogo se cierra

confirm
confirm(content: string, title: string, confirmButtonText: string, cancelButtonText: string)

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un diálogo de confirmación

Returns: void
confirm
confirm(content: any, title: string, confirmButtonText: string, cancelButtonText: string)

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un diálogo de confirmación

Returns: Promise<any>
info
info(type: String, content: String, title: String, timeOut: Number, confirmButtonText: String)

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un mensaje invasivo al usuario

Parameters :
  • type

    success, danger (error), warning, info

  • content

    Texto del mensaje

  • title

    Título

  • timeOut

    Tiempo en ms cuando se oculta el mensaje. Por default no se oculta.

Returns: void
info
info(params: { type: String; content: String; title: String; confirmButtonText: String; timeOut?: Number; })

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un mensaje invasivo al usuario

Returns: void
info
info(type: any, content: string, title: string, timeOut: number, confirmButtonText: string)

TODO: Migrar para usar 1 sólo objeto con su type como param
Muestra un mensaje invasivo al usuario

Returns: void
toast
toast(type: string, content: string, title: string, timeOut: number)

Muestra un mensaje no invasivo al usuario

Parameters :
  • type

    success, danger, warning, info

  • content

    Texto del mensaje

  • title

    Título

  • timeOut

    Tiempo en ms cuando se oculta el mensaje

Returns: void
showLoader
showLoader()

Muestra el loader en el navbar de la aplicación.

Returns: void
hideLoader
hideLoader()

Oculta el loader en el navbar de la aplicación.

Returns: void
wizard
wizard(config: WizardConfig)

Muestra al usuario una secuencia de imágenes y textos organizados en pasos

Parameters :
  • config : WizardConfig
Returns: Promise<any>

*

setViewContainerRef
setViewContainerRef(viewContainerRef: any)
Returns: void
setNavbarItem
setNavbarItem(componentRef: any, inputs: any)

Instancia una componente y la injecta en la parte dinamica del plex-app

Parameters :
  • componentRef
  • inputs
Returns: void
clearNavbar
clearNavbar()

Borra el item dinamico agregado.

Returns: void
toggleHideNavBar
toggleHideNavBar()

Esconde la barra de navegación.
Sólo para pantalla de login

Returns: void
navVisible
navVisible(visible: boolean)
Returns: void
isMobile
isMobile()

Determina si estamos en un dispositivo mobile.

Returns: void
updateNetwork
updateNetwork(action: "inc" | "dec")
Returns: void

Properties

Public appStatus
appStatus: Subject<any>
Public loaderCount
loaderCount: number
Default value: 0
Public menu
menu: DropdownItem[]
Public navbarVisible
navbarVisible: boolean
Default value: true
Public networkCounter
networkCounter: BehaviorSubject<number>

Cuenta los POST, PATCH, PUT, DELETE

Public title
title: PlexTitle[]

Contiene el título y breadcrumb que se muestran en el navbar

Public userInfo
userInfo: any
Private viewContainerRef
viewContainerRef: ViewContainerRef

Navbar dinamico

import { BehaviorSubject, Subject } from 'rxjs';
import { Injectable, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { TitleCasePipe } from '@angular/common';
import { DropdownItem } from './../dropdown/dropdown-item.inteface';
import { NotificationsService } from './../toast/simple-notifications/services/notifications.service';
import { default as swal } from 'sweetalert2';
import { WizardConfig } from './wizard-config.interface';
import { PlexTitle } from './plex-title.interface';
import * as introJs from 'intro.js';
import { BreakpointObserver } from '@angular/cdk/layout';

@Injectable()
export class Plex {
    public menu: DropdownItem[];
    public loaderCount = 0;
    public appStatus: Subject<any> = new Subject();
    public userInfo: any;
    public navbarVisible = true;

    /**
     * Cuenta los POST, PATCH, PUT, DELETE
     */
    public networkCounter = new BehaviorSubject(0);
    /**
     * Contiene el título y breadcrumb que se muestran en el navbar
     */
    public title: PlexTitle[];

    constructor(
        private titleService: Title,
        private noficationService: NotificationsService,
        private componentFactoryResolver: ComponentFactoryResolver,
        private breakpointObserver: BreakpointObserver,
        private titlecasePipe: TitleCasePipe
    ) { }

    /**
     * Actualiza el ménu de la aplicación
     *
     * @param {DropdownItem[]} menu Items del menú
     *
     * @memberof Plex
     */
    updateMenu(menu: DropdownItem[]) {
        this.menu = menu.map((item) => {
            if (item.icon) {
                const words = item.icon.split(' ');
                if (words.length > 1) {
                    item.prefix = words[0];
                    item.icon = words[1].substr(4);
                } else {
                    item.prefix = item.prefix || 'adi';
                }
            }
            return item;
        });
    }

    /**
     * Actualiza el título del navegador y breadcrumb
     *
     * @param {string} title Título
     *
     * @memberof Plex
     */
    updateTitle(title: string | PlexTitle[]) {
        setTimeout(() => {
            if (title) {
                if (typeof title === 'string') {
                    this.title = [{ name: title }];
                } else {
                    this.title = title as PlexTitle[];
                }
                const name = this.titlecasePipe.transform(this.title[this.title.length - 1].name);
                this.titleService.setTitle(name);
            } else {
                this.titleService.setTitle('');
                this.title = null;
            }
        });
    }

    /**
     * Actualiza el estado de la aplicación en el navbar
     *
     * @param {*} status Objeto de estado
     *
     * @memberof Plex
     */
    updateAppStatus(status: any) {
        this.appStatus.next(status);
    }

    /**
     * Actualiza la información del usuario actual
     *
     * @param {*} user Objeto con datos de usuario
     *
     * @memberof Plex
     */
    updateUserInfo(user: any) {
        this.userInfo = user;
    }

    /**
     * TODO: Migrar para usar 1 sólo objeto con su type como param
     * Muestra un diálogo de confirmación
     *
     * @param {string} content Texto
     * @param {string} [title='Confirmación'] Título
     * @returns {Promise<any>} Devuelve una promise se que resuelve con true/false cuando el diálogo se cierra
     *
     * @memberof Plex
     */
    confirm(params: { content: string, title: string, confirmButtonText: string, cancelButtonText: string });

    confirm(content: string, title?: string, confirmButtonText?: string, cancelButtonText?: string);

    confirm(content, title = 'Confirmación', confirmButtonText = 'Confirmar', cancelButtonText = 'Cancelar'): Promise<any> {

        let htmlContent;

        // Para compatibilidad
        if (typeof content === 'object') {
            title = content.title || 'Confirmación';
            htmlContent = content.content;
            confirmButtonText = content.confirmButtonText || 'Confirmar';
            cancelButtonText = content.cancelButtonText || 'Cancelar';
        } else {
            htmlContent = content;
        }

        return new Promise((resolve, reject) => {
            swal({
                title,
                html: htmlContent,
                type: 'question',
                showCancelButton: true,
                confirmButtonText: confirmButtonText.toLocaleUpperCase(),
                cancelButtonText: cancelButtonText.toLocaleUpperCase(),
                buttonsStyling: false,
                confirmButtonClass: 'btn btn-success',
                cancelButtonClass: 'btn btn-danger',
            }).then(() => resolve(true))
                .catch(() => resolve(false));
        });
    }

    /**
     * TODO: Migrar para usar 1 sólo objeto con su type como param
     * Muestra un mensaje invasivo al usuario
     *
     * @param {string} type success, danger (error), warning, info
     * @param {string} content Texto del mensaje
     * @param {string} [title='Información'] Título
     * @param {number} [timeOut=0] Tiempo en ms cuando se oculta el mensaje. Por default no se oculta.
     *
     * @memberof Plex
     */
    info(type: String, content: String, title?: String, timeOut?: Number, confirmButtonText?: String);
    info(params: { type: String, content: String, title: String, confirmButtonText: String, timeOut?: Number });
    info(type, content = '', title = 'Información', timeOut = 0, confirmButtonText = 'Aceptar') {
        let modalType;

        // Para compatibilidad
        if (typeof type === 'object') {
            // TODO: Usar el tipo SweetAlertType?
            modalType = type.type === 'danger' ? 'error' : type.type;
            content = type.content || '';
            title = type.title || 'Información';
            confirmButtonText = type.confirmButtonText ? type.confirmButtonText.toLocaleUpperCase() : 'Aceptar';
            timeOut = type.timeOut || 0;
        } else {
            // TODO: Usar el tipo SweetAlertType?
            if (type === 'danger') {
                type = modalType = 'error';
            }
            modalType = type;
        }

        return swal({
            title,
            html: content,
            type: modalType,
            confirmButtonText,
            buttonsStyling: false,
            confirmButtonClass: `btn btn-${modalType === 'error' ? 'danger' : modalType}`,
            timer: timeOut || null,
        }).catch(swal.noop);
    }

    /**
     * Muestra un mensaje no invasivo al usuario
     *
     * @param {string} type success, danger, warning, info
     * @param {string} content Texto del mensaje
     * @param {string} [title='Información'] Título
     * @param {number} [timeOut=5000] Tiempo en ms cuando se oculta el mensaje
     *
     * @memberof Plex
     */
    toast(type: string, content: string, title: string = 'Información', timeOut: number = 2500) {
        const options = {
            theClass: 'toast',
            timeOut
        };
        switch (type) {
            case 'success':
                this.noficationService.success(title, content, options);
                break;
            case 'info':
                this.noficationService.info(title, content, options);
                break;
            case 'danger':
                this.noficationService.error(title, content, options);
                break;
            case 'warning':
                this.noficationService.alert(title, content, options);
                break;
        }
    }

    /**
     * Muestra el loader en el navbar de la aplicación.
     *
     * @memberof Plex
     */
    showLoader() {
        // Debe ir dentro de setTimeout por un bug de Angular2
        setTimeout(() => {
            this.loaderCount++;
        });
    }

    /**
     * Oculta el loader en el navbar de la aplicación.
     *
     * @memberof Plex
     */
    hideLoader() {
        // Debe ir dentro de setTimeout por un bug de Angular2
        setTimeout(() => {
            if (this.loaderCount > 0) {
                this.loaderCount--;
            }
        });
    }

    /**
     * Muestra al usuario una secuencia de imágenes y textos organizados en pasos
     *
     * @param {WizardConfig} config
     * @returns {Promise<any>}
     * @memberof Plex
     */
    wizard(config: WizardConfig): Promise<any> {
        // Cheque si el usuario no desea verlo más
        if (!config.forceShow && localStorage[`wizard-${config.id}-${config.updatedOn.toISOString()}-hide`]) {
            return null;
        }

        // Promise que devolverá la función
        let resolve: any;
        const promise = new Promise((res, rej) => {
            resolve = res;
        });

        if (config.fullScreen) {
            // Utiliza SweetAlert2
            // Configura SweetAlert
            let steps = [];
            for (const i in config.steps) {
                steps.push({
                    title: config.steps[i].title,
                    html: config.steps[i].content,
                    // Empty gif
                    imageUrl: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
                    imageClass: config.steps[i].imageClass,
                    imageWidth: 500,
                    imageHeight: 250,
                    confirmButtonText: 'Siguiente',
                    cancelButtonText: 'Cancelar',
                    showCancelButton: true,
                    // animation: false,
                    // customClass: 'animated fadeInLeft'
                });
            }

            // En el primer paso el botón principal dice "Comenzar"
            steps[0].confirmButtonText = 'Comenzar';

            // En los pasos intermedios los botones dicen "Siguiente" y "Cancelar"
            steps = steps.map(s => {
                return { ...s, buttonsStyling: false, confirmButtonClass: 'btn btn-info', cancelButtonClass: 'btn btn-danger' };
            });

            // En el último paso el botón principal dice "Finalizar" y el botón "Cancelar" se oculta
            const last = steps[steps.length - 1];
            last.confirmButtonText = 'Finalizar';
            last.showCancelButton = false;

            // Crea el modal
            let modal: Promise<any>;
            if (steps.length === 1) {
                modal = swal(steps[0]);
            } else {
                const progressSteps: number[] = [];
                steps.forEach((element, index) => progressSteps.push(index + 1));
                steps.forEach((element, value, index) => element.progressSteps = progressSteps);
                modal = swal.queue(steps);
                if (config.showNumbers) {
                    swal.showProgressSteps();
                } else {
                    swal.hideProgressSteps();
                }
            }

            // Crea la promise
            modal.then((reason) => {
                // No volver a mostrar
                localStorage[`wizard-${config.id}-${config.updatedOn.toISOString()}-hide`] = true;
                resolve(true);
            }).catch((reason) => {
                resolve(false);
            });
        } else {
            // Utiliza Intro.js
            const steps: introJs.Step[] = [];
            for (const i in config.steps) {
                steps.push({
                    // title: config.steps[i].title,
                    intro: (config.steps[i].title ? `<h3>${config.steps[i].title}</h3>` : '') + config.steps[i].content,
                    element: document.querySelector(`[plex-wizard-ref="${i}"]`),
                    position: 'right'
                });
            }

            const intro = introJs();
            intro.setOptions({
                nextLabel: 'Siguiente',
                prevLabel: 'Volver',
                skipLabel: 'Cerrar',
                doneLabel: 'Finalizar',
                showProgress: true,
                showBullets: false,
                showStepNumbers: config.showNumbers,
                steps
            });
            intro.start()
                .oncomplete(() => {
                    // No volver a mostrar
                    localStorage[`wizard-${config.id}-${config.updatedOn.toISOString()}-hide`] = true;
                    resolve(true);
                })
                .onexit(() => resolve(false));
        }

        return promise;
    }

    /**
     * Navbar dinamico
     */

    private viewContainerRef: ViewContainerRef;
    setViewContainerRef(viewContainerRef) {
        this.viewContainerRef = viewContainerRef;
    }

    /**
     * Instancia una componente y la injecta en la parte dinamica del plex-app
     * @param componentRef
     * @param inputs
     */
    setNavbarItem(componentRef, inputs) {
        // el setTimeout resuelve el error ExpressionChangedAfterItHasBeenCheckedError.
        // La componente dinamica se estaba creando antes de que finalize la componente padre, lo que generaba ese error.
        // Por eso encolamos la creación de la componente al proximo tick del navegador.
        setTimeout(() => {
            this.viewContainerRef.clear();
            const componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentRef);
            const component = this.viewContainerRef.createComponent(componentFactory);
            Object.assign(component.instance, inputs);
        }, 0);
    }

    /**
     * Borra el item dinamico agregado.
     */
    clearNavbar() {
        this.viewContainerRef.clear();
    }

    /**
     * Esconde la barra de navegación.
     * Sólo para pantalla de login
     */
    toggleHideNavBar() {
        this.navbarVisible = !this.navbarVisible;
        return this.navbarVisible;
    }

    navVisible(visible: boolean) {
        this.navbarVisible = visible;
        return this.navbarVisible;
    }

    /**
     * Determina si estamos en un dispositivo mobile.
     */
    isMobile() {
        return this.breakpointObserver.isMatched('(max-width: 599px)');
    }

    updateNetwork(action: 'inc' | 'dec') {
        const count = this.networkCounter.getValue();
        if (action === 'inc') {
            this.networkCounter.next(count + 1);
        } else {
            if (count > 0) {
                this.networkCounter.next(count - 1);
            }

        }
    }
}

results matching ""

    No results matching ""