merge made with peter branch

This commit is contained in:
Eudes Inácio
2024-06-18 12:26:54 +01:00
33 changed files with 438 additions and 217 deletions
@@ -14,6 +14,10 @@ import { AgendaLocalDataSourceService } from './agenda-local-data-source.service
import { EEventFilterStatus } from './model/enums';
import { isHttpError } from '../../http.service';
import { TracingType } from '../../monitoring/opentelemetry/tracer';
import { APINODReturn, APIReturn } from '../../decorator/api-validate-schema.decorator';
import { EventListDataOutputDTOSchema, EventListOutputDTOSchema } from './model/eventListDTOOutput';
import { EventToApproveDataOutputDTOSchema } from './model/eventToApproveListOutputDTO';
import { EventOutputDTOSchema } from './model/eventDTOOutput';
@Injectable({
providedIn: 'root'
@@ -40,33 +44,57 @@ export class AgendaDataRepositoryService {
return this.agendaLocalDataSourceService.createCalendar(currentUserCalendar)
}
async getEventById(id: string) {
async getEventById(id: string, tracing?: TracingType) {
try {
const result = await this.agendaDataService.getEvent(id).pipe(
map((response) => {
console.log('Response', response.data)
console.log('Output', EventMapper.toDomain(response.data))
return EventMapper.toDomain(response.data)
EventMapper.toDomain(response)
return EventMapper.toDomain(response)
})
).toPromise()
return ok(result)
} catch (e) {
if(isHttpError(e)) {
tracing?.setAttribute('status.code', e.status.toString())
if (e.status == 400) {
tracing?.bugFlag()
tracing?.setAttribute('outcome', 'failed')
}
} else {
tracing?.bugFlag()
tracing.setAttribute('outcome', 'failed')
tracing?.setAttribute('map.error', 'true')
tracing?.setAttribute('map.error.context', JSON.stringify(e))
}
return err(e as HttpErrorResponse)
}
}
async getEventToApproveById(id: string) {
async getEventToApproveById(id: string, tracing?: TracingType) {
try {
const result = await this.agendaDataService.getEvent(id).pipe(
map((response) => {
console.log('response',response)
console.log('ToDomain',EventToApproveDetailsMapper.toDomain(response.data))
return EventToApproveDetailsMapper.toDomain(response.data)
console.log('ToDomain',EventToApproveDetailsMapper.toDomain(response))
APINODReturn(EventOutputDTOSchema, response, 'get/Events/${id}', tracing)
return EventToApproveDetailsMapper.toDomain(response)
})
).toPromise()
return ok(result)
} catch (e) {
if(isHttpError(e)) {
tracing?.setAttribute('status.code', e.status.toString())
if (e.status == 400) {
tracing?.bugFlag()
tracing?.setAttribute('outcome', 'failed')
}
} else {
tracing?.bugFlag()
tracing?.setAttribute('outcome', 'failed')
tracing?.setAttribute('map.error', 'true')
tracing?.setAttribute('map.error.context', JSON.stringify(e))
}
return err(e as HttpErrorResponse)
}
@@ -77,7 +105,8 @@ export class AgendaDataRepositoryService {
try {
const result = await this.agendaDataService.getEvents(userId, startDate, endDate, status, category, type).pipe(
map((response) => {
return ListEventMapper.toDomain(response.data, calendarOwnerName, userId)
APINODReturn(EventListDataOutputDTOSchema, response, 'get/Events', tracing)
return ListEventMapper.toDomain(response, calendarOwnerName, userId)
}
)).toPromise()
return ok(result)
@@ -85,8 +114,8 @@ export class AgendaDataRepositoryService {
if(isHttpError(e)) {
tracing?.setAttribute('status.code', e.status.toString())
} else {
console.error(e)
tracing?.setAttribute('map.error', JSON.stringify(e.error))
tracing?.setAttribute('map.error', 'true')
tracing?.setAttribute('map.error.context', JSON.stringify(e))
}
return err(e as HttpErrorResponse)
}
@@ -95,9 +124,10 @@ export class AgendaDataRepositoryService {
async eventToApproveList({ userId, startDate = null, endDate = null, status = EEventFilterStatus.Pending, category = null, type = null, calendarOwnerName = '' }, tracing?: TracingType) {
try {
const result = await this.agendaDataService.getEvents(userId, startDate = null, endDate = null, status, category = null, type = null).pipe(
const result = await this.agendaDataService.getEvents(userId, startDate = null, endDate = null, status, category = null, type = null, tracing).pipe(
map((response) => {
return EventListToApproveMapper.toDomain(response.data, calendarOwnerName, userId)
APINODReturn(EventToApproveDataOutputDTOSchema, response, 'get/ApproveList', tracing)
return EventListToApproveMapper.toDomain(response, calendarOwnerName, userId)
}
)).toPromise()
@@ -106,8 +136,8 @@ export class AgendaDataRepositoryService {
if(isHttpError(e)) {
tracing?.setAttribute('status.code', e.status.toString())
} else {
console.error(e)
tracing?.setAttribute('map.error', JSON.stringify(e.error))
tracing?.setAttribute('map.error', 'true')
tracing?.setAttribute('map.error.context', JSON.stringify(e))
}
return err(e as HttpErrorResponse)
}
@@ -6,6 +6,9 @@ import { SessionStore } from 'src/app/store/session.service';
import { SharedCalendarListOutputDTO, SharedCalendarListOutputDTOSchema } from './model/sharedCalendarOutputDTO';
import { HttpService } from '../../http.service';
import { APIReturn } from '../../decorator/api-validate-schema.decorator';
import { TracingType } from '../../monitoring/opentelemetry/tracer';
import { EventListOutputDTO, EventListOutputDTOSchema } from './model/eventListDTOOutput';
import { EventOutputDTO } from './model/eventDTOOutput';
@Injectable({
providedIn: 'root'
@@ -45,7 +48,8 @@ export class AgendaDataService {
return this.http.post<any>(`${this.baseUrl}/Events`, eventData);
}
getEvents(userId: number, startDate: string, endDate: string, status: number, category: string, type: string): Observable<any> {
// @APIReturn(EventListOutputDTOSchema, 'get/Events')
getEvents(userId: number, startDate: string, endDate: string, status: number, category: string, type: string, tracing?: TracingType): Observable<EventListOutputDTO> {
let params = new HttpParams()
.set('UserId', userId)
@@ -69,7 +73,7 @@ export class AgendaDataService {
return this.http.get<any>(`${this.baseUrl}/Events`, { params });
}
getEvent(id: string): Observable<any> {
getEvent(id: string): Observable<EventOutputDTO> {
return this.http.get<any>(`${this.baseUrl}/Events/${id}`);
}
@@ -131,7 +135,7 @@ export class AgendaDataService {
}
@APIReturn(SharedCalendarListOutputDTOSchema)
// @APIReturn(SharedCalendarListOutputDTOSchema, 'Users/${SessionStore.user.UserId}/ShareCalendar')
async getSharedCalendar() {
return await this.httpService.get<SharedCalendarListOutputDTO>(`${this.baseUrl}/Users/${SessionStore.user.UserId}/ShareCalendar`);
}
@@ -14,7 +14,9 @@ function getTextInsideParentheses(inputString) {
export class EventMapper {
constructor() {}
static toDomain(dto: EventOutputDTO) {
static toDomain(_dto: EventOutputDTO) {
const dto = _dto.data;
let category;
if(dto.category == EEventCategory.Oficial) {
@@ -51,7 +53,9 @@ export class EventMapper {
}
}
return {
"owner": dto.owner,
"HasAttachments": dto.hasAttachments,
"EventComunicationId": 1682,
"EventId": dto.id,
@@ -74,7 +78,7 @@ export class EventMapper {
IsRequired: FEAttendeeType(e.attendeeType) == 'Required',
UserType: "GD",
// "IsPR": false,
attendeeType: FEAttendeeType(e.attendeeType)
attendeeType: FEAttendeeType(e.attendeeType)
// "RoleDescription": null,
// "RoleId": 0
})),
@@ -17,7 +17,7 @@ export class ListEventMapper {
// @XTracer({name:'ListEventMapper/toDomain', log: false, bugPrint: false})
static toDomain(dto: EventListOutputDTO, calendarOwnerName: string, userId: string): EventList {
return dto.map((e) => {
return dto.data.map((e) => {
let category;
if(e.category == EEventCategory.Oficial) {
@@ -16,7 +16,9 @@ function getTextInsideParentheses(inputString) {
export class EventToApproveDetailsMapper {
constructor() {}
static toDomain(dto: EventOutputDTO): EventToApproveDetails {
static toDomain(_dto: EventOutputDTO): EventToApproveDetails {
let dto = _dto.data
let category;
if(dto.category == EEventCategory.Oficial) {
@@ -26,6 +28,11 @@ export class EventToApproveDetailsMapper {
}
let color;
if(dto.ownerType == EEventOwnerType.PR) {
color = 'PR'
} else {
color = 'MDGPR'
}
// if(dto.ownerType != 'PR') {
let ownerType;
@@ -36,7 +43,7 @@ export class EventToApproveDetailsMapper {
} else if(dto.ownerType == EEventOwnerType.Others) {
ownerType = 'Other'
}
let activityInstanceName;
let taskStatus;
@@ -69,9 +76,11 @@ export class EventToApproveDetailsMapper {
return 'Optional'
}
}
return {
"owner": dto.owner,
"serialNumber": dto.id,
"taskStatus": taskStatus,
"originator": {
@@ -19,7 +19,7 @@ export class EventListToApproveMapper {
static toDomain(dtoList: EventToApproveListOutputDTO, calendarOwnerName: string, userId: string): EventToApproveList {
return dtoList.map((dto) => {
return dtoList.data.map((dto) => {
let category;
if(dto.category == EEventCategory.Oficial) {
@@ -27,7 +27,7 @@ export class EventListToApproveMapper {
} else {
category = 'Pessoal'
}
let color;
let workflowDisplayName;
@@ -112,7 +112,3 @@ export class EventListToApproveMapper {
// "InstanceId": "AAMkADVhOGY3ZDQzLTg4ZGEtNDYxMC1iMzc5LTJkMDgwNjMxOWFlZQBGAAAAAABEDW9nKs69TKQcVqQURj8YBwBR2HR2eO7pSpNdD9cc70l+AAAAAAFKAABR2HR2eO7pSpNdD9cc70l+AACK2Od9AAA=",
// "originator": "dlima@gabinetedigital.local"
// }
@@ -1,4 +1,5 @@
import { z } from 'zod';
import { EAttendeeType, EEventCategory, EEventOwnerType, EEventStatus, EEventType } from './enums';
export const AttachmentInputDTOSchema = z.object({
id: z.string().nullable(),
@@ -7,7 +8,7 @@ export const AttachmentInputDTOSchema = z.object({
description: z.string().nullable(),
applicationId: z.number().int(),
}).strict();
const EAttendeeTypeDTO = z.enum(["Required", "Acknowledgment", "Optional"]);
const EAttendeeTypeDTO = z.nativeEnum(EAttendeeType);
const CommentSchema = z.object({
@@ -18,7 +19,7 @@ const CommentSchema = z.object({
const AttendeeSchema = z.object({
id: z.string(),
name: z.string(),
attendeeType: z.enum(["Required", "Acknowledgment", "Optional"]), // ["Required", "Acknowledgment", "Optional"] = [1,2,3]
attendeeType: z.nativeEnum(EAttendeeType), // ["Required", "Acknowledgment", "Optional"] = [1,2,3]
emailAddress: z.string(),
wxUserId: z.number(),
});
@@ -47,27 +48,32 @@ const EventRecurrenceSchema = z.object({
until: z.string()
});
export const EventOutputDTOSchema = z.object({
id: z.string(),
owner: OwnerSchema,
ownerType: z.number(), // ["PR", "MD", "Other"] = [1,2,3],
subject: z.string(),
body: z.string(),
location: z.string(),
startDate: z.string(),
endDate: z.string(),
type: z.string(),
category: z.number(), // ['Oficial', 'Pessoal'] = [1, 2]
attendees: z.array(AttendeeSchema),
isRecurring: z.boolean(),
eventRecurrence: EventRecurrenceSchema,
hasAttachments: z.boolean(),
attachments: z.array(AttachmentInputDTOSchema),
comments: z.array(CommentSchema),
isPrivate: z.boolean(),
isAllDayEvent: z.boolean(),
organizer: OrganizerSchema,
status: z.number(), // ['Pending', 'Revision', 'Approved', 'Declined', 'Communicated', 'ToCommunicate'] = [1, 2, 3, 4, 5, 6]
});
success: z.boolean(),
message: z.string(),
data: z.object({
id: z.string(),
owner: OwnerSchema,
ownerType: z.nativeEnum(EEventOwnerType), // ["PR", "MD", "Other"] = [1,2,3],
subject: z.string(),
body: z.string(),
location: z.string(),
startDate: z.string(),
endDate: z.string(),
type: z.nativeEnum(EEventType),
category: z.nativeEnum(EEventCategory), // ['Oficial', 'Pessoal'] = [1, 2]
attendees: z.array(AttendeeSchema),
isRecurring: z.boolean(),
eventRecurrence: EventRecurrenceSchema,
hasAttachments: z.boolean(),
attachments: z.array(AttachmentInputDTOSchema),
comments: z.array(CommentSchema),
isPrivate: z.boolean(),
isAllDayEvent: z.boolean(),
organizer: OrganizerSchema,
status: z.nativeEnum(EEventStatus), // ['Pending', 'Revision', 'Approved', 'Declined', 'Communicated', 'ToCommunicate'] = [1, 2, 3, 4, 5, 6]
}),
}).nullable();
export type EventOutputDTO = z.infer<typeof EventOutputDTOSchema>
@@ -1,25 +1,40 @@
import { z } from 'zod';
import { EEventCategory, EEventOwnerType, EEventStatus, EEventType } from './enums';
const EventSchema = z.array(z.object({
const OwnerSchema = z.object({
wxUserId: z.number(),
wxFullName: z.string(),
wxeMail: z.string(),
userPhoto: z.string(),
});
export const EventListOutputDTOSchema = z.object({
id: z.string(),
owner: z.string().nullable(),
owner: OwnerSchema,
ownerType: z.nativeEnum(EEventOwnerType),// ['MD','PR', 'Other'] // Assuming "MD" is the only valid option based on provided data
subject: z.string(),
body: z.string(),
location: z.string(),
location: z.string().nullable(),
startDate: z.string().datetime({ offset: true }),
endDate: z.string().datetime({ offset: true }),
type: z.nativeEnum(EEventType), // ['Meeting', 'Travel'] = [1,2 ]
// category: z.enum(['Oficial', 'Pessoal']), // Assuming "Oficial" is the only valid option based on provided data
category: z.nativeEnum(EEventCategory),
isRecurring: z.boolean(),
eventRecurrence: z.null(),
eventRecurrence: z.any().nullable(),
hasAttachments: z.boolean(),
isPrivate: z.boolean(),
isAllDayEvent: z.boolean(),
// status: z.enum(['Approved']), // Assuming "Approved" is the only valid option based on provided data
status: z.nativeEnum(EEventStatus), // Assuming "Approved" is the only valid option based on provided data
}))
})
export type EventListOutputDTO = z.infer<typeof EventSchema>;
export const EventListDataOutputDTOSchema = z.object({
success: z.boolean(),
message: z.string(),
data: z.array(EventListOutputDTOSchema),
}).nullable();
export type EventListOutputDTO = z.infer<typeof EventListDataOutputDTOSchema>;
@@ -1,15 +1,24 @@
import { z } from "zod";
import { EEventOwnerType, EEventType, EEventCategory, EEventStatus } from "./enums";
const OwnerSchema = z.object({
wxUserId: z.number(),
wxFullName: z.string(),
wxeMail: z.string(),
userPhoto: z.string(),
});
const EventToApproveList = z.array(z.object({
id: z.string().uuid(),
owner: z.string().nullable(),
owner: OwnerSchema,
ownerType: z.nativeEnum(EEventOwnerType),
subject: z.string(),
body: z.string(),
location: z.string(),
startDate: z.string().datetime(),
endDate: z.string().datetime(),
location: z.string().nullable(),
startDate: z.string().datetime({ offset: true }),
endDate: z.string().datetime({ offset: true }),
type: z.nativeEnum(EEventType),
category: z.nativeEnum(EEventCategory),
isRecurring: z.boolean(),
@@ -20,4 +29,11 @@ const EventToApproveList = z.array(z.object({
status: z.nativeEnum(EEventStatus)
}))
export type EventToApproveListOutputDTO = z.infer<typeof EventToApproveList>;
export const EventToApproveDataOutputDTOSchema = z.object({
success: z.boolean(),
message: z.string(),
data: EventToApproveList,
}).nullable();
export type EventToApproveListOutputDTO = z.infer<typeof EventToApproveDataOutputDTOSchema>;
+1 -1
View File
@@ -186,7 +186,7 @@ export class AuthService {
this.RochetChatConnectorService.logout();
this.RochetChatConnectorService.connect();
this.RochetChatConnectorService.login().then((message: any) => {
console.log('Chat login', message)
// console.log('Chat login', message)
SessionStore.user.RochetChatUserId = message.result.id
SessionStore.save()
@@ -2,8 +2,9 @@ import { HttpErrorResponse } from '@angular/common/http';
import { Result, err } from 'neverthrow';
import { z, ZodError } from 'zod';
import * as Sentry from '@sentry/capacitor';
import { TracingType } from '../monitoring/opentelemetry/tracer';
export function APIReturn(schema: z.ZodTypeAny) {
export function APIReturn(schema: z.ZodTypeAny, path: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
@@ -19,13 +20,8 @@ export function APIReturn(schema: z.ZodTypeAny) {
if (error instanceof ZodError) {
// If validation fails, throw an error with the details
//
console.log('unexpected data structure')
console.error('unexpected data structure', path)
// Capture the Zod validation error with additional context
Sentry.withScope((scope) => {
scope.setTag('APIReturn', 'user');
scope.setContext('data', { data: result.value });
Sentry.captureException(error);
});
console.error('Validation failed:', error.errors);
} else {
console.log('failed to setup the connection successful')
@@ -34,7 +30,7 @@ export function APIReturn(schema: z.ZodTypeAny) {
}
}
} else {
console.log()
// console.log()
// result.error.
}
@@ -43,3 +39,33 @@ export function APIReturn(schema: z.ZodTypeAny) {
return descriptor;
}
}
export function APINODReturn(schema: z.ZodTypeAny, data , path: string, tracing?: TracingType) {
try {
// Validate the result using the provided schema
schema.parse(data);
} catch (error) {
if (error instanceof ZodError) {
// If validation fails, throw an error with the details
//
console.error('unexpected data structure', path)
// Capture the Zod validation error with additional context
console.error('Validation failed:', error.errors);
tracing?.setAttribute('APIReturn.error', 'true')
let i = 0;
for(const schema of error.errors) {
tracing?.setAttribute('map.error.schema-'+i, JSON.stringify(schema))
}
} else {
// Throw any other unexpected errors
throw error;
}
}
}
+1 -1
View File
@@ -420,7 +420,7 @@ export class EventsService {
isMyEvent(event: any) {
const data: any = event
return data.Organizer.Id == SessionStore.user.UserId
return data.owner.wxUserId == SessionStore.user.UserId
}
@@ -27,6 +27,10 @@ export class CaptureLogService {
}
setToken() {
}
interceptLogs() {
(() => {
const originalConsoleLog = console.log;
@@ -13,7 +13,7 @@ function createProvider(serviceName) {
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.addSpanProcessor(new SimpleSpanProcessor(new ZipkinExporter({
url: 'https://5.180.182.151/zipkin-endpoint/api/v2/spans',
url: 'http://5.180.182.151:9411/api/v2/spans',
serviceName: serviceName,
// Uncomment and customize the following if needed
// getExportRequestHeaders: () => {
@@ -4,6 +4,7 @@ import { Tracer, Span } from '@opentelemetry/sdk-trace-base';
import { OpentelemetryAgendaProvider } from './opentelemetry';
import { Device, DeviceInfo } from '@capacitor/device';
const tracerInstance = OpentelemetryAgendaProvider.getTracer('example-tracer-hole', '111', {
})
@@ -81,12 +82,18 @@ export function XTracerAsync({ name, log, bugPrint }: any, p0?: any) {
try {
const result = await originalMethod.apply(this, args);
tracing.finish()
if(!window.location.origin.includes('https')) {
tracing.finish()
}
return result
} catch (e) {
tracing.finish()
if(!window.location.origin.includes('https')) {
tracing.finish()
}
console.error(e);
return false
}
@@ -162,12 +169,18 @@ export function XTracer({name, log, bugPrint}: any) {
try {
const result = originalMethod.apply(this, args);
tracing.finish()
if(!window.location.origin.includes('https')) {
tracing.finish()
}
return result
} catch (e) {
tracing.finish()
if(!window.location.origin.includes('https')) {
tracing.finish()
}
console.error(e);
return false
}
+1 -1
View File
@@ -334,7 +334,7 @@ export class TaskService {
let allEvents = await this.AgendaDataRepositoryService.eventToApproveList({
userId,
status: EEventFilterStatus.Pending
})
}, tracing)
if(allEvents.isOk()) {
tracing.setAttribute('outcome', 'success')