Compare commits
4 Commits
6a8f2d78bd
...
9afc586cab
| Author | SHA1 | Date |
|---|---|---|
|
|
9afc586cab | |
|
|
7962420565 | |
|
|
b821560edc | |
|
|
f252d604d6 |
|
|
@ -42,7 +42,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-area {
|
.logo-area {
|
||||||
display: flex; align-items: center; gap: 14px; text-decoration: none; color: #111827; min-width: 0;
|
display: flex; align-items: center; gap: 10px; text-decoration: none; color: #111827; min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-symbol {
|
.logo-symbol {
|
||||||
|
|
@ -61,7 +61,7 @@ $logo-secondary-grey: #757575;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: geometricPrecision;
|
text-rendering: geometricPrecision;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
--scale: 0.34;
|
--scale: 0.31;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lg-wordmark__line {
|
.lg-wordmark__line {
|
||||||
|
|
@ -106,6 +106,91 @@ $logo-secondary-grey: #757575;
|
||||||
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Header padrão (Home/Login/Interno): "LineGestão" em uma única linha */
|
||||||
|
.lg-wordmark:not([aria-label='Line Gestão Empresas']) {
|
||||||
|
.lg-wordmark__line {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: 'Gestão';
|
||||||
|
margin-left: 0.02em;
|
||||||
|
font: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
#c8c3ff 0%,
|
||||||
|
#7a6cff 26%,
|
||||||
|
#4b3fe6 52%,
|
||||||
|
#2b21c8 74%,
|
||||||
|
#120a78 100%
|
||||||
|
);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg-wordmark__movel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo do cliente: "LineGestão" na primeira linha e "Empresas" abaixo */
|
||||||
|
.lg-wordmark[aria-label='Line Gestão Empresas'] {
|
||||||
|
.lg-wordmark__line {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
|
font-size: calc(86px * var(--scale));
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: 'Gestão';
|
||||||
|
margin-left: 0.02em;
|
||||||
|
font: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
#c8c3ff 0%,
|
||||||
|
#7a6cff 26%,
|
||||||
|
#4b3fe6 52%,
|
||||||
|
#2b21c8 74%,
|
||||||
|
#120a78 100%
|
||||||
|
);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg-wordmark__movel {
|
||||||
|
font-size: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: calc(-6px * var(--scale));
|
||||||
|
line-height: 1;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: 'Empresas';
|
||||||
|
font-family: 'Poppins', 'Nunito', system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: calc(38px * var(--scale));
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
#6f7f96 0%,
|
||||||
|
#4b5b72 48%,
|
||||||
|
#2f3d52 100%
|
||||||
|
);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.nav-links { display: flex; align-items: center; justify-content: center; gap: 22px; flex: 1; }
|
.nav-links { display: flex; align-items: center; justify-content: center; gap: 22px; flex: 1; }
|
||||||
.nav-links .nav-link {
|
.nav-links .nav-link {
|
||||||
display: inline-flex; align-items: center; gap: 6px; color: $text-main; text-decoration: none; font-weight: 600; font-size: 14px; transition: color 0.2s;
|
display: inline-flex; align-items: center; gap: 6px; color: $text-main; text-decoration: none; font-weight: 600; font-size: 14px; transition: color 0.2s;
|
||||||
|
|
@ -766,7 +851,7 @@ $logo-secondary-grey: #757575;
|
||||||
.side-logo {
|
.side-logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 8px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: $text-main;
|
color: $text-main;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
@ -784,13 +869,15 @@ $logo-secondary-grey: #757575;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
gap: 6px;
|
gap: 0;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
--scale: 0.23;
|
--scale: 0.23;
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-wordmark__line {
|
.side-wordmark__line {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
font-family: 'Poppins', 'Nunito', system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
font-family: 'Poppins', 'Nunito', system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
font-size: calc(92px * var(--scale));
|
font-size: calc(92px * var(--scale));
|
||||||
|
|
@ -808,28 +895,29 @@ $logo-secondary-grey: #757575;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.side-wordmark__movel {
|
&::after {
|
||||||
font-family: 'Poppins', 'Nunito', system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
content: 'Gestão';
|
||||||
font-weight: 800;
|
|
||||||
font-size: calc(92px * var(--scale));
|
|
||||||
letter-spacing: -0.012em;
|
|
||||||
white-space: nowrap;
|
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-top: 0;
|
font: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
#aeb8c7 0%,
|
#c8c3ff 0%,
|
||||||
#6b778d 50%,
|
#7a6cff 26%,
|
||||||
#3f4b60 100%
|
#4b3fe6 52%,
|
||||||
|
#2b21c8 74%,
|
||||||
|
#120a78 100%
|
||||||
);
|
);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
line-height: 1;
|
text-shadow: 0 1px 1px rgba(15, 23, 42, 0.12);
|
||||||
position: relative;
|
}
|
||||||
top: 0;
|
}
|
||||||
|
|
||||||
|
.side-wordmark__movel {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
.side-menu-body { padding: 16px; display: flex; flex-direction: column; gap: 4px; }
|
.side-menu-body { padding: 16px; display: flex; flex-direction: column; gap: 4px; }
|
||||||
.side-item {
|
.side-item {
|
||||||
|
|
@ -864,7 +952,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lg-wordmark {
|
.lg-wordmark {
|
||||||
--scale: 0.29;
|
--scale: 0.27;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-symbol {
|
.logo-symbol {
|
||||||
|
|
@ -971,7 +1059,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-area {
|
.logo-area {
|
||||||
gap: 8px;
|
gap: 6px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -981,7 +1069,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lg-wordmark {
|
.lg-wordmark {
|
||||||
--scale: 0.22;
|
--scale: 0.21;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header público (Home/Login/Register): mantém logo visível e CTA fixo à direita */
|
/* Header público (Home/Login/Register): mantém logo visível e CTA fixo à direita */
|
||||||
|
|
@ -996,7 +1084,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-inner > .logo-area .lg-wordmark {
|
.header-inner > .logo-area .lg-wordmark {
|
||||||
--scale: 0.2;
|
--scale: 0.19;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-inner > .header-actions {
|
.header-inner > .header-actions {
|
||||||
|
|
@ -1013,7 +1101,7 @@ $logo-secondary-grey: #757575;
|
||||||
|
|
||||||
/* Header logado: mantém nome visível, porém menor para smartphone */
|
/* Header logado: mantém nome visível, porém menor para smartphone */
|
||||||
.left-logged .logo-area .lg-wordmark {
|
.left-logged .logo-area .lg-wordmark {
|
||||||
--scale: 0.2;
|
--scale: 0.19;
|
||||||
}
|
}
|
||||||
|
|
||||||
.client-header-context {
|
.client-header-context {
|
||||||
|
|
@ -1317,7 +1405,7 @@ $logo-secondary-grey: #757575;
|
||||||
|
|
||||||
@media (max-width: 420px) {
|
@media (max-width: 420px) {
|
||||||
.header-inner > .logo-area {
|
.header-inner > .logo-area {
|
||||||
gap: 6px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-inner > .logo-area .logo-symbol {
|
.header-inner > .logo-area .logo-symbol {
|
||||||
|
|
@ -1336,7 +1424,7 @@ $logo-secondary-grey: #757575;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-logged .logo-area {
|
.left-logged .logo-area {
|
||||||
gap: 6px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-logged .logo-area .lg-wordmark {
|
.left-logged .logo-area .lg-wordmark {
|
||||||
|
|
|
||||||
|
|
@ -1190,9 +1190,16 @@ export class Dashboard implements OnInit, AfterViewInit, OnDestroy {
|
||||||
'BLOQUEAR',
|
'BLOQUEAR',
|
||||||
'BLOQUEAD',
|
'BLOQUEAD',
|
||||||
'BLOQUEADO',
|
'BLOQUEADO',
|
||||||
|
'BLOQUEIO',
|
||||||
|
'BLOQ120',
|
||||||
'RESERVA',
|
'RESERVA',
|
||||||
'NAOATRIBUIDO',
|
'NAOATRIBUIDO',
|
||||||
'PENDENTE',
|
'PENDENTE',
|
||||||
|
'COBRANCA',
|
||||||
|
'FATURAMENTO',
|
||||||
|
'FINANCEIRO',
|
||||||
|
'BACKOFFICE',
|
||||||
|
'ADMINISTRATIVO',
|
||||||
];
|
];
|
||||||
if (invalidUserTokens.some((token) => usuarioKey.includes(token))) {
|
if (invalidUserTokens.some((token) => usuarioKey.includes(token))) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { NavigationEnd, Router } from '@angular/router';
|
||||||
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
|
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
|
||||||
import { PlanAutoFillService } from '../../services/plan-autofill.service';
|
import { PlanAutoFillService } from '../../services/plan-autofill.service';
|
||||||
import { AuthService } from '../../services/auth.service';
|
import { AuthService } from '../../services/auth.service';
|
||||||
|
import { TenantSyncService } from '../../services/tenant-sync.service';
|
||||||
import { firstValueFrom, Subscription, filter } from 'rxjs';
|
import { firstValueFrom, Subscription, filter } from 'rxjs';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { confirmDeletionWithTyping } from '../../utils/destructive-confirmation';
|
import { confirmDeletionWithTyping } from '../../utils/destructive-confirmation';
|
||||||
|
|
@ -121,7 +122,9 @@ interface ApiLineDetail {
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateMobileLineRequest = Omit<ApiLineDetail, 'id'>;
|
type UpdateMobileLineRequest = Omit<ApiLineDetail, 'id'>;
|
||||||
type CreateMobileLineRequest = Omit<ApiLineDetail, 'id'>;
|
type CreateMobileLineRequest = Omit<ApiLineDetail, 'id'> & {
|
||||||
|
reservaLineId?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
interface ClientGroupDto {
|
interface ClientGroupDto {
|
||||||
cliente: string;
|
cliente: string;
|
||||||
|
|
@ -268,7 +271,8 @@ export class Geral implements OnInit, AfterViewInit, OnDestroy {
|
||||||
private cdr: ChangeDetectorRef,
|
private cdr: ChangeDetectorRef,
|
||||||
private planAutoFill: PlanAutoFillService,
|
private planAutoFill: PlanAutoFillService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private router: Router
|
private router: Router,
|
||||||
|
private tenantSyncService: TenantSyncService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private readonly apiBase = (() => {
|
private readonly apiBase = (() => {
|
||||||
|
|
@ -2716,11 +2720,12 @@ export class Geral implements OnInit, AfterViewInit, OnDestroy {
|
||||||
private buildCreatePayload(model: any): CreateMobileLineRequest {
|
private buildCreatePayload(model: any): CreateMobileLineRequest {
|
||||||
this.calculateFinancials(model);
|
this.calculateFinancials(model);
|
||||||
|
|
||||||
const { contaEmpresa: _contaEmpresa, uid: _uid, reservaLineId: _reservaLineId, ...createModelPayload } = model;
|
const { contaEmpresa: _contaEmpresa, uid: _uid, ...createModelPayload } = model;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...createModelPayload,
|
...createModelPayload,
|
||||||
item: Number(model.item),
|
item: Number(model.item),
|
||||||
|
reservaLineId: (model.reservaLineId ?? '').toString().trim() || null,
|
||||||
dataBloqueio: this.dateInputToIso(model.dataBloqueio),
|
dataBloqueio: this.dateInputToIso(model.dataBloqueio),
|
||||||
dataEntregaOpera: this.dateInputToIso(model.dataEntregaOpera),
|
dataEntregaOpera: this.dateInputToIso(model.dataEntregaOpera),
|
||||||
dataEntregaCliente: this.dateInputToIso(model.dataEntregaCliente),
|
dataEntregaCliente: this.dateInputToIso(model.dataEntregaCliente),
|
||||||
|
|
@ -2755,7 +2760,8 @@ export class Geral implements OnInit, AfterViewInit, OnDestroy {
|
||||||
linha: (row.linha ?? '').toString(),
|
linha: (row.linha ?? '').toString(),
|
||||||
chip: (row.chip ?? '').toString(),
|
chip: (row.chip ?? '').toString(),
|
||||||
usuario: (row.usuario ?? '').toString(),
|
usuario: (row.usuario ?? '').toString(),
|
||||||
tipoDeChip: (row.tipoDeChip ?? '').toString()
|
tipoDeChip: (row.tipoDeChip ?? '').toString(),
|
||||||
|
reservaLineId: null
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.buildCreatePayload(lineModel);
|
return this.buildCreatePayload(lineModel);
|
||||||
|
|
@ -2772,9 +2778,13 @@ export class Geral implements OnInit, AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
private async finalizeCreateSuccess(createdCount: number) {
|
private async finalizeCreateSuccess(createdCount: number) {
|
||||||
const targetClient = (this.createModel?.cliente ?? '').toString().trim();
|
const targetClient = (this.createModel?.cliente ?? '').toString().trim();
|
||||||
|
const isNewClientCreated = this.createMode === 'NEW_CLIENT' && !!targetClient;
|
||||||
|
|
||||||
this.createSaving = false;
|
this.createSaving = false;
|
||||||
this.closeAllModals();
|
this.closeAllModals();
|
||||||
|
if (isNewClientCreated) {
|
||||||
|
this.tenantSyncService.notifyTenantsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
await this.showToast(this.getCreateSuccessMessage(createdCount));
|
await this.showToast(this.getCreateSuccessMessage(createdCount));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
.brand-logo {
|
.brand-logo {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 8px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
line-height: 0.92;
|
line-height: 0.92;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
--scale: 0.31;
|
--scale: 0.28;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-wordmark__line {
|
.login-wordmark__line {
|
||||||
|
|
@ -101,26 +101,32 @@
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
|
||||||
|
|
||||||
.login-wordmark__movel {
|
display: inline-flex;
|
||||||
font-family: "Poppins", "Nunito", system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
align-items: baseline;
|
||||||
font-weight: 700;
|
|
||||||
font-size: calc(34px * var(--scale));
|
&::after {
|
||||||
letter-spacing: -0.01em;
|
content: 'Gestão';
|
||||||
white-space: nowrap;
|
margin-left: 0.02em;
|
||||||
margin-left: calc(0.33em * var(--scale));
|
font: inherit;
|
||||||
margin-top: calc(-6px * var(--scale));
|
letter-spacing: inherit;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
#aeb8c7 0%,
|
#c8c3ff 0%,
|
||||||
#6b778d 50%,
|
#7a6cff 26%,
|
||||||
#3f4b60 100%
|
#4b3fe6 52%,
|
||||||
|
#2b21c8 74%,
|
||||||
|
#120a78 100%
|
||||||
);
|
);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-wordmark__movel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1366px) {
|
@media (max-width: 1366px) {
|
||||||
.login-logo-symbol {
|
.login-logo-symbol {
|
||||||
|
|
@ -129,7 +135,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-wordmark {
|
.login-wordmark {
|
||||||
--scale: 0.27;
|
--scale: 0.25;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,7 +146,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-wordmark {
|
.login-wordmark {
|
||||||
--scale: 0.24;
|
--scale: 0.22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
import {
|
import {
|
||||||
|
|
@ -10,12 +10,14 @@ import {
|
||||||
Validators,
|
Validators,
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
|
import { CustomSelectComponent } from '../../components/custom-select/custom-select';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SysadminService,
|
SysadminService,
|
||||||
SystemTenantDto,
|
SystemTenantDto,
|
||||||
CreateSystemTenantUserResponse,
|
CreateSystemTenantUserResponse,
|
||||||
} from '../../services/sysadmin.service';
|
} from '../../services/sysadmin.service';
|
||||||
|
import { TenantSyncService } from '../../services/tenant-sync.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-system-provision-user',
|
selector: 'app-system-provision-user',
|
||||||
|
|
@ -24,7 +26,7 @@ import {
|
||||||
templateUrl: './system-provision-user.html',
|
templateUrl: './system-provision-user.html',
|
||||||
styleUrls: ['./system-provision-user.scss'],
|
styleUrls: ['./system-provision-user.scss'],
|
||||||
})
|
})
|
||||||
export class SystemProvisionUserPage implements OnInit {
|
export class SystemProvisionUserPage implements OnInit, OnDestroy {
|
||||||
readonly sourceType = 'MobileLines.Cliente';
|
readonly sourceType = 'MobileLines.Cliente';
|
||||||
|
|
||||||
provisionForm: FormGroup;
|
provisionForm: FormGroup;
|
||||||
|
|
@ -37,10 +39,12 @@ export class SystemProvisionUserPage implements OnInit {
|
||||||
submitErrors: string[] = [];
|
submitErrors: string[] = [];
|
||||||
successMessage = '';
|
successMessage = '';
|
||||||
createdUser: CreateSystemTenantUserResponse | null = null;
|
createdUser: CreateSystemTenantUserResponse | null = null;
|
||||||
|
private tenantChangesSub?: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
private sysadminService: SysadminService
|
private sysadminService: SysadminService,
|
||||||
|
private tenantSyncService: TenantSyncService
|
||||||
) {
|
) {
|
||||||
this.provisionForm = this.fb.group(
|
this.provisionForm = this.fb.group(
|
||||||
{
|
{
|
||||||
|
|
@ -56,6 +60,18 @@ export class SystemProvisionUserPage implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.tenantChangesSub = this.tenantSyncService.changes$.subscribe(() => {
|
||||||
|
this.loadTenants();
|
||||||
|
});
|
||||||
|
this.loadTenants();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.tenantChangesSub?.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:focus')
|
||||||
|
onWindowFocus(): void {
|
||||||
this.loadTenants();
|
this.loadTenants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
import { EMPTY, Observable, Subject, fromEvent, merge } from 'rxjs';
|
||||||
|
import { filter, map } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class TenantSyncService {
|
||||||
|
private readonly storageKey = 'linegestao.tenants.updatedAt';
|
||||||
|
private readonly localChangesSubject = new Subject<void>();
|
||||||
|
readonly changes$: Observable<void>;
|
||||||
|
|
||||||
|
private readonly isBrowser: boolean;
|
||||||
|
|
||||||
|
constructor(@Inject(PLATFORM_ID) platformId: object) {
|
||||||
|
this.isBrowser = isPlatformBrowser(platformId);
|
||||||
|
|
||||||
|
const storageChanges$ = this.isBrowser
|
||||||
|
? fromEvent<StorageEvent>(window, 'storage').pipe(
|
||||||
|
filter((event) => event.key === this.storageKey && !!event.newValue),
|
||||||
|
map(() => void 0)
|
||||||
|
)
|
||||||
|
: EMPTY;
|
||||||
|
|
||||||
|
this.changes$ = merge(this.localChangesSubject.asObservable(), storageChanges$);
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyTenantsChanged(): void {
|
||||||
|
this.localChangesSubject.next();
|
||||||
|
|
||||||
|
if (!this.isBrowser) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.setItem(this.storageKey, String(Date.now()));
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue