mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-19 04:57:52 +00:00
Firebase web notifications added
This commit is contained in:
@@ -9,6 +9,7 @@ import { InativityService } from "src/app/services/inativity.service";
|
||||
import { ThemeService } from 'src/app/services/theme.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { Storage } from '@ionic/storage';
|
||||
import { AngularFireMessaging } from '@angular/fire/messaging';
|
||||
|
||||
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
|
||||
parse: {
|
||||
@@ -38,12 +39,34 @@ export class AppComponent {
|
||||
private sqliteservice: SqliteService,
|
||||
private InativityService: InativityService,
|
||||
public ThemeService: ThemeService,
|
||||
private storage: Storage
|
||||
private storage: Storage,
|
||||
/* private afMessaging: AngularFireMessaging, */
|
||||
) {
|
||||
this.initializeApp();
|
||||
this.storage.set('version', environment.version).then(() => {})
|
||||
/* this.requestPermission();
|
||||
this.receiveMessages(); */
|
||||
}
|
||||
|
||||
/* requestPermission() {
|
||||
this.afMessaging.requestToken.subscribe(
|
||||
(token) => {
|
||||
// Save the token to your server for sending notifications
|
||||
console.log('Permission granted! Token:', token);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Permission denied:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
receiveMessages() {
|
||||
this.afMessaging.messages.subscribe((message) => {
|
||||
console.log('Received message:', message);
|
||||
// Handle the received message, e.g., show a notification
|
||||
});
|
||||
} */
|
||||
|
||||
initializeApp() {
|
||||
this.platform.ready().then(() => {
|
||||
this.statusBar.styleDefault();
|
||||
|
||||
@@ -77,6 +77,9 @@ import * as Sentry from '@sentry/capacitor';
|
||||
// For automatic instrumentation (highly recommended)
|
||||
import { Integration } from '@sentry/types';
|
||||
import { BrowserTracing } from '@sentry/tracing';
|
||||
import { AngularFireModule } from '@angular/fire';
|
||||
import { AngularFireMessagingModule } from '@angular/fire/messaging';
|
||||
import { firebaseConfig } from '../firebase-config';
|
||||
|
||||
// import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
// import { AngularFireModule } from '@angular/fire';
|
||||
@@ -156,6 +159,8 @@ import { FirebaseX } from '@ionic-native/firebase-x/ngx'; */
|
||||
NgxMatMomentModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
AngularFireModule.initializeApp(firebaseConfig),
|
||||
AngularFireMessagingModule,
|
||||
|
||||
],
|
||||
providers: [
|
||||
|
||||
@@ -45,31 +45,36 @@ export class ProfilePage implements OnInit {
|
||||
private platform: Platform,
|
||||
private eventTriger: EventTrigger,
|
||||
public ThemeService: ThemeService,
|
||||
private notificationService: NotificationsService
|
||||
) {
|
||||
|
||||
|
||||
|
||||
router.events.subscribe((val) => {
|
||||
this.isProfileOpen = false
|
||||
this.logoutOut = true
|
||||
});
|
||||
|
||||
this.eventTriger.getObservable().subscribe((event) => {
|
||||
if(event.notification == "recive") {
|
||||
if (event.notification == "recive") {
|
||||
this.getNotificationData();
|
||||
} else if(event.notification == "deleted") {
|
||||
console.log('header', event.notification)
|
||||
this.getNotificationData();
|
||||
}
|
||||
});
|
||||
|
||||
this.notificationService.notificationReceived.subscribe(() => {
|
||||
this.getNotificationData();
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.hideImage = true
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.platform.is('desktop') || this.platform.is('mobileweb')) {
|
||||
this.getNotificationData();
|
||||
} else {
|
||||
this.getNotificationData();
|
||||
}
|
||||
|
||||
this.getNotificationData();
|
||||
|
||||
}
|
||||
|
||||
@@ -83,32 +88,52 @@ export class ProfilePage implements OnInit {
|
||||
asyncNotification() { }
|
||||
|
||||
async getNotificationData() {
|
||||
|
||||
//const keyExist = await this.storageservice.keyExist("Notifications")
|
||||
|
||||
//if(keyExist) {
|
||||
this.storageservice.get("Notifications").then((value) => {
|
||||
|
||||
this.DataArray = []
|
||||
value.forEach((element, i) => {
|
||||
let notificationObject;
|
||||
if (element.data) {
|
||||
notificationObject = {
|
||||
index: i,
|
||||
title: element.title,
|
||||
Service: element.data.Service,
|
||||
Object: element.data.Object,
|
||||
IdObject: element.data.IdObject,
|
||||
FolderId: element.data.FolderId,
|
||||
body: element.body,
|
||||
dateInit: this.getFormatedTime(element.data.dateInit),
|
||||
dateEnd: this.getFormatedTime(element.data.dateEnd),
|
||||
Location: element.data.Location,
|
||||
TypeAgenda: element.data.TypeAgenda,
|
||||
Role: element.data.Role,
|
||||
Status: element.data.Status
|
||||
}
|
||||
} else {
|
||||
//const keyExist = await this.storageservice.keyExist("Notifications")
|
||||
|
||||
//if(keyExist) {
|
||||
await this.storageservice.get("Notifications").then((value) => {
|
||||
|
||||
this.DataArray = []
|
||||
value.forEach((element, i) => {
|
||||
let notificationObject;
|
||||
if (element.notification) {
|
||||
|
||||
notificationObject = {
|
||||
index: i,
|
||||
title: element.notification.title,
|
||||
Service: element.data.Service,
|
||||
Object: element.data.Object,
|
||||
IdObject: element.data.IdObject,
|
||||
FolderId: element.data.FolderId,
|
||||
body: element.notification.body,
|
||||
dateInit: this.getFormatedTime(element.data.dateInit),
|
||||
dateEnd: this.getFormatedTime(element.data.dateEnd),
|
||||
Location: element.data.Location,
|
||||
TypeAgenda: element.data.TypeAgenda,
|
||||
Role: element.data.Role,
|
||||
Status: element.data.Status
|
||||
}
|
||||
|
||||
} else if (element.data) {
|
||||
notificationObject = {
|
||||
index: i,
|
||||
title: element.title,
|
||||
Service: element.data.Service,
|
||||
Object: element.data.Object,
|
||||
IdObject: element.data.IdObject,
|
||||
FolderId: element.data.FolderId,
|
||||
body: element.body,
|
||||
dateInit: this.getFormatedTime(element.data.dateInit),
|
||||
dateEnd: this.getFormatedTime(element.data.dateEnd),
|
||||
Location: element.data.Location,
|
||||
TypeAgenda: element.data.TypeAgenda,
|
||||
Role: element.data.Role,
|
||||
Status: element.data.Status
|
||||
}
|
||||
|
||||
} else {
|
||||
{
|
||||
notificationObject = {
|
||||
FolderId: element.FolderId,
|
||||
IdObject: element.IdObject,
|
||||
@@ -125,14 +150,15 @@ export class ProfilePage implements OnInit {
|
||||
title: element.title
|
||||
}
|
||||
}
|
||||
|
||||
this.DataArray.push(notificationObject)
|
||||
});
|
||||
this.notificationdata = this.DataArray
|
||||
}).catch((error) => {
|
||||
console.error('storage getnotification: ',error)
|
||||
})
|
||||
// }
|
||||
}
|
||||
|
||||
this.DataArray.push(notificationObject)
|
||||
});
|
||||
this.notificationdata = this.DataArray
|
||||
}).catch((error) => {
|
||||
console.error('storage getnotification: ', error)
|
||||
})
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
@@ -198,9 +224,6 @@ export class ProfilePage implements OnInit {
|
||||
|
||||
// this.notificationservice.tempClearArray();
|
||||
this.deleteNotification(index);
|
||||
this.eventTriger.publishSomeData({
|
||||
notification: "deleted"
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -213,8 +236,12 @@ export class ProfilePage implements OnInit {
|
||||
|
||||
this.storageservice.get("Notifications").then((value) => {
|
||||
|
||||
this.eventTriger.publishSomeData({
|
||||
notification: "deleted"
|
||||
})
|
||||
|
||||
}).catch((error) => {
|
||||
console.error('storage delete notification: ',error)
|
||||
console.error('storage delete notification: ', error)
|
||||
})
|
||||
});
|
||||
|
||||
@@ -225,14 +252,14 @@ export class ProfilePage implements OnInit {
|
||||
SessionStore.setUrlBeforeInactivity(this.router.url);
|
||||
this.logoutOut == false
|
||||
|
||||
if(environment.production) {
|
||||
if (environment.production) {
|
||||
window.location.pathname = '/auth'
|
||||
} else {
|
||||
const pathBeforeGoOut = window.location.pathname
|
||||
this.router.navigateByUrl('/auth', { replaceUrl: true });
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
if(this.logoutOut == false || pathBeforeGoOut == window.location.pathname) {
|
||||
if (this.logoutOut == false || pathBeforeGoOut == window.location.pathname) {
|
||||
window.location.pathname = '/auth'
|
||||
} else {
|
||||
|
||||
@@ -268,7 +295,7 @@ export class ProfilePage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
if(this.isProfileOpen == false) {
|
||||
if (this.isProfileOpen == false) {
|
||||
this.isProfileOpen = true;
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
@@ -278,11 +305,11 @@ export class ProfilePage implements OnInit {
|
||||
}
|
||||
});
|
||||
await modal.present();
|
||||
|
||||
|
||||
modal.onDidDismiss().then(() => {
|
||||
this.isProfileOpen = false;
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,15 @@ export class ContactsService {
|
||||
}
|
||||
|
||||
getContacts(namefilter:string): Observable<EventPerson[]>{
|
||||
const geturl = environment.apiURL + 'contacts/get';
|
||||
/* const geturl = environment.apiURL + 'contacts/get' */;
|
||||
const geturl = environment.apiURL + 'userauthentication/list'
|
||||
let params = new HttpParams();
|
||||
|
||||
/* params = params.set("namefilter", namefilter);
|
||||
params = params.set("domain", environment.domain); */
|
||||
|
||||
params = params.set("namefilter", namefilter);
|
||||
params = params.set("domain", environment.domain);
|
||||
params = params.set("domain", "");
|
||||
|
||||
let options = {
|
||||
headers: this.headers,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
import { EventEmitter, Injectable, NgZone } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
@@ -14,6 +14,8 @@ import { ActionPerformed, PushNotificationSchema, PushNotifications, Token, } fr
|
||||
import { notificationObject } from '../models/notifications';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { AngularFireMessaging } from '@angular/fire/messaging';
|
||||
import { Subject } from 'rxjs';
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
@@ -34,6 +36,7 @@ export class NotificationsService {
|
||||
|
||||
active = false
|
||||
isPushNotificationsAvailable = Capacitor.isPluginAvailable('PushNotifications');
|
||||
notificationReceived: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
@@ -42,44 +45,11 @@ export class NotificationsService {
|
||||
private platform: Platform,
|
||||
private router: Router,
|
||||
private zone: NgZone,
|
||||
private eventtrigger: EventTrigger,) {
|
||||
private eventtrigger: EventTrigger,
|
||||
private afMessaging: AngularFireMessaging,) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// registerCallback({type, funx, id = uuidv4()} : {
|
||||
// type: notificationObject,
|
||||
// funx: Function
|
||||
// id?: string
|
||||
// }) {
|
||||
// this.callbacks[id] = { funx, id, type}
|
||||
// return id;
|
||||
// }
|
||||
|
||||
|
||||
// private async runNotificationCallback(notification) {
|
||||
|
||||
// for (const [key, value] of Object.entries(this.callbacks)) {
|
||||
// if(value.type == notification.data.Object) {
|
||||
|
||||
// const dontRepeat = await value.funx(notification)
|
||||
|
||||
// if(dontRepeat) {
|
||||
// delete this.callbacks[key]
|
||||
// }
|
||||
|
||||
// } else if (value.type == '*') {
|
||||
// const dontRepeat = await value.funx(notification)
|
||||
|
||||
// if(dontRepeat) {
|
||||
// delete this.callbacks[key]
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
getTokenByUserIdAndId(user, userID) {
|
||||
// const geturl = environment.apiURL + 'notifications/user/' + userID;
|
||||
|
||||
@@ -87,46 +57,63 @@ export class NotificationsService {
|
||||
}
|
||||
|
||||
requestPermissions() {
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
}
|
||||
|
||||
PushNotifications.requestPermissions().then(result => {
|
||||
if (result.receive === 'granted') {
|
||||
// Register with Apple / Google to receive push via APNS/FCM
|
||||
PushNotifications.register();
|
||||
} else {
|
||||
// Show some error
|
||||
if (this.platform.is('mobile')) {
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
}
|
||||
});
|
||||
PushNotifications.requestPermissions().then(result => {
|
||||
if (result.receive === 'granted') {
|
||||
// Register with Apple / Google to receive push via APNS/FCM
|
||||
PushNotifications.register();
|
||||
} else {
|
||||
// Show some error
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
getAndpostToken(username) {
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
const geturl = environment.apiURL + 'notifications/token';
|
||||
if (this.platform.is('mobile')) {
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
}
|
||||
|
||||
PushNotifications.addListener('registration',
|
||||
(token: Token) => {
|
||||
this.postToken(token.value, geturl)
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.afMessaging.requestToken.subscribe(
|
||||
(token) => {
|
||||
// Save the token to your server for sending notifications
|
||||
console.log('Permission granted! Token:', token);
|
||||
this.postToken(token, geturl)
|
||||
},
|
||||
(error) => {
|
||||
console.error('Permission denied:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const geturl = environment.apiURL + 'notifications/token';
|
||||
PushNotifications.addListener('registration',
|
||||
(token: Token) => {
|
||||
const headers = { 'Authorization': SessionStore.user.BasicAuthKey };
|
||||
const body = {
|
||||
UserId: SessionStore.user.UserId,
|
||||
TokenId: token.value,
|
||||
Status: 1,
|
||||
Service: 1
|
||||
};
|
||||
|
||||
this.http.post<Tokenn>(`${geturl}`, body, { headers }).subscribe(data => {
|
||||
this.active = true
|
||||
|
||||
}, (error) => {
|
||||
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
postToken(token, geturl) {
|
||||
const headers = { 'Authorization': SessionStore.user.BasicAuthKey };
|
||||
const body = {
|
||||
UserId: SessionStore.user.UserId,
|
||||
TokenId: token,
|
||||
Status: 1,
|
||||
Service: 1
|
||||
};
|
||||
this.http.post<Tokenn>(`${geturl}`, body, { headers }).subscribe(data => {
|
||||
this.active = true
|
||||
}, (error) => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
registrationError() {
|
||||
@@ -142,33 +129,47 @@ export class NotificationsService {
|
||||
}
|
||||
|
||||
onReciveForeground() {
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
}
|
||||
|
||||
if(this.platform.is('mobile')) {
|
||||
|
||||
PushNotifications.addListener('pushNotificationReceived',
|
||||
(notification: PushNotificationSchema) => {
|
||||
this.active = true
|
||||
|
||||
console.log(notification)
|
||||
this.storageService.get("Notifications").then((store) => {
|
||||
|
||||
store.push(notification)
|
||||
this.storageService.store("Notifications", store)
|
||||
}).catch((error) => {
|
||||
if (!error) {
|
||||
this.storageService.store("Notifications", [notification])
|
||||
}
|
||||
})
|
||||
|
||||
// this.runNotificationCallback(notification)
|
||||
/* this.eventTriger.publish('notificatioRecive') */
|
||||
this.eventtrigger.publishSomeData({
|
||||
notification: "recive"
|
||||
})
|
||||
if (!this.isPushNotificationsAvailable) {
|
||||
return false
|
||||
}
|
||||
);
|
||||
PushNotifications.addListener('pushNotificationReceived',
|
||||
(notification: PushNotificationSchema) => {
|
||||
this.active = true
|
||||
|
||||
this.storenotification(notification)
|
||||
this.eventtrigger.publishSomeData({
|
||||
notification: "recive"
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
} else {
|
||||
this.afMessaging.messages.subscribe((notification) => {
|
||||
this.storenotification(notification)
|
||||
this.storenotification(notification)
|
||||
this.notificationReceived.emit();
|
||||
this.eventtrigger.publishSomeData({
|
||||
notification: "recive"
|
||||
})
|
||||
// Handle the received message, e.g., show a notification
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
storenotification(notification) {
|
||||
console.log(notification)
|
||||
this.storageService.get("Notifications").then((store) => {
|
||||
|
||||
store.push(notification)
|
||||
this.storageService.store("Notifications", store)
|
||||
}).catch((error) => {
|
||||
if (!error) {
|
||||
this.storageService.store("Notifications", [notification])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onReciveBackground() {
|
||||
|
||||
@@ -35,10 +35,16 @@
|
||||
</div>
|
||||
|
||||
<div title="Perfil" class="div-profile cursor-pointer" (click)="openProfile()">
|
||||
<div *ngIf="this.notificationLength > 0" class="icon-badge">{{notificationLength}}</div>
|
||||
<!-- <div *ngIf="this.notificationLength > 0" class="icon-badge">{{notificationLength}}</div> -->
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="icon" src='assets/images/theme/doneIt/icons-profile.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon" src='assets/images/icons-profile.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
||||
|
||||
<div class="profile-text">
|
||||
<div *ngIf="this.notificationLength > 0" class="icon-badge"
|
||||
style="right: -18px;top: -29px;">
|
||||
{{notificationLength}} </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -156,9 +162,9 @@
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
||||
|
||||
<div class="profile-text">
|
||||
<div *ngIf="this.notificationLength > 0 && !production" class="icon-badge"
|
||||
style="right: -18px;top: -9px;">
|
||||
{{notificationLength}}</div>
|
||||
<div *ngIf="this.notificationLength > 0" class="icon-badge"
|
||||
style="right: -18px;top: -29px;">
|
||||
{{notificationLength}} </div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { PermissionList } from 'src/app/models/permission/permissionList';
|
||||
import { PermissionService } from 'src/app/services/permission.service';
|
||||
import { EventTrigger } from 'src/app/services/eventTrigger.service'
|
||||
import { ActiveTabService } from 'src/app/services/active-tab.service';
|
||||
import { NotificationsService } from 'src/app/services/notifications.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
@@ -27,7 +28,7 @@ export class HeaderPage implements OnInit {
|
||||
hideSearchBtn: boolean = false;
|
||||
notificationdata: any[] = [];
|
||||
DataArray: Array<object> = [];
|
||||
notificationLength: 0;
|
||||
notificationLength: number = 0;
|
||||
SessionStore = SessionStore
|
||||
check: boolean;
|
||||
|
||||
@@ -36,6 +37,7 @@ export class HeaderPage implements OnInit {
|
||||
canOpenSearch = false
|
||||
showProfileModal = false
|
||||
permissionList = new PermissionList();
|
||||
notificationCount: number = 0;
|
||||
|
||||
|
||||
constructor(
|
||||
@@ -48,7 +50,8 @@ export class HeaderPage implements OnInit {
|
||||
public RouteService: RouteService,
|
||||
public p: PermissionService,
|
||||
private eventTriger: EventTrigger,
|
||||
public ActiveTabService: ActiveTabService
|
||||
public ActiveTabService: ActiveTabService,
|
||||
private notificationService: NotificationsService
|
||||
) {
|
||||
this.loggeduser = SessionStore.user;
|
||||
router.events.subscribe((val) => {
|
||||
@@ -60,22 +63,28 @@ export class HeaderPage implements OnInit {
|
||||
|
||||
this.eventTriger.getObservable().subscribe((event) => {
|
||||
if(event.notification == "recive") {
|
||||
this.notificationLengthData()
|
||||
console.log('header', event.notification)
|
||||
this.notificationLength++
|
||||
} else if(event.notification == "deleted") {
|
||||
console.log('header', event.notification)
|
||||
this.notificationLength--
|
||||
}
|
||||
});
|
||||
|
||||
/* this.notificationService.notificationReceived.subscribe(() => {
|
||||
console.log('header', 'event.notification')
|
||||
this.notificationLengthData()
|
||||
}); */
|
||||
|
||||
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.hideSearch();
|
||||
this.update();
|
||||
this.notificationLengthData();
|
||||
|
||||
}
|
||||
|
||||
update() {
|
||||
|
||||
}
|
||||
|
||||
async notificationLengthData() {
|
||||
await this.storageservice.get("Notifications").then((value) => {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
export const firebaseConfig = {
|
||||
apiKey: "AIzaSyAAdHmTFznCMerdT99nrewJgISRvtxPqoY",
|
||||
authDomain: "gabinete-digital-2020.firebaseapp.com",
|
||||
databaseURL: "https://gabinete-digital-2020.firebaseio.com",
|
||||
projectId: "gabinete-digital-2020",
|
||||
storageBucket: "gabinete-digital-2020.appspot.com",
|
||||
messagingSenderId: "800733765231",
|
||||
appId: "1:800733765231:web:28e7792ab150006513779a",
|
||||
measurementId: "G-8QN4BLZ8XK"
|
||||
};
|
||||
Reference in New Issue
Block a user