- +

{{customDate}}

diff --git a/src/app/pages/login/login.page.ts b/src/app/pages/login/login.page.ts index 90efc91fa..66c33ff08 100644 --- a/src/app/pages/login/login.page.ts +++ b/src/app/pages/login/login.page.ts @@ -179,7 +179,6 @@ export class LoginPage implements OnInit { await this.AgendaDataRepositoryService.clearSharedCalendar() - await this.AgendaDataRepositoryService.createOwnCalendar() this.RochetChatConnectorService.logout(); this.clearStoreService.clear(); this.ChatSystemService.clearChat(); diff --git a/src/app/services/Repositorys/Agenda/agenda-data-repository.service.ts b/src/app/services/Repositorys/Agenda/agenda-data-repository.service.ts index abc549cfd..7e9a8d593 100644 --- a/src/app/services/Repositorys/Agenda/agenda-data-repository.service.ts +++ b/src/app/services/Repositorys/Agenda/agenda-data-repository.service.ts @@ -18,6 +18,8 @@ import { APINODReturn, APIReturn } from '../../decorator/api-validate-schema.dec import { EventListDataOutputDTOSchema, EventListOutputDTOSchema } from './model/eventListDTOOutput'; import { EventToApproveDataOutputDTOSchema } from './model/eventToApproveListOutputDTO'; import { EventOutputDTOSchema } from './model/eventDTOOutput'; +import { SharedCalendarListDetectChanges } from './async/change/shareCalendarChangeDetector'; +import { SharedCalendarListItemOutputDTO } from './model/sharedCalendarOutputDTO'; @Injectable({ providedIn: 'root' @@ -30,7 +32,7 @@ export class AgendaDataRepositoryService { private agendaLocalDataSourceService: AgendaLocalDataSourceService ) { } - createOwnCalendar() { + createOwnCalendar(): SharedCalendarListItemOutputDTO { const currentUserCalendar = { wxUserId: SessionStore.user.UserId, wxFullName: SessionStore.user.FullName, @@ -41,7 +43,7 @@ export class AgendaDataRepositoryService { date: '', } - return this.agendaLocalDataSourceService.createCalendar(currentUserCalendar) + return currentUserCalendar } async getEventById(id: string, tracing?: TracingType) { @@ -54,6 +56,7 @@ export class AgendaDataRepositoryService { ).toPromise() return ok(result) } catch (e) { + tracing.setAttribute('eventId', id) if(isHttpError(e)) { tracing?.setAttribute('status.code', e.status.toString()) if (e.status == 400) { @@ -83,6 +86,7 @@ export class AgendaDataRepositoryService { ).toPromise() return ok(result) } catch (e) { + tracing.setAttribute('eventId', id) if(isHttpError(e)) { tracing?.setAttribute('status.code', e.status.toString()) if (e.status == 400) { @@ -238,22 +242,41 @@ export class AgendaDataRepositoryService { async getSharedCalendar() { const result = await this.agendaDataService.getSharedCalendar() + const localList = await this.agendaLocalDataSourceService.geCalendars() if (result.isOk()) { - if (result.value?.data) { - - await this.agendaLocalDataSourceService.clearSharedCalendar() - await this.createOwnCalendar() - return await this.agendaLocalDataSourceService.bulkCreate(result.value.data) + if(!result.value?.data) { + result.value.data = [this.createOwnCalendar()] } else { - await this.agendaLocalDataSourceService.clearSharedCalendar() - await this.createOwnCalendar() - return result + result.value.data.push(this.createOwnCalendar()) } + + const { remove, insert, update } = SharedCalendarListDetectChanges(localList, result.value.data) + + for(const item of insert) { + this.agendaLocalDataSourceService.createCalendar(item) + } + + for(const item of remove) { + this.agendaLocalDataSourceService.removeCalendar(item) + } + } else { - await this.agendaLocalDataSourceService.clearSharedCalendar() - return await this.createOwnCalendar() + + if(isHttpError(result.error)) { + if (result.error.status == 404) { + const remove = localList.filter(e => e.wxUserId != SessionStore.user.UserId) + + for(const item of remove) { + this.agendaLocalDataSourceService.removeCalendar(item) + } + + } + } + + const item = this.createOwnCalendar() + this.agendaLocalDataSourceService.createCalendar(item) } } diff --git a/src/app/services/Repositorys/Agenda/agenda-local-data-source.service.ts b/src/app/services/Repositorys/Agenda/agenda-local-data-source.service.ts index fd594f1da..dab92dda0 100644 --- a/src/app/services/Repositorys/Agenda/agenda-local-data-source.service.ts +++ b/src/app/services/Repositorys/Agenda/agenda-local-data-source.service.ts @@ -55,6 +55,16 @@ export class AgendaLocalDataSourceService { } } + async removeCalendar(data: SharedCalendarListItemOutputDTO) { + // db.eve + try { + const result = await AgendaDataSource.shareCalendar.delete(data.wxUserId) + return ok(result) + } catch (e) { + return err(false) + } + } + clearSharedCalendar() { // db.eve try { diff --git a/src/app/services/Repositorys/Agenda/async/change/shareCalendarChangeDetector.ts b/src/app/services/Repositorys/Agenda/async/change/shareCalendarChangeDetector.ts new file mode 100644 index 000000000..2f0eee567 --- /dev/null +++ b/src/app/services/Repositorys/Agenda/async/change/shareCalendarChangeDetector.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { SharedCalendarListItemOutputDTO } from "../../model/sharedCalendarOutputDTO"; + +type Changes = { + insert: SharedCalendarListItemOutputDTO[]; + update: SharedCalendarListItemOutputDTO[]; + remove: SharedCalendarListItemOutputDTO[]; +}; + +export function SharedCalendarListDetectChanges( + localList: SharedCalendarListItemOutputDTO[], + serverList: SharedCalendarListItemOutputDTO[] +): Changes { + const changes: Changes = { insert: [], update: [], remove: [] }; + + const localMap = new Map(localList.map(item => [item.wxUserId, item])); + const serverMap = new Map(serverList.map(item => [item.wxUserId, item])); + + // Detect new or updated items + for (const [id, serverItem] of serverMap) { + const localItem = localMap.get(id); + if (!localItem) { + changes.insert.push(serverItem); + } else if (localItem.wxFullName !== serverItem.wxFullName) { + changes.update.push(serverItem); + } + } + + // Detect deleted items + for (const [id, localItem] of localMap) { + if (!serverMap.has(id)) { + changes.remove.push(localItem); + } + } + + return changes; +} diff --git a/src/app/services/Repositorys/Agenda/model/enums.ts b/src/app/services/Repositorys/Agenda/model/enums.ts index ad702044f..25fb0fba9 100644 --- a/src/app/services/Repositorys/Agenda/model/enums.ts +++ b/src/app/services/Repositorys/Agenda/model/enums.ts @@ -6,7 +6,7 @@ export enum EEventFilterStatus { Declined, Communicated, ToCommunicate, - AllToCommunicate, + AllToCommunicate, // approvado e to communicate PendingEvents, } @@ -41,11 +41,10 @@ export enum EEventType Travel, Conference, } - + export enum EAttendeeType { Required = 1, Acknowledgment, Optional } - \ No newline at end of file diff --git a/src/app/services/monitoring/opentelemetry/opentelemetry.ts b/src/app/services/monitoring/opentelemetry/opentelemetry.ts index 74bda8d1d..c2334fa3f 100644 --- a/src/app/services/monitoring/opentelemetry/opentelemetry.ts +++ b/src/app/services/monitoring/opentelemetry/opentelemetry.ts @@ -30,4 +30,5 @@ function createProvider(serviceName) { // Example usage: export const OpentelemetryChatProvider = createProvider('FO-chat-service'); export const OpentelemetryAgendaProvider = createProvider('FO-agenda-service'); +export const OpentelemetryNotificationProvider = createProvider('FO-notification'); export const OpentelemetryPublicationProvider = createProvider('FO-publication-service'); diff --git a/src/app/services/monitoring/opentelemetry/tracer.ts b/src/app/services/monitoring/opentelemetry/tracer.ts index 19dcca15d..f3474bd80 100644 --- a/src/app/services/monitoring/opentelemetry/tracer.ts +++ b/src/app/services/monitoring/opentelemetry/tracer.ts @@ -1,13 +1,13 @@ import { v4 as uuidv4 } from 'uuid'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { Tracer, Span } from '@opentelemetry/sdk-trace-base'; -import { OpentelemetryAgendaProvider } from './opentelemetry'; +import { OpentelemetryAgendaProvider, OpentelemetryNotificationProvider } from './opentelemetry'; import { Device, DeviceInfo } from '@capacitor/device'; -const tracerInstance = OpentelemetryAgendaProvider.getTracer('example-tracer-hole', '111', { +const tracerInstance = OpentelemetryAgendaProvider.getTracer('example-tracer-hole', '111', {}) +const tracerNotificationInstance = OpentelemetryNotificationProvider.getTracer('example-tracer-hole', '111', {}) -}) // const logger: ILoggerAdapter = new ColoredLoggerService() let device: DeviceInfo; @@ -16,7 +16,64 @@ Device.getInfo().then(e => { device = e }); -export function XTracerAsync({ name, log, bugPrint }: any, p0?: any) { + +const createTracingInstance = ({bugPrint, name, module, autoFinish}): TracingType => { + const requestId = uuidv4() + + let _tracerInstance:Tracer + + if(module == 'notification') { + _tracerInstance = tracerNotificationInstance + } else { + _tracerInstance = tracerInstance + } + + const span = _tracerInstance.startSpan(name); + let hasBug:Boolean + + const data = { + event: {}, + tags: {} + } + + return { + span: span as any, + tracer: tracerInstance, + tracerId: requestId, + attributes: SemanticAttributes, + setStatus: (status: any) => { + span.setStatus(status); + }, + addEvent: (context: string, message?: any, obj?: any) => { + + data.event[context] = message; + + const value = [JSON.stringify(message)] as any + span.addEvent(context, value); + }, + LocalLogEvent:(context: string, message: any, obj: any) => { + data.tags[context] = message; + }, + setAttribute: (key: string, value: string) => { + data.tags[key] = value; + span.setAttribute(key, value); + }, + finish: () => { + span.end(); + if(bugPrint && hasBug) { + console.error(name, data) + } + }, + bugFlag:() => { + hasBug = true + }, + createSpan: (name, parent?: any) => { + return tracerInstance.startSpan(name, { root: false }, parent) as Span; + } + } +} + +export function XTracerAsync({ name, log, bugPrint, module = null, autoFinish = true }) { return ( target: unknown, propertyKey: string, @@ -25,55 +82,9 @@ export function XTracerAsync({ name, log, bugPrint }: any, p0?: any) { const originalMethod = descriptor.value; descriptor.value = async function (...args: unknown[]) { - const requestId = uuidv4() - const span = tracerInstance.startSpan(name); - let hasBug:Boolean - const data = { - event: {}, - tags: {} - } + const tracing = createTracingInstance({bugPrint, name, module, autoFinish}) - const createTracingInstance = (): TracingType => { - - return { - span: span as any, - tracer: tracerInstance, - tracerId: requestId, - attributes: SemanticAttributes, - setStatus: (status: any) => { - span.setStatus(status); - }, - addEvent: (context: string, message?: any, obj?: any) => { - - data.event[context] = message; - - const value = [JSON.stringify(message)] as any - span.addEvent(context, value); - }, - LocalLogEvent:(context: string, message: any, obj: any) => { - data.tags[context] = message; - }, - setAttribute: (key: string, value: string) => { - data.tags[key] = value; - span.setAttribute(key, value); - }, - finish: () => { - span.end(); - if(bugPrint && hasBug) { - console.error(name, data) - } - }, - bugFlag:() => { - hasBug = true - }, - createSpan: (name, parent?: any) => { - return tracerInstance.startSpan(name, { root: false }, parent) as Span; - } - } - } - - const tracing = createTracingInstance() tracing.setAttribute('current.page', window.location.pathname); tracing.setAttribute('device.name', device?.name || device?.model) @@ -83,16 +94,17 @@ export function XTracerAsync({ name, log, bugPrint }: any, p0?: any) { const result = await originalMethod.apply(this, args); if(!window.location.origin.includes('https')) { - tracing.finish() + if(autoFinish) { + tracing.finish() + } } - - return result } catch (e) { - if(!window.location.origin.includes('https')) { - tracing.finish() + if(autoFinish) { + tracing.finish() + } } console.error(e); return false @@ -102,7 +114,7 @@ export function XTracerAsync({ name, log, bugPrint }: any, p0?: any) { } -export function XTracer({name, log, bugPrint}: any) { +export function XTracer({ name, log, bugPrint, module, autoFinish = true }: any) { return ( target: unknown, propertyKey: string, @@ -111,56 +123,8 @@ export function XTracer({name, log, bugPrint}: any) { const originalMethod = descriptor.value; descriptor.value = function (...args: unknown[]) { - const requestId = uuidv4() - const span = tracerInstance.startSpan(name); + const tracing = createTracingInstance({bugPrint, name, module, autoFinish}) - let hasBug:Boolean - - const data = { - event: {}, - tags: {} - } - - const createTracingInstance = (): TracingType => { - - return { - span: span as any, - tracer: tracerInstance, - tracerId: requestId, - attributes: SemanticAttributes, - setStatus: (status: any) => { - span.setStatus(status); - }, - addEvent: (context: string, message?: any, obj?: any) => { - - data.event[context] = message; - - const value = [JSON.stringify(message)] as any - span.addEvent(context, value); - }, - LocalLogEvent:(context: string, message: any, obj: any) => { - data.tags[context] = message; - }, - setAttribute: (key: string, value: string) => { - data.tags[key] = value; - span.setAttribute(key, value); - }, - finish: () => { - span.end(); - if(bugPrint && hasBug) { - console.error(name, data) - } - }, - bugFlag:() => { - hasBug = true - }, - createSpan: (name, parent?: any) => { - return tracerInstance.startSpan(name, { root: false }, parent) as Span; - } - } - } - - const tracing = createTracingInstance() tracing.setAttribute('current.page', window.location.pathname); tracing.setAttribute('device.name', device?.name || device?.model) @@ -169,15 +133,12 @@ export function XTracer({name, log, bugPrint}: any) { try { const result = originalMethod.apply(this, args); - if(!window.location.origin.includes('https')) { tracing.finish() } - return result } catch (e) { - if(!window.location.origin.includes('https')) { tracing.finish() } diff --git a/src/app/services/notifications.service.ts b/src/app/services/notifications.service.ts index 8a26feedf..26a162a47 100644 --- a/src/app/services/notifications.service.ts +++ b/src/app/services/notifications.service.ts @@ -18,7 +18,7 @@ import { ChatService } from 'src/app/services/chat.service'; import { FCM } from '@capacitor-community/fcm'; import { ChatSystemService } from './chat/chat-system.service'; import {ChatController} from 'src/app/controller/chat' - +import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer'; @Injectable({ providedIn: 'root' }) @@ -99,7 +99,8 @@ export class NotificationsService { } } - private getAndpostToken(username) { + @XTracerAsync({name:'Notification/getAndpostToken', log: false, bugPrint: true, module:'notification', autoFinish: false}) + private getAndpostToken(username, tracing?: TracingType) { const geturl = environment.apiURL + 'notifications/token'; if (this.platform.is('mobile')) { @@ -109,31 +110,44 @@ export class NotificationsService { if (this.platform.is('ios')) { FCM.getToken() .then(r => { - this.postToken(r.token, geturl) + this.postToken(r.token, geturl, tracing) this.token = r.token + tracing.setAttribute('notification.token', 'true') + tracing.setAttribute('outcome', 'success') // alert(this.token) }) - .catch(err => console.log(err)); + .catch(err => { + console.log(err) + tracing.setAttribute('notification.token', 'false') + tracing.setAttribute('outcome', 'failed') + }); } else { PushNotifications.addListener('registration', (token: Token) => { - this.postToken(token.value, geturl) + this.postToken(token.value, geturl, tracing) this.token = token.value + tracing.setAttribute('notification.token', 'true') + } ); } } else { + tracing.setAttribute('notification.request', 'true') this.afMessaging.requestToken.subscribe( (token) => { // Save the token to your server for sending notifications console.log('Permission granted! Token:', token); - this.postToken(token, geturl) + this.postToken(token, geturl, tracing) this.token = token + tracing.setAttribute('notification.token', 'true') + tracing.setAttribute('outcome', 'success') }, (error) => { console.error('Permission denied:', error); + tracing.setAttribute('notification.token', 'false') + tracing.setAttribute('outcome', 'failed') } ); } @@ -146,7 +160,7 @@ export class NotificationsService { this.DeleteToken(geturl) } - postToken(token, geturl) { + postToken(token, geturl, tracing: TracingType) { const headers = { 'Authorization': SessionStore.user.BasicAuthKey }; const body = { UserId: SessionStore.user.UserId, @@ -156,8 +170,11 @@ export class NotificationsService { }; this.http.post(`${geturl}`, body, { headers }).subscribe(data => { this.active = true + tracing.setAttribute('outcome','success') + tracing.finish() }, (error) => { - + tracing.setAttribute('outcome','failed') + tracing.finish() }) }