mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 12:37:53 +00:00
fix publication
This commit is contained in:
@@ -0,0 +1,170 @@
|
|||||||
|
# 📅 6-Month LinkedIn Content Calendar for Peter (Full-Stack Developer)
|
||||||
|
|
||||||
|
This is a practical roadmap to grow your visibility and influence on LinkedIn.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌍 LinkedIn Fame Roadmap
|
||||||
|
|
||||||
|
### Phase 1 – Foundation (Weeks 1–2)
|
||||||
|
- Optimize profile (photo, banner, headline, about, featured projects).
|
||||||
|
- Follow 100+ relevant devs, recruiters, and companies.
|
||||||
|
|
||||||
|
### Phase 2 – Consistency (Weeks 3–6)
|
||||||
|
- Post 3–4 times per week.
|
||||||
|
- Share lessons, demos, explainers, and personal wins.
|
||||||
|
- Engage with other posts.
|
||||||
|
|
||||||
|
### Phase 3 – Authority Building (Months 2–4)
|
||||||
|
- Write long-form articles (e.g., offline-first, clean architecture).
|
||||||
|
- Share diagrams, benchmarks, and tutorials.
|
||||||
|
- Start a content series.
|
||||||
|
|
||||||
|
### Phase 4 – Expansion (Months 4–6)
|
||||||
|
- Collaborate with other devs.
|
||||||
|
- Speak in webinars or podcasts.
|
||||||
|
- Share across GitHub, Dev.to, Medium.
|
||||||
|
|
||||||
|
### Phase 5 – Thought Leadership (Months 6+)
|
||||||
|
- Release libraries/tools.
|
||||||
|
- Do live coding sessions.
|
||||||
|
- Mentor juniors, share insights.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 📅 Content Calendar
|
||||||
|
|
||||||
|
## Month 1 – Kickoff & Personal Branding
|
||||||
|
**Goal**: Introduce yourself and build recognition.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Intro post: “I’m Peter, a full-stack dev passionate about scalable apps & clean architecture.”
|
||||||
|
- Share your tech stack (Angular, Node.js, Redis, RabbitMQ, OpenTelemetry, Nginx).
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Story: “How I solved a 5GB+ file upload challenge.”
|
||||||
|
- Quick explainer: “What is distributed tracing & why should devs care?”
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Share a coding tip from your daily work.
|
||||||
|
- Comment on trending dev posts.
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- Failure story: “I misconfigured Nginx SSL once, here’s the lesson.”
|
||||||
|
- Diagram: “Reverse proxy explained in 30 seconds.”
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Month 2 – Technical Authority
|
||||||
|
**Goal**: Show deep technical knowledge.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Article: “Offline-first architecture in Angular.”
|
||||||
|
- LinkedIn summary post linking to article.
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Redis vs. DB caching.
|
||||||
|
- Code snippet with before/after perf gain.
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Diagram: RabbitMQ message flow.
|
||||||
|
- Debugging queue bottleneck tip.
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- OpenTelemetry case: “Frontend + Backend performance tracing.”
|
||||||
|
- Engage with 10 influencers’ posts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Month 3 – Visibility Boost
|
||||||
|
**Goal**: Grow network and reach.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Series: “Clean Architecture in Practice (Part 1: Principles).”
|
||||||
|
- Share a GitHub repo demo.
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Poll: Biggest scaling pain?
|
||||||
|
- Humor/meme about dev life.
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Case study: Angular rendering optimization.
|
||||||
|
- Video: whiteboard explanation.
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- Share someone else’s post with your perspective.
|
||||||
|
- Open-source contribution story.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Month 4 – Expansion
|
||||||
|
**Goal**: Gain recognition outside current network.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Article: Scaling Angular apps with Nginx & Redis.
|
||||||
|
- Share in groups.
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Live mini-demo of debugging/tracing.
|
||||||
|
- Checklist: “5 things every scalable backend must have.”
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Share book/article you loved.
|
||||||
|
- Poll: “What do you log in production?”
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- Failure/lesson post.
|
||||||
|
- Tutorial: Nginx SSL in 5 steps.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Month 5 – Community Building
|
||||||
|
**Goal**: Start building a following.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Launch LinkedIn series/group: “Scalable Full-Stack Weekly.”
|
||||||
|
- Ask network for topic ideas.
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Monitoring with Prometheus + OpenTelemetry.
|
||||||
|
- Show a metrics dashboard screenshot.
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Article: Clean architecture for offline-first mobile apps.
|
||||||
|
- Share summary post.
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- Journey post: “From beginner to distributed systems.”
|
||||||
|
- Engage with 20+ posts this week.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Month 6 – Thought Leadership
|
||||||
|
**Goal**: Become a go-to expert.
|
||||||
|
|
||||||
|
- **Week 1**:
|
||||||
|
- Reflection post: “6 months of writing on LinkedIn.”
|
||||||
|
- Poll: Which post helped you most?
|
||||||
|
|
||||||
|
- **Week 2**:
|
||||||
|
- Release a small tool/framework.
|
||||||
|
- Write article introducing it.
|
||||||
|
|
||||||
|
- **Week 3**:
|
||||||
|
- Mentorship post: “If I started full-stack dev in 2025…”
|
||||||
|
- Share GitHub contributions/stats.
|
||||||
|
|
||||||
|
- **Week 4**:
|
||||||
|
- Case study: “How I built a resilient offline-first app.”
|
||||||
|
- Reflection: invite more followers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# ⚡ Daily Engagement Habits
|
||||||
|
- Comment on 5 posts/day with value.
|
||||||
|
- Send 2–3 connection requests/day.
|
||||||
|
- Reply to all comments within 24h.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
✅ With consistency + authenticity, expect exponential growth by **Month 3–4**.
|
||||||
+34
-55
@@ -64,19 +64,9 @@ import { CustomImageCachePageRoutingModule } from './services/file/custom-image-
|
|||||||
import { IonicImageLoaderModule } from 'ionic-image-loader-v5';
|
import { IonicImageLoaderModule } from 'ionic-image-loader-v5';
|
||||||
import { NgxExtendedPdfViewerModule } from 'ngx-extended-pdf-viewer';
|
import { NgxExtendedPdfViewerModule } from 'ngx-extended-pdf-viewer';
|
||||||
import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
|
import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
|
||||||
|
|
||||||
|
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatNativeDateModule } from '@angular/material/core';
|
import { MatNativeDateModule } from '@angular/material/core';
|
||||||
|
|
||||||
|
|
||||||
// The example is using Angular, Import '@sentry/vue' or '@sentry/react' when using a Sibling different than Angular.
|
|
||||||
import * as SentrySibling from '@sentry/angular';
|
import * as SentrySibling from '@sentry/angular';
|
||||||
import * as Sentry from '@sentry/capacitor';
|
|
||||||
// The e xample is using Angular, Import '@sentry/vue' or '@sentry/react' when using a Sibling different than Angular.
|
|
||||||
// For automatic instrumentation (highly recommended)
|
|
||||||
import { Integration } from '@sentry/types';
|
|
||||||
import { BrowserTracing } from '@sentry/tracing';
|
|
||||||
import { AngularFireModule } from '@angular/fire';
|
import { AngularFireModule } from '@angular/fire';
|
||||||
import { AngularFireMessagingModule } from '@angular/fire/messaging';
|
import { AngularFireMessagingModule } from '@angular/fire/messaging';
|
||||||
import { firebaseConfig } from '../firebase-config';
|
import { firebaseConfig } from '../firebase-config';
|
||||||
@@ -87,26 +77,26 @@ import { LoggingInterceptorService } from './services/logging-interceptor.servic
|
|||||||
import { PopupQuestionPipe } from './modals/popup-question.pipe';
|
import { PopupQuestionPipe } from './modals/popup-question.pipe';
|
||||||
import '@teamhive/capacitor-video-recorder';
|
import '@teamhive/capacitor-video-recorder';
|
||||||
import { tokenInterceptor } from './infra/monitoring/interceptors/token.interceptors';
|
import { tokenInterceptor } from './infra/monitoring/interceptors/token.interceptors';
|
||||||
|
|
||||||
import { InputFilterDirective } from './services/directives/input-filter.directive';
|
import { InputFilterDirective } from './services/directives/input-filter.directive';
|
||||||
import { DeplomaOptionsPageModule } from './shared/popover/deploma-options/deploma-options.module';
|
import { DeplomaOptionsPageModule } from './shared/popover/deploma-options/deploma-options.module';
|
||||||
import { DiplomaOptionsPage } from './shared/popover/deploma-options/deploma-options.page';
|
import { DiplomaOptionsPage } from './shared/popover/deploma-options/deploma-options.page';
|
||||||
import { ImageCropperModule } from 'ngx-image-cropper';
|
import { ImageCropperModule } from 'ngx-image-cropper';
|
||||||
import { metricsInterceptor } from './infra/monitoring/interceptors/metter.interceptor';
|
import { metricsInterceptor } from './infra/monitoring/interceptors/metter.interceptor';
|
||||||
|
|
||||||
import {MatMenuModule} from '@angular/material/menu';
|
import {MatMenuModule} from '@angular/material/menu';
|
||||||
import {MatIconModule} from '@angular/material/icon';
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
import { ChatModule } from './module/chat/chat.module';
|
import { ChatModule } from './module/chat/chat.module';
|
||||||
import { openTelemetryLogging } from './services/monitoring/opentelemetry/logging';
|
|
||||||
|
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localePt from '@angular/common/locales/pt';
|
import localePt from '@angular/common/locales/pt';
|
||||||
import { LogsDatabase } from './infra/database/dexie/instance/logs/service';
|
|
||||||
import { UserModule } from './module/user/user.module';
|
import { UserModule } from './module/user/user.module';
|
||||||
import { Logger } from './services/logger/main/service';
|
import { Logger } from './services/logger/main/service';
|
||||||
|
|
||||||
// Register the locale data
|
|
||||||
registerLocaleData(localePt, 'pt');
|
registerLocaleData(localePt, 'pt');
|
||||||
|
import * as Sentry from '@sentry/capacitor';
|
||||||
|
import { Integration } from '@sentry/types';
|
||||||
|
import { BrowserTracing } from '@sentry/tracing';
|
||||||
|
import { LogsDatabase } from './infra/database/dexie/instance/logs/service';
|
||||||
|
import { AppErrorHandler } from './infra/crash-analytics/app-error-handler';
|
||||||
|
|
||||||
|
|
||||||
// Sentry.init(
|
// Sentry.init(
|
||||||
// {
|
// {
|
||||||
@@ -117,11 +107,7 @@ registerLocaleData(localePt, 'pt');
|
|||||||
// // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
|
// // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
|
||||||
// // We recommend adjusting this value in production.
|
// // We recommend adjusting this value in production.
|
||||||
// tracesSampleRate: 1.0,
|
// tracesSampleRate: 1.0,
|
||||||
// integrations: [
|
// debug: true, // logs to console
|
||||||
// new BrowserTracing({
|
|
||||||
// tracingOrigins: ['localhost', 'https://gd-api.oapr.gov.ao/api/'],
|
|
||||||
// }) as Integration,
|
|
||||||
// ],
|
|
||||||
// beforeSend(event) {
|
// beforeSend(event) {
|
||||||
// console.log('event.exception.values[0].value', event.exception.values[0].value);
|
// console.log('event.exception.values[0].value', event.exception.values[0].value);
|
||||||
|
|
||||||
@@ -131,19 +117,17 @@ registerLocaleData(localePt, 'pt');
|
|||||||
// console.log('event', event)
|
// console.log('event', event)
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// openTelemetryLogging.send({
|
// // openTelemetryLogging.send({
|
||||||
// level: 'info',
|
// // level: 'info',
|
||||||
// message: event.exception.values[0].value,
|
// // message: event.exception.values[0].value,
|
||||||
// payload: {
|
// // payload: {
|
||||||
// object: {
|
// // object: {
|
||||||
// sentry: true,
|
// // sentry: true,
|
||||||
// error: event
|
// // error: event
|
||||||
|
// // }
|
||||||
|
// // },
|
||||||
|
// // })
|
||||||
// }
|
// }
|
||||||
// },
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log('Sentry Event', event);
|
|
||||||
// // Return event to send it to Sentry
|
// // Return event to send it to Sentry
|
||||||
// return event;
|
// return event;
|
||||||
// },
|
// },
|
||||||
@@ -151,18 +135,6 @@ registerLocaleData(localePt, 'pt');
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
|
|
||||||
import Tracker from '@openreplay/tracker';
|
|
||||||
import trackerAssist from '@openreplay/tracker-assist'; // 👈 for errors, logs & stack traces
|
|
||||||
const tracker = new Tracker({
|
|
||||||
projectKey: "g8HOZiBi5iUWEsK3Ajw5",
|
|
||||||
__DISABLE_SECURE_MODE: true, // ✅ allow HTTP + localhost
|
|
||||||
});
|
|
||||||
tracker.start()
|
|
||||||
tracker.use(trackerAssist());
|
|
||||||
tracker.setUserID('john@doe.com');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
const httpLogs = [];
|
const httpLogs = [];
|
||||||
|
|
||||||
@@ -186,9 +158,15 @@ tracker.setUserID('john@doe.com');
|
|||||||
let requestPayload = null;
|
let requestPayload = null;
|
||||||
if (config?.body) {
|
if (config?.body) {
|
||||||
try {
|
try {
|
||||||
requestPayload = typeof config.body === "string"
|
if (typeof config.body === "string") {
|
||||||
? config.body
|
requestPayload = config.body;
|
||||||
: JSON.stringify(config.body);
|
} else if (config.body !== null && typeof config.body === "object") {
|
||||||
|
// Keep plain objects/arrays as-is
|
||||||
|
requestPayload = config.body;
|
||||||
|
} else {
|
||||||
|
// For other cases (like FormData, Blob, etc.), attempt safe stringify
|
||||||
|
requestPayload = JSON.stringify(config.body);
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
requestPayload = "[Unserializable body]";
|
requestPayload = "[Unserializable body]";
|
||||||
}
|
}
|
||||||
@@ -307,7 +285,7 @@ tracker.setUserID('john@doe.com');
|
|||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if(xhr.status >= 400 || xhr.status === 0) {
|
if(xhr.status >= 400 && !log.url.includes('petermaquiran.xyz') || xhr.status === 0 && !log.url.includes('petermaquiran.xyz')) {
|
||||||
Logger.error('XHR', log)
|
Logger.error('XHR', log)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,11 +376,12 @@ tracker.setUserID('john@doe.com');
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MAT_DATE_LOCALE, useValue: 'pt' },
|
{ provide: MAT_DATE_LOCALE, useValue: 'pt' },
|
||||||
{
|
//{ provide: ErrorHandler, useClass: AppErrorHandler },
|
||||||
provide: ErrorHandler,
|
// {
|
||||||
// Attach the Sentry ErrorHandler
|
// provide: ErrorHandler,
|
||||||
useValue: SentrySibling.createErrorHandler(),
|
// // Attach the Sentry ErrorHandler
|
||||||
},
|
// useValue: SentrySibling.createErrorHandler(),
|
||||||
|
// },
|
||||||
StatusBar,
|
StatusBar,
|
||||||
//SplashScreen,
|
//SplashScreen,
|
||||||
HttpClient,
|
HttpClient,
|
||||||
@@ -433,7 +412,7 @@ tracker.setUserID('john@doe.com');
|
|||||||
FFmpeg,
|
FFmpeg,
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true },
|
||||||
tokenInterceptor,
|
tokenInterceptor,
|
||||||
metricsInterceptor
|
metricsInterceptor,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { ActionLocalRepositoryService } from 'src/app/module/actions/data/reposi
|
|||||||
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
|
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
|
||||||
export const ActionsCreateInputDTOSchema = z.object({
|
export const ActionsCreateInputDTOSchema = z.object({
|
||||||
userId: z.number(),
|
userId: z.number(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
@@ -19,7 +18,6 @@ export const ActionsCreateInputDTOSchema = z.object({
|
|||||||
});
|
});
|
||||||
export type ActionsCreateInput = z.infer<typeof ActionsCreateInputDTOSchema>
|
export type ActionsCreateInput = z.infer<typeof ActionsCreateInputDTOSchema>
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const ActionsUpdateInputDTOSchema = z.object({
|
||||||
|
userId: z.number(),
|
||||||
|
description: z.string(),
|
||||||
|
detail: z.string(),
|
||||||
|
location: z.string(),
|
||||||
|
dateBegin: z.string().refine((val) => !isNaN(Date.parse(val)), {
|
||||||
|
message: "Invalid ISO date string",
|
||||||
|
}),
|
||||||
|
dateEnd: z.string().refine((val) => !isNaN(Date.parse(val)), {
|
||||||
|
message: "Invalid ISO date string",
|
||||||
|
}),
|
||||||
|
actionType: z.string(),
|
||||||
|
processId: z.number()
|
||||||
|
});
|
||||||
|
export type ActionsUpdateInput = z.infer<typeof ActionsUpdateInputDTOSchema>
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ActionsUpdateUseCaseService {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PublicationRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-remote-repository.service';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const FileSchema = z.object({
|
||||||
|
originalFileName: z.string(),
|
||||||
|
fileBase64: z.string(),
|
||||||
|
fileExtension: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PublicationCreateInputDtoSchema = z.object({
|
||||||
|
userId: z.number(),
|
||||||
|
dateIndex: z.string().datetime(), // validates ISO date string
|
||||||
|
title: z.string(),
|
||||||
|
message: z.string(),
|
||||||
|
datePublication: z.string().datetime(), // validates ISO date string
|
||||||
|
files: z.array(FileSchema),
|
||||||
|
organicEntityId: z.number(),
|
||||||
|
processId: z.number()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type PublicationCreateInputDto = z.infer<typeof PublicationCreateInputDtoSchema>;
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class PublicationCreateUseCaseService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private remote: PublicationRemoteRepositoryService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
execute(input: PublicationCreateInputDto) {
|
||||||
|
return this.remote.createPublication(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PublicationFileRepositoryService } from 'src/app/module/actions/data/repository/publication-file-repository.service';
|
||||||
|
import { IPublicationDocument, PublicationDocumentEntitySchema } from '../entity/publicationDocument';
|
||||||
|
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||||
|
import { MessageUpdateInput } from '../../chat/usecase/message/message-update-by-id-use-case.service';
|
||||||
|
import { Logger } from 'src/app/services/logger/main/service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class PublicationFilesDeleteByPathUseCaseService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private remote: PublicationFileRepositoryService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
execute(file: IPublicationDocument) {
|
||||||
|
|
||||||
|
const validation = zodSafeValidation<MessageUpdateInput>(PublicationDocumentEntitySchema, file)
|
||||||
|
|
||||||
|
if(validation.isOk()) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Logger.error('failed to update message, validation failed', {
|
||||||
|
zodErrorList: validation.error.errors,
|
||||||
|
data: file
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return this.remote.deleteFile(`${file.path}\\${file.name}.${file.extension}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ export class PublicationListByProcessIdService {
|
|||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
const publications = result.value.data.data || [];
|
const publications = result.value.data.data || [];
|
||||||
|
|
||||||
var localList = await this.local.findAll();
|
var localList = await this.local.find({processId: processId});
|
||||||
|
|
||||||
if(localList.isOk()) {
|
if(localList.isOk()) {
|
||||||
|
|
||||||
@@ -72,7 +72,8 @@ export class PublicationListByProcessIdService {
|
|||||||
// detect added & updated
|
// detect added & updated
|
||||||
for (const [id, serverItem] of serverMap) {
|
for (const [id, serverItem] of serverMap) {
|
||||||
if (!localMap.has(id)) {
|
if (!localMap.has(id)) {
|
||||||
console.log(localList.value.map(item => item.documentId.toString()).join(","), id);
|
console.log(serverMap.get(id), "addddddd");
|
||||||
|
console.log(localList, publications);
|
||||||
added.push(serverMap.get(id));
|
added.push(serverMap.get(id));
|
||||||
} else if (serverItem.datePublication !== localMap.get(id).datePublication) {
|
} else if (serverItem.datePublication !== localMap.get(id).datePublication) {
|
||||||
updated.push(serverMap.get(id));
|
updated.push(serverMap.get(id));
|
||||||
@@ -84,7 +85,7 @@ export class PublicationListByProcessIdService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// detect removed
|
// detect removed
|
||||||
for (const [id, localItem] of Object.keys(localMap)) {
|
for (const [id, localItem] of localMap) {
|
||||||
if (!serverMap.has(id)) {
|
if (!serverMap.has(id)) {
|
||||||
remove.push(localMap.get(id));
|
remove.push(localMap.get(id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PublicationRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-remote-repository.service';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
const FileSchema = z.object({
|
||||||
|
originalFileName: z.string(),
|
||||||
|
fileBase64: z.string(),
|
||||||
|
fileExtension: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PublicationUpdateInputDtoSchema = z.object({
|
||||||
|
userId: z.number(),
|
||||||
|
dateIndex: z.string().datetime(), // validates ISO date string
|
||||||
|
title: z.string(),
|
||||||
|
message: z.string(),
|
||||||
|
datePublication: z.string().datetime(), // validates ISO date string
|
||||||
|
files: z.array(FileSchema),
|
||||||
|
organicEntityId: z.number(),
|
||||||
|
processId: z.number(),
|
||||||
|
documentId: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type PublicationUpdateInputDto = z.infer<typeof PublicationUpdateInputDtoSchema>;
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class PublicationUpdateUseCaseService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private remote: PublicationRemoteRepositoryService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
execute(input: PublicationUpdateInputDto) {
|
||||||
|
return this.remote.updatePublication(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,8 @@ export const MessageEntitySchema = z.object({
|
|||||||
info: z.array(z.object({
|
info: z.array(z.object({
|
||||||
memberId: z.number(),
|
memberId: z.number(),
|
||||||
readAt: z.string().nullable(),
|
readAt: z.string().nullable(),
|
||||||
deliverAt: z.string().nullable()
|
deliverAt: z.string().nullable(),
|
||||||
|
isDeleted: z.boolean().optional(),
|
||||||
})).optional(),
|
})).optional(),
|
||||||
sending: z.boolean().optional(),
|
sending: z.boolean().optional(),
|
||||||
attachments: z.array(MessageEntityAttachmentSchema).optional(),
|
attachments: z.array(MessageEntityAttachmentSchema).optional(),
|
||||||
@@ -121,4 +122,8 @@ export class MessageEntity {
|
|||||||
return this.sender?.wxUserId == SessionStore.user.UserId
|
return this.sender?.wxUserId == SessionStore.user.UserId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _isDeleted() {
|
||||||
|
return this.isDeleted || this.info.filter(e =>e.memberId == SessionStore.user.UserId && e.isDeleted).length == 1
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class ListenMessageByRoomIdNewUseCase {
|
|||||||
|
|
||||||
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
return this.MessageSocketRepositoryService.listenToMessages().pipe(
|
||||||
map(message => message.data),
|
map(message => message.data),
|
||||||
filter((message) => message?.deviceId != getInstanceId()),
|
filter((message) => message?.deviceId != getInstanceId() && data.roomId == message?.roomId),
|
||||||
map(message => {
|
map(message => {
|
||||||
return Object.assign(new MessageEntity(), message)
|
return Object.assign(new MessageEntity(), message)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ export class RoomBoldSyncUseCaseService {
|
|||||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||||
) {
|
) {
|
||||||
this.listenToIncomingMessage();
|
this.listenToIncomingMessage();
|
||||||
// this.loadHistory()
|
|
||||||
//this.onInsertToDB()
|
|
||||||
this.listenToUpdateMessages();
|
this.listenToUpdateMessages();
|
||||||
this.loadHistory()
|
this.loadHistory()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export class RoomSetLastMessageService {
|
|||||||
if(room.messages?.[0]?.id == message.id) {
|
if(room.messages?.[0]?.id == message.id) {
|
||||||
|
|
||||||
// incoming _message does not have sender
|
// incoming _message does not have sender
|
||||||
const messageToUpdate = ({...room.messages?.[0],isDeleted: true})
|
const messageToUpdate = ({...room.messages?.[0],isDeleted: true, info: message.info})
|
||||||
|
|
||||||
const result = await this.roomLocalRepository.update(room.$id, {
|
const result = await this.roomLocalRepository.update(room.$id, {
|
||||||
messages: [messageToUpdate]
|
messages: [messageToUpdate]
|
||||||
@@ -170,7 +170,7 @@ export class RoomSetLastMessageService {
|
|||||||
}),
|
}),
|
||||||
map((response: any) => response.value.data as IMessageGetAllByRoomIdOutPut)
|
map((response: any) => response.value.data as IMessageGetAllByRoomIdOutPut)
|
||||||
).subscribe(async (data)=> {
|
).subscribe(async (data)=> {
|
||||||
const loadHistoryFirstMessage = data.data[0]
|
const loadHistoryFirstMessage = Object.assign(new MessageEntity(), data.data[0]);
|
||||||
if(loadHistoryFirstMessage) {
|
if(loadHistoryFirstMessage) {
|
||||||
|
|
||||||
const roomId = loadHistoryFirstMessage.roomId
|
const roomId = loadHistoryFirstMessage.roomId
|
||||||
@@ -184,7 +184,9 @@ export class RoomSetLastMessageService {
|
|||||||
messages: [loadHistoryFirstMessage]
|
messages: [loadHistoryFirstMessage]
|
||||||
})
|
})
|
||||||
} else if (roomEntity.hasLastMessage()) {
|
} else if (roomEntity.hasLastMessage()) {
|
||||||
const localLastMessageDate = new Date(room.value.messages[0].sentAt).getTime()
|
var lastMessage = Object.assign(new MessageEntity(), room.value.messages[0]);
|
||||||
|
|
||||||
|
const localLastMessageDate = new Date(lastMessage.sentAt).getTime()
|
||||||
const loadHistoryLastMessageDate = new Date(loadHistoryFirstMessage.sentAt).getTime()
|
const loadHistoryLastMessageDate = new Date(loadHistoryFirstMessage.sentAt).getTime()
|
||||||
|
|
||||||
if(loadHistoryFirstMessage.id == room.value.messages?.[0]?.id) {
|
if(loadHistoryFirstMessage.id == room.value.messages?.[0]?.id) {
|
||||||
@@ -214,7 +216,7 @@ export class RoomSetLastMessageService {
|
|||||||
|
|
||||||
} else if(loadHistoryLastMessageDate == localLastMessageDate) {
|
} else if(loadHistoryLastMessageDate == localLastMessageDate) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else if(room.value.messages[0].isDeleted != loadHistoryFirstMessage.isDeleted) {
|
} else if(lastMessage._isDeleted != loadHistoryFirstMessage._isDeleted) {
|
||||||
// await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, {
|
// await this.roomLocalRepository.update(loadHistoryFirstMessage.roomId, {
|
||||||
// messages: [loadHistoryFirstMessage]
|
// messages: [loadHistoryFirstMessage]
|
||||||
// })
|
// })
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { z } from "zod";
|
|||||||
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||||
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
import { IRoomRemoteRepository } from 'src/app/core/chat/repository/room/room-remote-repository';
|
||||||
|
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||||
|
import { RoomByIdOutputDTO, RoomByIdOutputDTOSchema } from './room-get-by-id-use-case.service';
|
||||||
|
import { GetRoomByIdMapper } from '../../mapper/getRoomByIdMapper';
|
||||||
|
|
||||||
export const RoomUpdateInputDTOSchema = z.object({
|
export const RoomUpdateInputDTOSchema = z.object({
|
||||||
roomName: z.string(),
|
roomName: z.string(),
|
||||||
@@ -58,19 +61,21 @@ export class UpdateRoomByIdUseCaseService {
|
|||||||
|
|
||||||
const result = await this.roomRemoteDataSourceService.updateRoom(data)
|
const result = await this.roomRemoteDataSourceService.updateRoom(data)
|
||||||
|
|
||||||
if(result.isOk()) {
|
// if(result.isOk()) {
|
||||||
const localList = await this.roomLocalDataSourceService.findAll()
|
// const result = await this.roomRemoteDataSourceService.getRoom(data.roomId)
|
||||||
// const { roomsToDelete, roomsToInsert, roomsToUpdate } = roomListDetermineChanges([result.value.data], localList)
|
|
||||||
|
|
||||||
// for( const roomData of roomsToUpdate) {
|
// if(result.isOk()) {
|
||||||
// if(!roomData.chatRoom.createdBy?.wxUserId) {
|
// const localListRoom = await this.roomLocalDataSourceService.findAll()
|
||||||
// delete roomData.chatRoom.createdBy;
|
// if(localListRoom.isOk()) {
|
||||||
|
|
||||||
|
// const getRoomById = await this.roomLocalDataSourceService.findOne({id:result.value.data.id})
|
||||||
|
// if(getRoomById.isOk() && getRoomById.value) {
|
||||||
|
// const room = GetRoomByIdMapper.toDomain(result.value)
|
||||||
|
// this.roomLocalDataSourceService.update(room.id, room)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// this.roomLocalDataSourceService.updateRoom(roomData.chatRoom)
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export class SocketMessageDeleteUseCaseService {
|
|||||||
if(result.isOk() && result.value) {
|
if(result.isOk() && result.value) {
|
||||||
|
|
||||||
tracing?.addEvent("Message found")
|
tracing?.addEvent("Message found")
|
||||||
const updateResult = await this.messageLocalDataSourceService.update(result.value.$id, { isDeleted: true })
|
const updateResult = await this.messageLocalDataSourceService.update(result.value.$id, { isDeleted: true, info: input.info })
|
||||||
return updateResult
|
return updateResult
|
||||||
}else {
|
}else {
|
||||||
tracing.hasError("failed to delete message")
|
tracing.hasError("failed to delete message")
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ export class UserLoginUseCaseService {
|
|||||||
return err(result.error.status as LoginError)
|
return err(result.error.status as LoginError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return err(LoginError.userNotFound);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tracing.setAttribute('parameter error','true')
|
tracing.setAttribute('parameter error','true')
|
||||||
// Logger.error('failed to send message doe to invalid attachment', {
|
// Logger.error('failed to send message doe to invalid attachment', {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// app-error-handler.ts
|
||||||
|
import { ErrorHandler, Injectable } from '@angular/core';
|
||||||
|
import * as crypto from 'crypto-js'; // install: npm install crypto-js
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppErrorHandler implements ErrorHandler {
|
||||||
|
private sentErrors = new Set<string>(); // cache of sent error hashes
|
||||||
|
|
||||||
|
handleError(error: any): void {
|
||||||
|
const normalizedError = this.normalizeError(error);
|
||||||
|
|
||||||
|
// Only send if stack trace exists
|
||||||
|
if (!normalizedError.stack) {
|
||||||
|
console.warn('Error without stack trace skipped:', normalizedError.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate hash (message + stack)
|
||||||
|
const hash = crypto.SHA256(normalizedError.message + normalizedError.stack).toString();
|
||||||
|
|
||||||
|
if (this.sentErrors.has(hash)) {
|
||||||
|
console.debug('Duplicate error skipped:', normalizedError.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sentErrors.add(hash);
|
||||||
|
|
||||||
|
// 🚀 Send error to monitoring service
|
||||||
|
this.sendToServer(normalizedError, hash);
|
||||||
|
|
||||||
|
console.error('Global error captured:', normalizedError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private normalizeError(error: any): { message: string; stack?: string } {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return { message: error.message, stack: error.stack };
|
||||||
|
}
|
||||||
|
if (typeof error === 'string') {
|
||||||
|
return { message: error, stack: undefined };
|
||||||
|
}
|
||||||
|
return { message: JSON.stringify(error), stack: (error?.stack || undefined) };
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendToServer(error: { message: string; stack?: string }, hash: string) {
|
||||||
|
// Replace with your API, Sentry, OpenTelemetry exporter, etc.
|
||||||
|
fetch('/api/log-error', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ ...error, hash }),
|
||||||
|
}).catch((err) => console.warn('Failed to send error:', err));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,8 @@ export const MessageTableSchema = z.object({
|
|||||||
info: z.array(z.object({
|
info: z.array(z.object({
|
||||||
memberId: z.number(),
|
memberId: z.number(),
|
||||||
readAt: z.string().nullable(),
|
readAt: z.string().nullable(),
|
||||||
deliverAt: z.string().nullable()
|
deliverAt: z.string().nullable(),
|
||||||
|
isDeleted: z.boolean().optional(),
|
||||||
})).optional(),
|
})).optional(),
|
||||||
attachments: z.array(z.object({
|
attachments: z.array(z.object({
|
||||||
fileType: z.nativeEnum(MessageAttachmentFileType),
|
fileType: z.nativeEnum(MessageAttachmentFileType),
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ export class HttpService {
|
|||||||
constructor(private http: HttpClient) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
private async handleRequest<T>(fux: Function, tracing?: TracingType, url?: string, method?: string): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
|
private async handleRequest<T>(fux: Function, tracing?: TracingType, url?: string, method?: string): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
|
||||||
var response = await fux(tracing) as HttpResponse<T>
|
|
||||||
try {
|
try {
|
||||||
|
var response = await fux(tracing) as HttpResponse<T>
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
data: response.body,
|
data: response.body,
|
||||||
status: response.status,
|
status: response.status,
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import { Router } from "@angular/router";
|
|||||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||||
import { Platform } from '@ionic/angular';
|
import { Platform } from '@ionic/angular';
|
||||||
import { UserLoginOutputResponse } from "../../../core/user/repository/user-remote-repository";
|
import { UserLoginOutputResponse } from "../../../core/user/repository/user-remote-repository";
|
||||||
import { UserLoginMapper } from "../../../core/user/mapper/user-login";
|
|
||||||
import { UserSession } from "../../../models/user.model";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TokenInterceptor implements HttpInterceptor {
|
export class TokenInterceptor implements HttpInterceptor {
|
||||||
@@ -51,14 +49,12 @@ export class TokenInterceptor implements HttpInterceptor {
|
|||||||
return next.handle(request).pipe(
|
return next.handle(request).pipe(
|
||||||
|
|
||||||
catchError((error) => {
|
catchError((error) => {
|
||||||
console.log('interceptor ',error)
|
|
||||||
if(error.url.includes('/Users/RefreshToken') && error.status === 401) {
|
if(error.url.includes('/Users/RefreshToken') && error.status === 401) {
|
||||||
console.log("refresh token error11",error)
|
|
||||||
return throwError(error);
|
return throwError(error);
|
||||||
}
|
}
|
||||||
else if (error instanceof HttpErrorResponse && error.status === 401) {
|
else if (error instanceof HttpErrorResponse && error.status === 401) {
|
||||||
return this.handle401Error(request, next);
|
return this.handle401Error(request, next);
|
||||||
} else if (error.url.includes(`${environment.apiURL.slice(0, -1)}`) && error.status === 0){
|
} else if (error.url.includes(`${environment.apiURLStage.slice(0, -1)}`) && error.status === 0) {
|
||||||
return this.handle401Error(request, next);
|
return this.handle401Error(request, next);
|
||||||
} else {
|
} else {
|
||||||
return throwError(error);
|
return throwError(error);
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// import Tracker from '@openreplay/tracker';
|
||||||
|
// import trackerAssist from '@openreplay/tracker-assist'; // 👈 for errors, logs & stack traces
|
||||||
|
// import { SessionStore } from 'src/app/store/session.service';
|
||||||
|
|
||||||
|
// export function initOpenReplay() {
|
||||||
|
// const shouldEnableTracker =
|
||||||
|
// !window.location.href.includes('oapr') &&
|
||||||
|
// !window.location.href.includes('localhost')
|
||||||
|
|
||||||
|
// if (shouldEnableTracker) {
|
||||||
|
// const tracker = new Tracker({
|
||||||
|
// projectKey: 'g8HOZiBi5iUWEsK3Ajw5',
|
||||||
|
// __DISABLE_SECURE_MODE: true,
|
||||||
|
// network: {
|
||||||
|
// // === Required for TS compatibility ===
|
||||||
|
// sessionTokenHeader: false, // 👈 explicitly set (default = false)
|
||||||
|
// // === Capture settings ===
|
||||||
|
// capturePayload: true, // ✅ capture request/response bodies
|
||||||
|
// failuresOnly: false, // set true if you only want 4xx/5xx
|
||||||
|
// ignoreHeaders: ['Cookie', 'Set-Cookie', 'Authorization'], // default sensitive headers
|
||||||
|
// captureInIframes: false,
|
||||||
|
|
||||||
|
// // === Sanitizer to avoid leaking secrets ===
|
||||||
|
// sanitizer: (data) => {
|
||||||
|
// // Example: sanitize login payload
|
||||||
|
// if (data.url.includes('/login') && data.request.body) {
|
||||||
|
// try {
|
||||||
|
// const body = JSON.parse(data.request.body as string)
|
||||||
|
// if (body.password) body.password = '<REDACTED>'
|
||||||
|
// data.request.body = JSON.stringify(body)
|
||||||
|
// } catch {
|
||||||
|
// // drop non-JSON body
|
||||||
|
// data.request.body = null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Example: redact custom auth token header
|
||||||
|
// if (data.request.headers['x-auth-token']) {
|
||||||
|
// data.request.headers['x-auth-token'] = '<REDACTED>'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Example: truncate very large responses
|
||||||
|
// if (
|
||||||
|
// typeof data.response.body === 'string' &&
|
||||||
|
// data.response.body.length > 5000
|
||||||
|
// ) {
|
||||||
|
// data.response.body =
|
||||||
|
// data.response.body.slice(0, 5000) + '...[truncated]'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return data
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
|
||||||
|
// tracker.start()
|
||||||
|
// tracker.use(trackerAssist())
|
||||||
|
// tracker.setUserID(SessionStore.user?.FullName || ''); // 👈 set current user ID
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
@@ -131,7 +131,7 @@ export class SignalRConnection {
|
|||||||
|
|
||||||
this.sendDataSubject.pipe(
|
this.sendDataSubject.pipe(
|
||||||
filter((message) => {
|
filter((message) => {
|
||||||
return input.data.requestId == message?.data.requestId ||
|
return input.data.requestId == message?.data?.requestId ||
|
||||||
input?.data?.roomName == message?.data.roomName && typeof input?.data?.roomName == 'string'
|
input?.data?.roomName == message?.data.roomName && typeof input?.data?.roomName == 'string'
|
||||||
|
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { HttpModule } from 'src/app/infra/http/http.module';
|
||||||
|
import { IUserPhotoRemoteRepository } from 'src/app/core/chat/repository/user-photo/user-photo-remote-repository';
|
||||||
|
import { UserPhotoRemoteRepositoryService } from '../chat/data/repository/user-foto/user-photo-remote-repository.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [HttpModule],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: IUserPhotoRemoteRepository,
|
||||||
|
useClass: UserPhotoRemoteRepositoryService
|
||||||
|
},
|
||||||
|
],
|
||||||
|
declarations: [],
|
||||||
|
schemas: [],
|
||||||
|
entryComponents: []
|
||||||
|
})
|
||||||
|
export class ActionsModule {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActionsCreateInput } from 'src/app/core/actions/use-case/actions-create-use-case.service';
|
import { ActionsCreateInput } from 'src/app/core/actions/use-case/actions-create-use-case.service';
|
||||||
import { ActionGetAllOutPut } from 'src/app/core/actions/use-case/actions-get-all-use-case.service';
|
import { ActionGetAllOutPut } from 'src/app/core/actions/use-case/actions-get-all-use-case.service';
|
||||||
|
import { ActionsUpdateInput } from 'src/app/core/actions/use-case/actions-update-use-case.service';
|
||||||
import { PublicationGetDocumentByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-get-documents-by-document-id.service';
|
import { PublicationGetDocumentByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-get-documents-by-document-id.service';
|
||||||
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
|
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
|
||||||
import { HttpService } from 'src/app/infra/http/http.service';
|
import { HttpService } from 'src/app/infra/http/http.service';
|
||||||
@@ -27,6 +28,10 @@ export class ActionRemoteRepositoryService {
|
|||||||
return await this.http.post<ApiResponse<any>>(`${this.baseUrl}`, input);
|
return await this.http.post<ApiResponse<any>>(`${this.baseUrl}`, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async update(input: ActionsUpdateInput) {
|
||||||
|
return await this.http.put<ApiResponse<any>>(`${this.baseUrl}/${input.processId}`, input);
|
||||||
|
}
|
||||||
|
|
||||||
async postGetListByProcessId(processId: string) {
|
async postGetListByProcessId(processId: string) {
|
||||||
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
|
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpService } from 'src/app/infra/http/http.service';
|
||||||
|
import { ApiResponse } from 'src/app/infra/http/type';
|
||||||
|
import { environment } from 'src/environments/environment';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class PublicationFileRepositoryService {
|
export class PublicationFileRepositoryService {
|
||||||
|
|
||||||
constructor() { }
|
private baseUrl = `${environment.apiURLStage.slice(0, -1)}/PresidentialActions`; // Your base URL
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private http: HttpService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
async deleteFile(path: string) {
|
||||||
|
return await this.http.delete<ApiResponse<any>>(
|
||||||
|
`${this.baseUrl}/posts/file`,{ path }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { PublicationCreateInputDto } from 'src/app/core/actions/use-case/publication-create-use-case.service';
|
||||||
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
|
import { PublicationListByProcessIdOutPut } from 'src/app/core/actions/use-case/publication-list-by-process-id.service';
|
||||||
|
import { PublicationUpdateInputDto } from 'src/app/core/actions/use-case/publication-update-use-case.service';
|
||||||
import { HttpService } from 'src/app/infra/http/http.service';
|
import { HttpService } from 'src/app/infra/http/http.service';
|
||||||
import { ApiResponse } from 'src/app/infra/http/type';
|
import { ApiResponse } from 'src/app/infra/http/type';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
@@ -18,4 +20,12 @@ export class PublicationRemoteRepositoryService {
|
|||||||
async listByProcessId(processId: number) {
|
async listByProcessId(processId: number) {
|
||||||
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
|
return await this.http.get<ApiResponse<PublicationListByProcessIdOutPut>>(`${this.baseUrl}/${processId}/Posts`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createPublication(input: PublicationCreateInputDto) {
|
||||||
|
return await this.http.post<ApiResponse<PublicationCreateInputDto>>(`${this.baseUrl}/${input.processId}/Posts`, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updatePublication(input: PublicationUpdateInputDto) {
|
||||||
|
return await this.http.put<ApiResponse<PublicationUpdateInputDto>>(`${this.baseUrl}/${input.processId}/Posts/${input.documentId}`, input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,14 @@ export function messageListDetermineChanges(serverList: MessageTable[], localLis
|
|||||||
return localItem && (item.editedAt !== localItem.editedAt || item.isDeleted !== localItem.isDeleted || item.sentAt != item.sentAt || item.reactions.some((r, index) => {
|
return localItem && (item.editedAt !== localItem.editedAt || item.isDeleted !== localItem.isDeleted || item.sentAt != item.sentAt || item.reactions.some((r, index) => {
|
||||||
const localReaction = localItem.reactions[index];
|
const localReaction = localItem.reactions[index];
|
||||||
return !localReaction || r.reactedAt !== localReaction.reactedAt;
|
return !localReaction || r.reactedAt !== localReaction.reactedAt;
|
||||||
|
}) ||
|
||||||
|
item.info.some((info, index) => {
|
||||||
|
const localInfo = localItem.info[index];
|
||||||
|
return !localInfo ||
|
||||||
|
info.memberId !== localInfo.memberId ||
|
||||||
|
info.readAt !== localInfo.readAt ||
|
||||||
|
info.deliverAt !== localInfo.deliverAt ||
|
||||||
|
info.isDeleted !== localInfo.isDeleted;
|
||||||
})) ;
|
})) ;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { IUserRemoteRepository } from 'src/app/core/user/repository/user-remote-repository';
|
|
||||||
import { UserLoginInput, UserLoginUseCaseService } from 'src/app/core/user/use-case/user-login-use-case.service';
|
import { UserLoginInput, UserLoginUseCaseService } from 'src/app/core/user/use-case/user-login-use-case.service';
|
||||||
import { UserLogOutUseCaseService } from 'src/app/core/user/use-case/user-log-out-use-case.service';
|
import { UserLogOutUseCaseService } from 'src/app/core/user/use-case/user-log-out-use-case.service';
|
||||||
import { SessionStore } from './service/session.service'
|
|
||||||
import { UserEntity } from 'src/app/core/user/entity/userEntity';
|
|
||||||
import { UserRefreshTokenService } from 'src/app/core/user/use-case/user-refresh-token.service';
|
import { UserRefreshTokenService } from 'src/app/core/user/use-case/user-refresh-token.service';
|
||||||
|
//import { initOpenReplay } from 'src/app/infra/open-replay';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
@@ -21,8 +20,7 @@ export class UserService {
|
|||||||
const result = await this.userLoginUseCaseService.execute(input)
|
const result = await this.userLoginUseCaseService.execute(input)
|
||||||
|
|
||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
|
//initOpenReplay();
|
||||||
// SessionStore.reset(new UserEntity({...result.value, ...result.value.user}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
+2
-2
@@ -297,9 +297,9 @@ export class DiplomaAssinarPage implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.processes.presidentialActionsSignature(body).toPromise()
|
await this.processes.createSignatureV2(body);
|
||||||
|
|
||||||
await this.Assinar();
|
//await this.Assinar();
|
||||||
this.TaskService.loadDiplomas();
|
this.TaskService.loadDiplomas();
|
||||||
this.goBack();
|
this.goBack();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ ion-item-option {
|
|||||||
border: 1px solid #d30a0a;
|
border: 1px solid #d30a0a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 701px) {
|
//@media only screen and (min-width: 701px) {
|
||||||
.content-right {
|
.content-right {
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
width: 65%;
|
width: 65%;
|
||||||
@@ -255,22 +255,22 @@ ion-item-option {
|
|||||||
display: block !important;
|
display: block !important;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
|
|
||||||
@media only screen and (min-width: 100px) {
|
// @media only screen and (min-width: 100px) {
|
||||||
.item-icon2,
|
// .item-icon2,
|
||||||
.title-content,
|
// .title-content,
|
||||||
.main-content,
|
// .main-content,
|
||||||
.item {
|
// .item {
|
||||||
font-size: 14px;
|
// font-size: 14px;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@media only screen and (min-width: 500px) {
|
// @media only screen and (min-width: 500px) {
|
||||||
.item-icon2,
|
// .item-icon2,
|
||||||
.title-content,
|
// .title-content,
|
||||||
.main-content,
|
// .main-content,
|
||||||
.item {
|
// .item {
|
||||||
font-size: 16px;
|
// font-size: 16px;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
-22
@@ -23,36 +23,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post-item overflow-y-auto height-100 ">
|
<div class="post-item overflow-y-auto height-100 ">
|
||||||
|
|
||||||
<div style="width: 100%;">
|
<div style="width: 100%;">
|
||||||
<app-swiper
|
<app-swiper
|
||||||
[publicationList]=publication
|
[publicationList]=publication
|
||||||
></app-swiper>
|
></app-swiper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <swiper-container [pagination]="{clickable: true, dynamicBullets: true }">
|
|
||||||
<swiper-slide *ngFor="let files of publication.Files let k = index">
|
|
||||||
<div>
|
|
||||||
<img *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'image'" class="post-img"
|
|
||||||
src="{{'data:image/jpg;base64,' + files.FileBase64}}">
|
|
||||||
|
|
||||||
<video *ngIf="checkFileType.checkFileType(files.FileExtension ) == 'video'" class="post-video" controls="controls" preload="metadata"
|
|
||||||
playsinline webkit-playsinline="webkit-playsinline" (play)="StopvideoService.registerVideoWithEvent($event)" >
|
|
||||||
<source [src]="files.FileBase64" type="video/mp4">
|
|
||||||
</video>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</swiper-slide>
|
|
||||||
</swiper-container> -->
|
|
||||||
<!-- <div *ngIf="publication.FileBase64.length < 30" class="post-img">
|
|
||||||
<img src="/assets/icon/icon-no-image.svg" alt="image">
|
|
||||||
</div> -->
|
|
||||||
<div class="post-description px-20">
|
<div class="post-description px-20">
|
||||||
<pre class="text font-14-rem">{{publication.Message}}</pre>
|
<pre class="text font-14-rem">{{publication.Message}}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="publication.Title == ''" class="d-flex flex-column">
|
<div *ngIf="publication.Title == ''" class="d-flex flex-column">
|
||||||
@@ -76,7 +56,6 @@
|
|||||||
<p><ion-skeleton-text animated></ion-skeleton-text></p>
|
<p><ion-skeleton-text animated></ion-skeleton-text></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
@@ -95,4 +74,3 @@
|
|||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-footer>
|
</ion-footer>
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
|
|||||||
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
|
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
|
||||||
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
|
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
|
||||||
import { Resource } from '@opentelemetry/resources';
|
import { Resource } from '@opentelemetry/resources';
|
||||||
//import { OTLPTraceExporter } from '@opentelemetry/exporter-otlp-http';
|
|
||||||
import { context, trace, propagation } from '@opentelemetry/api';
|
import { context, trace, propagation } from '@opentelemetry/api';
|
||||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
||||||
// const { OTLPTraceExporter: OTLPTraceExporterProto } = require("@opentelemetry/exporter-trace-otlp-proto");
|
|
||||||
|
|
||||||
function createProvider(serviceName) {
|
function createProvider(serviceName) {
|
||||||
const provider = new WebTracerProvider({
|
const provider = new WebTracerProvider({
|
||||||
@@ -31,10 +28,6 @@ function createProvider(serviceName) {
|
|||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter({
|
|
||||||
// url: 'https://ip-2-56-212-253-123420.vps.hosted-by-mvps.net:85/collector/v1/traces',
|
|
||||||
// })));
|
|
||||||
|
|
||||||
provider.register();
|
provider.register();
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,29 +116,29 @@ export class NotificationsService {
|
|||||||
|
|
||||||
if (this.platform.is('mobile')) {
|
if (this.platform.is('mobile')) {
|
||||||
if (!this.isPushNotificationsAvailable) {
|
if (!this.isPushNotificationsAvailable) {
|
||||||
tracing.setAttribute('notification.available', 'false')
|
tracing?.setAttribute('notification.available', 'false')
|
||||||
tracing.setAttribute('outcome', 'failed')
|
tracing?.setAttribute('outcome', 'failed')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.platform.is('ios')) {
|
if (this.platform.is('ios')) {
|
||||||
FCM.getToken()
|
FCM.getToken()
|
||||||
.then(r => {
|
.then(r => {
|
||||||
tracing.setAttribute('notification.token', 'true')
|
tracing?.setAttribute('notification.token', 'true')
|
||||||
this.postToken(r.token, geturl, tracing)
|
this.postToken(r.token, geturl, tracing)
|
||||||
this.token = r.token
|
this.token = r.token
|
||||||
// alert(this.token)
|
// alert(this.token)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
tracing.setAttribute('notification.token', 'false')
|
tracing?.setAttribute('notification.token', 'false')
|
||||||
tracing.setAttribute('outcome', 'failed')
|
tracing?.setAttribute('outcome', 'failed')
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
PushNotifications.addListener('registration',
|
PushNotifications.addListener('registration',
|
||||||
(token: Token) => {
|
(token: Token) => {
|
||||||
|
|
||||||
tracing.setAttribute('notification.token', 'true')
|
tracing?.setAttribute('notification.token', 'true')
|
||||||
this.postToken(token.value, geturl, tracing)
|
this.postToken(token.value, geturl, tracing)
|
||||||
this.token = token.value
|
this.token = token.value
|
||||||
|
|
||||||
@@ -147,19 +147,19 @@ export class NotificationsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tracing.setAttribute('notification.request', 'true')
|
tracing?.setAttribute('notification.request', 'true')
|
||||||
this.afMessaging.requestToken.subscribe(
|
this.afMessaging.requestToken.subscribe(
|
||||||
(token) => {
|
(token) => {
|
||||||
// Save the token to your server for sending notifications
|
// Save the token to your server for sending notifications
|
||||||
console.log('Permission granted! Token:', token);
|
console.log('Permission granted! Token:', token);
|
||||||
this.postToken(token, geturl, tracing)
|
this.postToken(token, geturl, tracing)
|
||||||
this.token = token
|
this.token = token
|
||||||
tracing.setAttribute('notification.token', 'true')
|
tracing?.setAttribute('notification.token', 'true')
|
||||||
tracing.setAttribute('outcome', 'success')
|
tracing?.setAttribute('outcome', 'success')
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|
||||||
tracing.setAttribute('notification.token', 'false')
|
tracing?.setAttribute('notification.token', 'false')
|
||||||
tracing.hasError('Permission denied: request token');
|
tracing.hasError('Permission denied: request token');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -185,14 +185,14 @@ export class NotificationsService {
|
|||||||
Service: 1
|
Service: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing.setAttribute('token.data', token)
|
tracing?.setAttribute('token.data', token)
|
||||||
this.http.post<Tokenn>(`${geturl}`, body, { }).subscribe(data => {
|
this.http.post<Tokenn>(`${geturl}`, body, { }).subscribe(data => {
|
||||||
this.active = true
|
this.active = true
|
||||||
tracing.setAttribute('outcome','success')
|
tracing?.setAttribute('outcome','success')
|
||||||
tracing.finish()
|
tracing.finish()
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
tracing.setAttribute('postToken','failed')
|
tracing?.setAttribute('postToken','failed')
|
||||||
tracing.setAttribute('outcome','failed')
|
tracing?.setAttribute('outcome','failed')
|
||||||
tracing.finish()
|
tracing.finish()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -493,9 +493,9 @@ export class NotificationsService {
|
|||||||
this.zone.run(() => this.router.navigate(['/home/chat'], navigationExtras));
|
this.zone.run(() => this.router.navigate(['/home/chat'], navigationExtras));
|
||||||
}, 200);
|
}, 200);
|
||||||
} else {
|
} else {
|
||||||
tracing.setAttribute('notification.route', 'false')
|
tracing?.setAttribute('notification.route', 'false')
|
||||||
tracing.setAttribute('outcome', 'failed')
|
tracing?.setAttribute('outcome', 'failed')
|
||||||
tracing.setAttribute('parameters', JSON.stringify(notification))
|
tracing?.setAttribute('parameters', JSON.stringify(notification))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
@@ -504,12 +504,12 @@ export class NotificationsService {
|
|||||||
if(!validationError.success) {
|
if(!validationError.success) {
|
||||||
const errors: z.ZodError<any> = (validationError as any).error;
|
const errors: z.ZodError<any> = (validationError as any).error;
|
||||||
console.log("Validation errors:", errors.issues);
|
console.log("Validation errors:", errors.issues);
|
||||||
tracing.setAttribute('validation.errors', JSON.stringify(errors.issues))
|
tracing?.setAttribute('validation.errors', JSON.stringify(errors.issues))
|
||||||
}
|
}
|
||||||
|
|
||||||
tracing.setAttribute('outcome', 'failed')
|
tracing?.setAttribute('outcome', 'failed')
|
||||||
tracing.setAttribute('parameters', JSON.stringify(notification))
|
tracing?.setAttribute('parameters', JSON.stringify(notification))
|
||||||
tracing.setAttribute('error', JSON.stringify(error))
|
tracing?.setAttribute('error', JSON.stringify(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||||
import { UserSession } from '../models/user.model';
|
import { UserSession } from '../models/user.model';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
@@ -10,6 +10,19 @@ import { GetTasksListType } from '../models/GetTasksListType';
|
|||||||
import { fullTaskList } from '../models/dailyworktask.model';
|
import { fullTaskList } from '../models/dailyworktask.model';
|
||||||
import { ChangeProfileService } from './change-profile.service';
|
import { ChangeProfileService } from './change-profile.service';
|
||||||
import { SessionStore } from '../store/session.service';
|
import { SessionStore } from '../store/session.service';
|
||||||
|
import { HttpService } from '../infra/http/http.service';
|
||||||
|
import { Result } from 'neverthrow';
|
||||||
|
import { HttpResult } from '../infra/http/type';
|
||||||
|
|
||||||
|
interface SignatureInputDTO {
|
||||||
|
InstanceId: any;
|
||||||
|
FolderId: any;
|
||||||
|
DraftIds: any;
|
||||||
|
OriginalFileName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
@@ -22,7 +35,8 @@ export class ProcessesService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
private changeProfileService: ChangeProfileService
|
private changeProfileService: ChangeProfileService,
|
||||||
|
private httpService: HttpService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.loggeduser = SessionStore.user;
|
this.loggeduser = SessionStore.user;
|
||||||
@@ -249,6 +263,36 @@ export class ProcessesService {
|
|||||||
return this.http.post<any>(`${geturl}`, body, options)
|
return this.http.post<any>(`${geturl}`, body, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private baseUrl = `${environment.apiURLStage.slice(0, -1)}`;
|
||||||
|
async createSignatureV2(input: SignatureInputDTO) {
|
||||||
|
// Split DraftIds into an array
|
||||||
|
const draftIds: String[] = input.DraftIds?.split(";").filter(Boolean) || [];
|
||||||
|
|
||||||
|
if (draftIds.length === 0) {
|
||||||
|
throw new Error("No valid DraftIds provided");
|
||||||
|
}
|
||||||
|
// Run all requests in parallel
|
||||||
|
const responses: Result<HttpResult<any>, HttpErrorResponse>[] = await Promise.all(
|
||||||
|
draftIds.map(draftId =>
|
||||||
|
this.httpService.put<any>(
|
||||||
|
`${this.baseUrl}/Contents/${draftId}/signature/${SessionStore.user.UserId}`,
|
||||||
|
input
|
||||||
|
) as Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const failures = responses.filter(r => r.isErr() );
|
||||||
|
|
||||||
|
if (failures.length > 0) {
|
||||||
|
// You can either throw or return both successes and failures
|
||||||
|
throw new Error(
|
||||||
|
`Some requests failed draft}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return responses;
|
||||||
|
}
|
||||||
|
|
||||||
CompleteTask(body: Excludetask) {
|
CompleteTask(body: Excludetask) {
|
||||||
|
|
||||||
// double check
|
// double check
|
||||||
|
|||||||
@@ -253,7 +253,9 @@ GetIdsPublicationNext(id:any){
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeletePublication(folderId:any,publicationId:any){
|
DeletePublication(folderId:any,publicationId:any){
|
||||||
const geturl = environment.apiURL + 'presidentialActions/'+folderId+'/posts/'+publicationId;
|
var baseUrl = `${environment.apiURLStage.slice(0, -1)}/PresidentialActions`;
|
||||||
|
|
||||||
|
const geturl = `${baseUrl}/${folderId}/Posts/${publicationId}`;
|
||||||
let params = new HttpParams();
|
let params = new HttpParams();
|
||||||
params = params.set("folderId", folderId);
|
params = params.set("folderId", folderId);
|
||||||
params = params.set("id", publicationId);
|
params = params.set("id", publicationId);
|
||||||
|
|||||||
@@ -1,71 +1,19 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import * as signalR from "@microsoft/signalr"
|
import * as signalR from "@microsoft/signalr"
|
||||||
import { SessionStore } from '../store/session.service';
|
import { SessionStore } from '../store/session.service';
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http';
|
|
||||||
import { CMAPIService } from '../shared/repository/CMAPI/cmapi.service';
|
import { CMAPIService } from '../shared/repository/CMAPI/cmapi.service';
|
||||||
import { HubConnectionBuilder } from '@microsoft/signalr';
|
|
||||||
import { ok, err as Err, Result } from 'neverthrow';
|
import { ok, err as Err, Result } from 'neverthrow';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SocketConnectionMCRService {
|
export class SocketConnectionMCRService {
|
||||||
// private callbacks: Function[] = []
|
|
||||||
// private onDisconnect: Function[] = []
|
|
||||||
// private onConnect: Function[] = []
|
|
||||||
|
|
||||||
constructor(private http: HttpClient, private _CMAPIService: CMAPIService) {
|
constructor(private http: HttpClient, private _CMAPIService: CMAPIService) {
|
||||||
window["http"] = this.http
|
window["http"] = this.http
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect() {
|
|
||||||
|
|
||||||
// var connection = new signalR.HubConnectionBuilder()
|
|
||||||
// .withUrl("https://gdcmapi-dev.dyndns.info/FileHub", {
|
|
||||||
// accessTokenFactory: () => "Bearer "+SessionStore.user.Authorization
|
|
||||||
// }).configureLogging(signalR.LogLevel.Information)
|
|
||||||
// .build();
|
|
||||||
|
|
||||||
// connection.on("ReceiveMessage", (message) => {
|
|
||||||
// console.log("ReceiveMessage", message)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// connection.onreconnected((connectionId) => {
|
|
||||||
// console.assert(connection.state === signalR.HubConnectionState.Connected);
|
|
||||||
// console.log(`Reconnected with connectionId: ${connectionId}`);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// connection.start()
|
|
||||||
// .then(() => {
|
|
||||||
// console.log("SignalR connection started.");
|
|
||||||
// })
|
|
||||||
// .catch((error) => {
|
|
||||||
// console.error("Error starting SignalR connection:", error);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// connection.onclose((error) => {
|
|
||||||
// connection.start()
|
|
||||||
// console.log("SignalR connection closed:", error);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// subscribe(callback) {
|
|
||||||
// this.callbacks.push(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// unsubscribe(callback) {
|
|
||||||
// this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// onDisconnectCallback(callback) {
|
|
||||||
// this.onDisconnect.push(callback)
|
|
||||||
// }
|
|
||||||
// onConnectCallback(callback) {
|
|
||||||
// this.onConnect.push(callback)
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReconnectingWebSocketSignalR {
|
class ReconnectingWebSocketSignalR {
|
||||||
@@ -81,7 +29,6 @@ class ReconnectingWebSocketSignalR {
|
|||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
console.log("try to connect=================================")
|
|
||||||
this.stop = false;
|
this.stop = false;
|
||||||
|
|
||||||
// Limpar a conexão anterior, se existir
|
// Limpar a conexão anterior, se existir
|
||||||
@@ -98,53 +45,53 @@ class ReconnectingWebSocketSignalR {
|
|||||||
.configureLogging(signalR.LogLevel.Information)
|
.configureLogging(signalR.LogLevel.Information)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
this.connection.start()
|
// this.connection.start()
|
||||||
.then(() => {
|
// .then(() => {
|
||||||
this.isOpen = true;
|
// this.isOpen = true;
|
||||||
console.log('WebSocket connection established');
|
// console.log('WebSocket connection established');
|
||||||
this.onConnect.forEach(callback => callback());
|
// this.onConnect.forEach(callback => callback());
|
||||||
this.whenConnected.forEach(callback => callback());
|
// this.whenConnected.forEach(callback => callback());
|
||||||
|
|
||||||
}).catch((error) => {
|
// }).catch((error) => {
|
||||||
|
|
||||||
console.error("Error starting SignalR connection:", error);
|
// console.error("Error starting SignalR connection:", error);
|
||||||
// Adicione tratamento de erros detalhado conforme necessário
|
// // Adicione tratamento de erros detalhado conforme necessário
|
||||||
// Exemplo: Verificar se o erro é devido à perda de conexão com a internet
|
// // Exemplo: Verificar se o erro é devido à perda de conexão com a internet
|
||||||
|
|
||||||
if (error.message.includes("Failed to fetch")) {
|
// if (error.message.includes("Failed to fetch")) {
|
||||||
console.error("Erro de conexão com a internet");
|
// console.error("Erro de conexão com a internet");
|
||||||
}
|
// }
|
||||||
// Tentar reconectar após um atraso
|
// // Tentar reconectar após um atraso
|
||||||
if (!this.stop) {
|
// if (!this.stop) {
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
this.connect();
|
// this.connect();
|
||||||
}, 1000); // Ajuste o atraso conforme necessário
|
// }, 1000); // Ajuste o atraso conforme necessário
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
this.connection.on("ReceiveMessage", (message) => {
|
// this.connection.on("ReceiveMessage", (message) => {
|
||||||
|
|
||||||
const data = JSON.parse(message);
|
// const data = JSON.parse(message);
|
||||||
|
|
||||||
console.log("ReceiveMessage", data);
|
// console.log("ReceiveMessage", data);
|
||||||
|
|
||||||
this.callbacks.forEach(callback => callback(data));
|
// this.callbacks.forEach(callback => callback(data));
|
||||||
|
|
||||||
});
|
// });
|
||||||
|
|
||||||
this.connection.onclose((error) => {
|
// this.connection.onclose((error) => {
|
||||||
console.log('WebSocket connection closed..');
|
// console.log('WebSocket connection closed..');
|
||||||
this.isOpen = false;
|
// this.isOpen = false;
|
||||||
this.onDisconnect.forEach(callback => callback());
|
// this.onDisconnect.forEach(callback => callback());
|
||||||
// Tentar reconectar após um atraso
|
// // Tentar reconectar após um atraso
|
||||||
if (!this.stop && (!error || error.message !== "Connection stopped by client.")) {
|
// if (!this.stop && (!error || error.message !== "Connection stopped by client.")) {
|
||||||
setTimeout(() => {
|
// setTimeout(() => {
|
||||||
this.connect();
|
// this.connect();
|
||||||
}, 3000); // Ajuste o atraso conforme necessário
|
// }, 3000); // Ajuste o atraso conforme necessário
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
commit(path): Promise<Result<true, false>> {
|
commit(path): Promise<Result<true, false>> {
|
||||||
@@ -218,188 +165,6 @@ class ReconnectingWebSocketSignalR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface socketResponse {
|
|
||||||
index: string
|
|
||||||
Guid: string
|
|
||||||
IsCompleted: Boolean
|
|
||||||
}
|
|
||||||
// class ReconnectingWebSocket {
|
|
||||||
|
|
||||||
// private url: string
|
|
||||||
// private socket
|
|
||||||
// isOpen: boolean
|
|
||||||
// private callbacks: Function[] = []
|
|
||||||
// private onDisconnect: Function[] = []
|
|
||||||
// private onConnect: Function[] = []
|
|
||||||
// private whenConnected: Function[] = []
|
|
||||||
// private stop = true
|
|
||||||
// http: HttpClient = window["http"]
|
|
||||||
|
|
||||||
// constructor(url) {
|
|
||||||
// this.url = url;
|
|
||||||
// this.socket = null;
|
|
||||||
// this.isOpen = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// connect() {
|
|
||||||
// this.socket = new WebSocket(this.url);
|
|
||||||
|
|
||||||
// this.socket.addEventListener('open', (event) => {
|
|
||||||
// this.isOpen = true;
|
|
||||||
// console.log('WebSocket connection established');
|
|
||||||
|
|
||||||
// // Example: Send a message to the server
|
|
||||||
// this.socket.send('Hello, WebSocket Server!');
|
|
||||||
// this.onConnect.forEach(callback => callback());
|
|
||||||
// this.whenConnected.forEach(callback => callback())
|
|
||||||
// });
|
|
||||||
|
|
||||||
// this.socket.addEventListener('message', (event) => {
|
|
||||||
// const data: socketResponse = JSON.parse(event.data)
|
|
||||||
// this.callbacks.forEach(callback => callback(data));
|
|
||||||
// });
|
|
||||||
|
|
||||||
// this.socket.addEventListener('close', (event) => {
|
|
||||||
// console.log('WebSocket connection closed');
|
|
||||||
// this.isOpen = false;
|
|
||||||
// this.onDisconnect.forEach(callback => callback());
|
|
||||||
// // Attempt to reconnect after a delay
|
|
||||||
// if(this.stop == false) {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// this.connect();
|
|
||||||
// }, 1000); // Adjust the delay as needed
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// send(message) {
|
|
||||||
// if (this.isOpen) {
|
|
||||||
// this.socket.send(message);
|
|
||||||
// } else {
|
|
||||||
// console.error('WebSocket connection is not open. Unable to send message.');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// disconnect() {
|
|
||||||
// this.stop = true
|
|
||||||
// if (this.isOpen) {
|
|
||||||
// this.isOpen = false;
|
|
||||||
// this.socket.close();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// subscribe(callback) {
|
|
||||||
// this.callbacks.push(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// unsubscribe(callback) {
|
|
||||||
// this.callbacks = this.callbacks.filter(cb => cb !== callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// onDisconnectCallback(callback) {
|
|
||||||
// this.onDisconnect.push(callback)
|
|
||||||
// }
|
|
||||||
// onConnectCallback(callback) {
|
|
||||||
// this.onConnect.push(callback)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// registerWhenConnected(f: Function) {
|
|
||||||
// if(this.isOpen) {
|
|
||||||
// f();
|
|
||||||
// } else {
|
|
||||||
// this.whenConnected.push(f);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export class ObjectMergeNotification{
|
|
||||||
|
|
||||||
// socket = new ReconnectingWebSocket('ws://localhost:3002');
|
|
||||||
// callbacks: {[GUID: string]: Function} = {}
|
|
||||||
// runWatch = true
|
|
||||||
// CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
|
|
||||||
// watchCount = 0
|
|
||||||
|
|
||||||
// constructor() {
|
|
||||||
// this.socket.onDisconnectCallback(()=> {
|
|
||||||
// console.log("run watch")
|
|
||||||
// this.runWatch = true
|
|
||||||
// this.watch()
|
|
||||||
// })
|
|
||||||
|
|
||||||
// this.socket.onConnectCallback(()=> {
|
|
||||||
// console.log("open trigger")
|
|
||||||
// this.runWatch = false
|
|
||||||
// })
|
|
||||||
|
|
||||||
// this.socket.subscribe((data: socketResponse) => {
|
|
||||||
// if(data.IsCompleted == true) {
|
|
||||||
// console.log("==================!!!====================")
|
|
||||||
// try {
|
|
||||||
// this.callbacks[data.Guid](data)
|
|
||||||
// delete this.callbacks[data.Guid]
|
|
||||||
// } catch (error) {}
|
|
||||||
// } else {
|
|
||||||
// console.log("else", data)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
// this.watch()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// connect() {
|
|
||||||
// this.socket.connect()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async watch() {
|
|
||||||
|
|
||||||
// this.watchCount = 0;
|
|
||||||
|
|
||||||
// if(this.runWatch) {
|
|
||||||
// setTimeout(async () => {
|
|
||||||
// for(const [key, funx] of Object.entries(this.callbacks)) {
|
|
||||||
|
|
||||||
// const request = await this.CMAPIService.getVideoHeader(key)
|
|
||||||
|
|
||||||
// if(request.isOk()) {
|
|
||||||
// funx()
|
|
||||||
// delete this.callbacks[key]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.watchCount++
|
|
||||||
// if(this.watchCount <= 15) {
|
|
||||||
// this.watch()
|
|
||||||
// } else {
|
|
||||||
// this.runWatch = false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }, 1000)
|
|
||||||
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
// console.log("end loop============================")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// close() {
|
|
||||||
// this.socket.disconnect();
|
|
||||||
// this.watchCount = 0;
|
|
||||||
// this.runWatch = false
|
|
||||||
// }
|
|
||||||
|
|
||||||
// subscribe(GUID, callback:Function) {
|
|
||||||
// this.callbacks[GUID] = callback;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// unsubscribe(GUID) {
|
|
||||||
// delete this.callbacks[GUID]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
export class ObjectMergeNotification{
|
export class ObjectMergeNotification{
|
||||||
|
|
||||||
socket = new ReconnectingWebSocketSignalR()
|
socket = new ReconnectingWebSocketSignalR()
|
||||||
@@ -457,9 +222,6 @@ export class ObjectMergeNotification{
|
|||||||
|
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.log("end loop============================")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -161,9 +161,9 @@ export class EventDetailsDocumentsOptionsPage implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.processes.presidentialActionsSignature(body).toPromise()
|
await this.processes.createSignatureV2(body);
|
||||||
|
|
||||||
await this.Assinar();
|
//await this.Assinar();
|
||||||
this.TaskService.loadDiplomas();
|
this.TaskService.loadDiplomas();
|
||||||
this.goBackRoute();
|
this.goBackRoute();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { PublicationFolder } from 'src/app/models/publicationfolder';
|
|||||||
import { PublicationsService } from 'src/app/services/publications.service';
|
import { PublicationsService } from 'src/app/services/publications.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||||
|
|
||||||
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
|
import { NgxMatDateFormats } from '@angular-material-components/datetime-picker';
|
||||||
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
|
import { NGX_MAT_DATE_FORMATS } from '@angular-material-components/datetime-picker';
|
||||||
|
import { SessionStore } from 'src/app/store/session.service';
|
||||||
|
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
|
||||||
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
|
const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
|
||||||
parse: {
|
parse: {
|
||||||
dateInput: "YYYY-MMMM-DD HH:mm"
|
dateInput: "YYYY-MMMM-DD HH:mm"
|
||||||
@@ -60,9 +60,8 @@ export class EditActionPage implements OnInit {
|
|||||||
private publicationsService: PublicationsService,
|
private publicationsService: PublicationsService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private httpErrorHandle: HttpErrorHandle,
|
private httpErrorHandle: HttpErrorHandle,
|
||||||
) {
|
private actionRemoteRepository: ActionRemoteRepositoryService
|
||||||
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getPublicationDetail();
|
this.getPublicationDetail();
|
||||||
@@ -73,11 +72,8 @@ export class EditActionPage implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPublicationDetail() {
|
getPublicationDetail() {
|
||||||
|
|
||||||
this.publicationsService.GetPresidentialAction(this.folderId).subscribe( res => {
|
this.publicationsService.GetPresidentialAction(this.folderId).subscribe( res => {
|
||||||
this.folder = res;
|
this.folder = res;
|
||||||
console.log('FOLDER',this.folder)
|
|
||||||
|
|
||||||
|
|
||||||
this.dateControlStart = new FormControl(moment(new Date(this.folder.DateBegin)));
|
this.dateControlStart = new FormControl(moment(new Date(this.folder.DateBegin)));
|
||||||
this.dateControlEnd = new FormControl(moment(new Date(this.folder.DateEnd)));
|
this.dateControlEnd = new FormControl(moment(new Date(this.folder.DateEnd)));
|
||||||
@@ -116,29 +112,27 @@ export class EditActionPage implements OnInit {
|
|||||||
this.injectValidation();
|
this.injectValidation();
|
||||||
this.runValidation();
|
this.runValidation();
|
||||||
|
|
||||||
let body = {
|
|
||||||
ProcessId: this.folderId,
|
|
||||||
Description: this.folder.Description,
|
|
||||||
Detail: this.folder.Detail,
|
|
||||||
DateBegin: this.folder.DateBegin,
|
|
||||||
DateEnd: this.folder.DateEnd,
|
|
||||||
ActionType: this.folder.ActionType,
|
|
||||||
}
|
|
||||||
|
|
||||||
const loader = this.toastService.loading()
|
const loader = this.toastService.loading()
|
||||||
|
|
||||||
try {
|
var result = await this.actionRemoteRepository.update({
|
||||||
await this.publicationsService.UpdatePresidentialAction(body).toPromise()
|
userId: SessionStore.user.UserId,
|
||||||
|
description: this.folder.Description,
|
||||||
|
detail: this.folder.Detail,
|
||||||
|
location: "string",
|
||||||
|
dateBegin: this.folder.DateBegin,
|
||||||
|
dateEnd: this.folder.DateEnd,
|
||||||
|
actionType: "Evento",
|
||||||
|
processId: this.folder.ProcessId as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
if(result.isOk()) {
|
||||||
this.close();
|
this.close();
|
||||||
this.updateDesktopComponent.emit();
|
this.httpErrorHandle.httpsSucessMessagge('Editar Acção');
|
||||||
this.httpErrorHandle.httpsSucessMessagge('Editar Acção')
|
|
||||||
this.getActions.emit()
|
this.getActions.emit()
|
||||||
|
} else {
|
||||||
} catch (error) {
|
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||||
this.httpErrorHandle.httpStatusHandle(error)
|
|
||||||
} finally {
|
|
||||||
loader.remove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loader.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,6 @@
|
|||||||
<ion-label class="title"> Nova Acção</ion-label> <br>
|
<ion-label class="title"> Nova Acção</ion-label> <br>
|
||||||
<i style="margin-top: -3px; font-size: 15px;" > Campos marcados com * são obrigatórios</i>
|
<i style="margin-top: -3px; font-size: 15px;" > Campos marcados com * são obrigatórios</i>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="actionType">
|
|
||||||
<ion-segment [(ngModel)]="segment" (ionChange)="segmentChanged($event)">
|
|
||||||
<ion-segment-button value="Viagem">
|
|
||||||
<ion-label>Viagem</ion-label>
|
|
||||||
</ion-segment-button>
|
|
||||||
<ion-segment-button value="Evento">
|
|
||||||
<ion-label>Evento</ion-label>
|
|
||||||
</ion-segment-button>
|
|
||||||
</ion-segment>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
@@ -31,16 +20,6 @@
|
|||||||
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
|
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="ion-input-class flex-grow-1">
|
<div class="ion-input-class flex-grow-1">
|
||||||
<!-- <ion-datetime
|
|
||||||
class="d-block d-md-none"
|
|
||||||
[(ngModel)]="folder.DateBegin"
|
|
||||||
placeholder="Início"
|
|
||||||
displayFormat="D MMM YYYY H:mm"
|
|
||||||
minuteValues="0,5,10,15,20,25,30,35,40,45,50,55"
|
|
||||||
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
|
|
||||||
max="2025">
|
|
||||||
</ion-datetime> -->
|
|
||||||
|
|
||||||
<mat-form-field appearance="none" class="width-100 date-hour-picker d-md-block">
|
<mat-form-field appearance="none" class="width-100 date-hour-picker d-md-block">
|
||||||
<input matInput [ngxMatDatetimePicker]="picker1"
|
<input matInput [ngxMatDatetimePicker]="picker1"
|
||||||
placeholder="Data inicio*"
|
placeholder="Data inicio*"
|
||||||
@@ -68,15 +47,6 @@
|
|||||||
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
|
<ion-icon slot="start" src="assets/images/icons-calendar.svg"></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="ion-input-class d-flex flex-grow-1">
|
<div class="ion-input-class d-flex flex-grow-1">
|
||||||
<!-- <ion-datetime
|
|
||||||
class="flex-grow-1 d-md-none"
|
|
||||||
[(ngModel)]="folder.DateEnd"
|
|
||||||
placeholder="Fim"
|
|
||||||
displayFormat="D MMM YYYY H:mm"
|
|
||||||
minuteValues="0,5,10,15,20,25,30,35,40,45,50,55"
|
|
||||||
monthShortNames="Jan, Fev, Mar, Abr, Mai, Jun, Jul, Aug, Sep, Out, Nov, Dez"
|
|
||||||
max="2025">
|
|
||||||
</ion-datetime> -->
|
|
||||||
|
|
||||||
<mat-form-field appearance="none" class="width-100 date-hour-picker d-md-block">
|
<mat-form-field appearance="none" class="width-100 date-hour-picker d-md-block">
|
||||||
<input matInput [ngxMatDatetimePicker]="picker2"
|
<input matInput [ngxMatDatetimePicker]="picker2"
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ const CUSTOM_DATE_FORMATS: NgxMatDateFormats = {
|
|||||||
monthYearA11yLabel: "MMMM YYYY"
|
monthYearA11yLabel: "MMMM YYYY"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-new-action',
|
selector: 'app-new-action',
|
||||||
templateUrl: './new-action.page.html',
|
templateUrl: './new-action.page.html',
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<ion-header class="ion-no-border background-white px-20 pt-25">
|
<ion-header class="ion-no-border background-white px-20 pt-25">
|
||||||
<div class="title-content d-flex">
|
<div class="title-content d-flex">
|
||||||
<!-- <div class="back-icon">
|
|
||||||
<ion-icon class="font-35-rem" (click)="goBack()" slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
|
||||||
</div> -->
|
|
||||||
<div class="div-title" >
|
<div class="div-title" >
|
||||||
<ion-label class="title">{{ publicationTitle }}</ion-label> <br>
|
<ion-label class="title">{{ publicationTitle }}</ion-label> <br>
|
||||||
<i style="margin-top: -3px; font-size: 15px;"> Campos marcados com * são obrigatórios</i>
|
<i style="margin-top: -3px; font-size: 15px;"> Campos marcados com * são obrigatórios</i>
|
||||||
@@ -16,7 +13,7 @@
|
|||||||
|
|
||||||
<div *ngIf="publicationType!='1'" class="ion-item-container"
|
<div *ngIf="publicationType!='1'" class="ion-item-container"
|
||||||
[class.input-error]="Form?.get('Subject')?.invalid && validateFrom ">
|
[class.input-error]="Form?.get('Subject')?.invalid && validateFrom ">
|
||||||
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="PublicationFromMvService.form.Title" name="title"
|
<ion-input autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="data.title" name="title"
|
||||||
placeholder="Título*"></ion-input>
|
placeholder="Título*"></ion-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -27,48 +24,47 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ion-textarea-class flex-grow-1"
|
<div class="ion-textarea-class flex-grow-1"
|
||||||
[class.input-error]="Form?.get('Message')?.invalid && validateFrom ">
|
[class.input-error]="Form?.get('Message')?.invalid && validateFrom ">
|
||||||
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="PublicationFromMvService.form.Message"
|
<ion-textarea autocomplete="on" autocorrect="on" spellcheck="true" [(ngModel)]="data.message"
|
||||||
name="description" ngDefaultControl rows="12" cols="20" placeholder="Corpo de texto*"></ion-textarea>
|
name="description" ngDefaultControl rows="12" cols="20" placeholder="Corpo de texto*"></ion-textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="data.files.length > 0">
|
||||||
<!-- <div *ngIf="publication">
|
|
||||||
OriginalFileName: {{ publication.OriginalFileName }}
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Captured -->
|
|
||||||
<div *ngIf="PublicationFromMvService.form.Files.length > 0">
|
|
||||||
<ion-label class="attached-title pb-10">Anexos</ion-label>
|
<ion-label class="attached-title pb-10">Anexos</ion-label>
|
||||||
<div>
|
<div>
|
||||||
<div class="d-flex" >
|
<div class="d-flex" >
|
||||||
|
|
||||||
<div *ngFor="let seleted of PublicationFromMvService.form.Files.slice(0, displayLimit), let i = index" lot="start" class="mr-10">
|
<div *ngFor="let seleted of data.files.slice(0, displayLimit), let i = index" lot="start" class="mr-10">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<div class="text-center cursor-pointer" (click)="deleteFromSeletedContent(i)" style="font-weight: 700;color: #c63527; text-align-last: right;">
|
<div class="text-center cursor-pointer" (click)="deleteFromSeletedContent(i, seleted)" style="font-weight: 700;color: #c63527; text-align-last: right;">
|
||||||
X
|
X
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' && seleted.chucksManager">
|
<div *ngIf="checkFileType.checkFileType(seleted.fileExtension) == 'video' && seleted.chucksManager">
|
||||||
|
|
||||||
<mat-progress-bar
|
|
||||||
|
|
||||||
mode="determinate"
|
|
||||||
[style.width]="seleted.chucksManager.uploadPercentage"
|
|
||||||
></mat-progress-bar>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-img *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'image'"
|
<ion-img
|
||||||
name="image" ngDefaultControl [src]="seleted.url" style="height: 69px; width: 69px;"></ion-img>
|
*ngIf="checkFileType.checkFileType(seleted.fileExtension) == 'image'"
|
||||||
|
name="image"
|
||||||
|
ngDefaultControl
|
||||||
|
[src]="'data:image/' + seleted.fileExtension + ';base64,' + seleted.fileBase64"
|
||||||
|
style="height: 69px; width: 69px;">
|
||||||
|
</ion-img>
|
||||||
|
|
||||||
<video class="sdf" *ngIf="checkFileType.checkFileType(seleted.FileExtension) == 'video' " width="70" height="70"
|
<video class="sdf"
|
||||||
preload="metadata" webkit-playsinline="webkit-playsinline">
|
*ngIf="checkFileType.checkFileType(seleted.fileExtension) == 'video'"
|
||||||
<source type="video/mp4" [src]="seleted.url">
|
width="70" height="70"
|
||||||
|
preload="metadata"
|
||||||
|
webkit-playsinline="webkit-playsinline"
|
||||||
|
controls>
|
||||||
|
<source
|
||||||
|
[src]="getSafeVideoUrl(seleted)"
|
||||||
|
[type]="'video/' + seleted.fileExtension">
|
||||||
|
Your browser does not support the video tag.
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -76,15 +72,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <button class="btn-no-color" (click)="clear()">
|
|
||||||
<ion-icon name="close"></ion-icon>
|
|
||||||
</button> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div *ngIf="checkTableDivice()" style="display: flex;">
|
<div *ngIf="checkTableDivice()" style="display: flex;">
|
||||||
<div (click)="chossePhotoOrVideo()">
|
<div (click)="chossePhotoOrVideo()">
|
||||||
<div class="attach-icon">
|
<div class="attach-icon">
|
||||||
@@ -102,7 +93,7 @@
|
|||||||
|
|
||||||
<div *ngIf="photoOrVideo" class="container-multiselect pt-10" style="width: 200px;">
|
<div *ngIf="photoOrVideo" class="container-multiselect pt-10" style="width: 200px;">
|
||||||
<button id="container-multiselect" class="multiselect-button" (click)="takePicture()">Fotografia</button>
|
<button id="container-multiselect" class="multiselect-button" (click)="takePicture()">Fotografia</button>
|
||||||
<button id="container-multiselect" class="multiselect-button" (click)="startVideoRecording()">Video</button>
|
<!-- <button id="container-multiselect" class="multiselect-button" (click)="startVideoRecording()">Video</button> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { PublicationsService } from 'src/app/services/publications.service';
|
import { PublicationsService } from 'src/app/services/publications.service';
|
||||||
import { Publication } from 'src/app/models/publication';
|
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { ThemeService } from 'src/app/services/theme.service';
|
import { ThemeService } from 'src/app/services/theme.service';
|
||||||
@@ -9,18 +8,17 @@ import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
|||||||
import { PublicationFolderService } from 'src/app/store/publication-folder.service';
|
import { PublicationFolderService } from 'src/app/store/publication-folder.service';
|
||||||
import { FilePicker } from '@capawesome/capacitor-file-picker';
|
import { FilePicker } from '@capawesome/capacitor-file-picker';
|
||||||
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
||||||
import { FileValidatorService } from "src/app/services/file/file-validator.service";
|
|
||||||
import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service";
|
|
||||||
import { LakefsRepositoryService } from '../../repository/lakefs/lakefs-repository.service';
|
|
||||||
|
|
||||||
import { CaptureImageOptions, MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx';
|
import { CaptureImageOptions, MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx';
|
||||||
import { Directory, Filesystem, FilesystemDirectory } from '@capacitor/filesystem';
|
import { Directory, Filesystem, FilesystemDirectory } from '@capacitor/filesystem';
|
||||||
import { ModalController, Platform } from '@ionic/angular';
|
import { ModalController, Platform } from '@ionic/angular';
|
||||||
import { PublicationAttachmentEntity } from '../upload/upload-streaming.service';
|
import { PublicationAttachmentEntity } from '../upload/upload-streaming.service';
|
||||||
import { VideoconvertService } from 'src/app/services/videoconvert.service';
|
import { VideoconvertService } from 'src/app/services/videoconvert.service';
|
||||||
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
|
|
||||||
import { PublicationFromMvService } from "src/app/shared/publication/upload/publication-from-mv.service"
|
import { PublicationFromMvService } from "src/app/shared/publication/upload/publication-from-mv.service"
|
||||||
import { UploadStreamingService } from "src/app/shared/publication/upload/upload-streaming.service"
|
import { UploadStreamingService } from "src/app/shared/publication/upload/upload-streaming.service"
|
||||||
|
import { PublicationCreateUseCaseService } from "src/app/core/actions/use-case/publication-create-use-case.service";
|
||||||
|
import { PublicationUpdateUseCaseService } from 'src/app/core/actions/use-case/publication-update-use-case.service';
|
||||||
|
import { PublicationFilesDeleteByPathUseCaseService } from 'src/app/core/actions/use-case/publication-files-delete-by-path-use-case.service';
|
||||||
|
import { DomSanitizer} from '@angular/platform-browser';
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
newRapid = "1",
|
newRapid = "1",
|
||||||
new = "2",
|
new = "2",
|
||||||
@@ -43,7 +41,7 @@ export class NewPublicationPage implements OnInit {
|
|||||||
Form: FormGroup;
|
Form: FormGroup;
|
||||||
validateFrom = false
|
validateFrom = false
|
||||||
|
|
||||||
@Input() publication!: Publication;
|
@Input() publication!: IPublication;
|
||||||
@Input() publicationType: ActionType;
|
@Input() publicationType: ActionType;
|
||||||
@Input() folderId: string;
|
@Input() folderId: string;
|
||||||
@Input() documentId: string;
|
@Input() documentId: string;
|
||||||
@@ -54,7 +52,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
@Output() goBacktoPublicationDetails = new EventEmitter<any>();
|
@Output() goBacktoPublicationDetails = new EventEmitter<any>();
|
||||||
|
|
||||||
guestPicture: any;
|
guestPicture: any;
|
||||||
|
|
||||||
capturedImage: any = '';
|
capturedImage: any = '';
|
||||||
capturedImageTitle: any = '';
|
capturedImageTitle: any = '';
|
||||||
fileType: string;
|
fileType: string;
|
||||||
@@ -65,6 +62,18 @@ export class NewPublicationPage implements OnInit {
|
|||||||
photoOrVideo: boolean = false;
|
photoOrVideo: boolean = false;
|
||||||
video: any;
|
video: any;
|
||||||
|
|
||||||
|
data: PublicationCreateInputDto & PublicationUpdateInputDto = {
|
||||||
|
userId: SessionStore.user.UserId,
|
||||||
|
dateIndex: new Date().toISOString(),
|
||||||
|
title: "",
|
||||||
|
message: "",
|
||||||
|
datePublication: new Date().toISOString(),
|
||||||
|
files: [],
|
||||||
|
organicEntityId: 101,
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteFiles: IPublicationDocument[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public PublicationFromMvService: PublicationFromMvService,
|
public PublicationFromMvService: PublicationFromMvService,
|
||||||
private publications: PublicationsService,
|
private publications: PublicationsService,
|
||||||
@@ -78,73 +87,63 @@ export class NewPublicationPage implements OnInit {
|
|||||||
private platform: Platform,
|
private platform: Platform,
|
||||||
private videoconvertService: VideoconvertService,
|
private videoconvertService: VideoconvertService,
|
||||||
public UploadStreamingService: UploadStreamingService,
|
public UploadStreamingService: UploadStreamingService,
|
||||||
private modalController: ModalController
|
private modalController: ModalController,
|
||||||
|
private publicationCreateUseCaseService: PublicationCreateUseCaseService,
|
||||||
|
private publicationFileGetByDocumentIdService: PublicationFileGetByDocumentIdService,
|
||||||
|
private local: PublicationFileLocalRepositoryService,
|
||||||
|
private PublicationUpdateUseCaseService: PublicationUpdateUseCaseService,
|
||||||
|
private PublicationFilesDeleteByPathUseCaseService: PublicationFilesDeleteByPathUseCaseService,
|
||||||
|
public sanitizer: DomSanitizer,
|
||||||
) {
|
) {
|
||||||
this.publicationTitle = 'Nova Publicação';
|
this.publicationTitle = 'Nova Publicação';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.PublicationFromMvService.clear()
|
|
||||||
this.setAction();
|
this.setAction();
|
||||||
this.setData()
|
this.data.processId = this.folderId as any;
|
||||||
|
this.processData();
|
||||||
}
|
}
|
||||||
|
|
||||||
setData() {
|
|
||||||
if(this.publication) {
|
|
||||||
this.processData(this.publication)
|
|
||||||
} else {
|
|
||||||
this.getPublicationDetail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getPublicationDetail() {
|
processData() {
|
||||||
if (this.publicationType != ActionType.new) {
|
if (this.publicationType == ActionType.edit) {
|
||||||
this.showLoader = true;
|
|
||||||
this.publications.GetPublicationWithArrayOfFilesById(this.documentId).subscribe(res => {
|
|
||||||
this.processData(res)
|
|
||||||
|
|
||||||
console.log("res get", res)
|
this.data.title = this.publication.title;
|
||||||
this.showLoader = false;
|
this.data.message = this.publication.message;
|
||||||
}, (error) => {
|
this.data.documentId = this.publication.documentId;
|
||||||
console.log(error)
|
this.data.processId = this.publication.processId;
|
||||||
this.showLoader = false;
|
this.data.datePublication = this.publication.datePublication;
|
||||||
this.goBack()
|
this.data.userId = this.publication.userId;
|
||||||
|
this.data.organicEntityId = this.publication.organicEntityId;
|
||||||
|
this.data.dateIndex = this.publication.dateIndex;
|
||||||
|
|
||||||
|
this.local.find({documentId: this.publication.documentId}).then(async e => {
|
||||||
|
if(e.isOk() && e.value.length == 0) {
|
||||||
|
var result = await this.publicationFileGetByDocumentIdService.execute({
|
||||||
|
documentId: this.publication.documentId,
|
||||||
|
processId: this.publication.processId,
|
||||||
|
datePublication: this.publication.datePublication
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processData(res) {
|
if(result.isOk()) {
|
||||||
|
this.data.files = result.value.added.map(file => ({
|
||||||
console.log("res process", res)
|
fileBase64: file.file,
|
||||||
this.PublicationFromMvService.form.Files = []
|
fileExtension: file.extension,
|
||||||
this.PublicationFromMvService.form.setData({
|
originalFileName: "NoUploadNeed",
|
||||||
DateIndex: res.DateIndex,
|
...file
|
||||||
DocumentId: res.DocumentId,
|
}));
|
||||||
ProcessId: res.ProcessId,
|
}
|
||||||
Title: res.Title,
|
} else if(e.isOk()) {
|
||||||
Message: res.Message,
|
console.log(e.value);
|
||||||
DatePublication: res.DatePublication
|
this.data.files = e.value.map(file => ({
|
||||||
|
fileBase64: file.file,
|
||||||
|
fileExtension: file.extension,
|
||||||
|
originalFileName: "NoUploadNeed",
|
||||||
|
...file
|
||||||
|
}));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res.Files && Array.isArray(res?.Files)) {
|
|
||||||
|
|
||||||
const newFiles: PublicationAttachmentEntity[] = res.Files.map(e => {
|
|
||||||
return new PublicationAttachmentEntity(
|
|
||||||
{
|
|
||||||
base64: e.FileBase64,
|
|
||||||
extension: e.FileExtension,
|
|
||||||
OriginalFileName: e.OriginalFileName,
|
|
||||||
FileType: this.checkFileType.checkFileType(e.FileExtension) as any
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
for(const files of newFiles) {
|
|
||||||
this.PublicationFromMvService.form.Files.push(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async takePicture() {
|
async takePicture() {
|
||||||
@@ -159,27 +158,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
this.capturedImageTitle = 'foto';
|
this.capturedImageTitle = 'foto';
|
||||||
|
|
||||||
this.showCroppModal()
|
this.showCroppModal()
|
||||||
/* if(validation.isOk) { */
|
|
||||||
/* const compressedImage = await this.compressImageBase64(
|
|
||||||
this.capturedImage,
|
|
||||||
800, // maxWidth
|
|
||||||
800, // maxHeight
|
|
||||||
0.9 // quality
|
|
||||||
).then((picture) => {
|
|
||||||
this.photoOrVideo = false;
|
|
||||||
|
|
||||||
const FileExtension = this.removeTextBeforeSlash('jpeg', '/')
|
|
||||||
|
|
||||||
const newAttachment = new PublicationAttachmentEntity(
|
|
||||||
{
|
|
||||||
base64: picture,
|
|
||||||
extension: FileExtension,
|
|
||||||
OriginalFileName: "foto",
|
|
||||||
FileType: 'image'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
this.PublicationFromMvService.form.Files.push(newAttachment)
|
|
||||||
}); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async laodPicture() {
|
async laodPicture() {
|
||||||
@@ -211,8 +189,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
FileType: 'image'
|
FileType: 'image'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
//newAttachment.needUpload();
|
|
||||||
|
|
||||||
this.PublicationFromMvService.form.Files.push(newAttachment)
|
this.PublicationFromMvService.form.Files.push(newAttachment)
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -225,8 +201,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
multiple: true,
|
multiple: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(result)
|
|
||||||
|
|
||||||
result.files.forEach(async blobFile => {
|
result.files.forEach(async blobFile => {
|
||||||
console.log(blobFile)
|
console.log(blobFile)
|
||||||
if (this.checkFileType.checkFileType(blobFile.mimeType) == 'image') {
|
if (this.checkFileType.checkFileType(blobFile.mimeType) == 'image') {
|
||||||
@@ -243,29 +217,14 @@ export class NewPublicationPage implements OnInit {
|
|||||||
})
|
})
|
||||||
} else if (this.checkFileType.checkFileType(blobFile.mimeType) == 'video') {
|
} else if (this.checkFileType.checkFileType(blobFile.mimeType) == 'video') {
|
||||||
|
|
||||||
let convertedVideo = await this.videoconvertService.convertVideoWeb(blobFile.blob,"src/assets/videos/","output",'mp4')
|
|
||||||
|
|
||||||
this.convertBlobToBase64(blobFile.blob).then((value: string) => {
|
this.convertBlobToBase64(blobFile.blob).then((value: string) => {
|
||||||
|
|
||||||
this.filesSizeSum = this.filesSizeSum + blobFile.size
|
this.data.files.push({
|
||||||
|
fileBase64: this.removeTextBeforeSlash(value, ','),
|
||||||
|
fileExtension: 'mp4',
|
||||||
|
originalFileName: "image",
|
||||||
|
})
|
||||||
|
|
||||||
const FileExtension = this.removeTextBeforeSlash(blobFile.mimeType, '/')
|
|
||||||
|
|
||||||
const file = new File([blobFile.blob], blobFile.name);
|
|
||||||
|
|
||||||
const newAttachment = new PublicationAttachmentEntity(
|
|
||||||
{
|
|
||||||
base64: this.removeTextBeforeSlash(value, ','),
|
|
||||||
extension: 'mp4',
|
|
||||||
blobFile: file,
|
|
||||||
FileType: this.checkFileType.checkFileType(FileExtension) as any,
|
|
||||||
OriginalFileName: 'load video'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
newAttachment.needUpload()
|
|
||||||
this.PublicationFromMvService.form.Files.push(newAttachment)
|
|
||||||
this.filecontent = true;
|
|
||||||
}).catch((erro) => {
|
}).catch((erro) => {
|
||||||
console.log(erro)
|
console.log(erro)
|
||||||
})
|
})
|
||||||
@@ -277,6 +236,11 @@ export class NewPublicationPage implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSafeVideoUrl(file: { fileExtension: string, fileBase64: string }): SafeResourceUrl {
|
||||||
|
const unsafeUrl = 'data:video/' + file.fileExtension + ';base64,' + file.fileBase64;
|
||||||
|
return this.sanitizer.bypassSecurityTrustResourceUrl(unsafeUrl);
|
||||||
|
}
|
||||||
|
|
||||||
async loadVideoTablet() {
|
async loadVideoTablet() {
|
||||||
|
|
||||||
const result = await FilePicker.pickMedia
|
const result = await FilePicker.pickMedia
|
||||||
@@ -340,11 +304,10 @@ export class NewPublicationPage implements OnInit {
|
|||||||
injectValidation() {
|
injectValidation() {
|
||||||
|
|
||||||
this.Form = new FormGroup({
|
this.Form = new FormGroup({
|
||||||
Subject: new FormControl(this.PublicationFromMvService.form.Title, [
|
Subject: new FormControl(this.data.title, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
// Validators.minLength(4)
|
|
||||||
]),
|
]),
|
||||||
Message: new FormControl(this.PublicationFromMvService.form.Message, [
|
Message: new FormControl(this.data.message, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.maxLength(1000)
|
Validators.maxLength(1000)
|
||||||
])
|
])
|
||||||
@@ -361,12 +324,24 @@ export class NewPublicationPage implements OnInit {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.PublicationFromMvService.setFolderId(this.folderId)
|
this.data.datePublication = new Date().toISOString();
|
||||||
this.PublicationFromMvService.setFolderId(this.folderId)
|
|
||||||
this.goBack();
|
|
||||||
await this.PublicationFromMvService.save()
|
|
||||||
|
|
||||||
// this.PublicationHolderService.setPublication(this.PublicationFromMvService)
|
if (this.publicationType == ActionType.edit) {
|
||||||
|
this.data.files = this.data.files.filter(e => e.originalFileName != 'NoUploadNeed');
|
||||||
|
|
||||||
|
this.PublicationUpdateUseCaseService.execute(this.data).then(async res => {
|
||||||
|
for(var e of this.deleteFiles) {
|
||||||
|
await this.PublicationFilesDeleteByPathUseCaseService.execute(e)
|
||||||
|
}
|
||||||
|
this.PublicationFolderService.loadPublications(this.folderId as any);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.publicationCreateUseCaseService.execute(this.data).then(res => {
|
||||||
|
this.PublicationFolderService.loadPublications(this.folderId as any);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@@ -409,14 +384,7 @@ export class NewPublicationPage implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async goBack() {
|
async goBack() {
|
||||||
|
|
||||||
if (this.publicationType == ActionType.new) {
|
|
||||||
this.goBackToViewPublications.emit();
|
this.goBackToViewPublications.emit();
|
||||||
} else {
|
|
||||||
this.goBackToViewPublications.emit();
|
|
||||||
//this.goBacktoPublicationDetails.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async compressImageBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise<string> {
|
async compressImageBase64(base64String: string, maxWidth: number, maxHeight: number, quality: number): Promise<string> {
|
||||||
@@ -496,19 +464,6 @@ export class NewPublicationPage implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* convertBlobToBase64(blob: Blob) {
|
|
||||||
console.log('Convert blob ',blob)
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const reader = new FileReader;
|
|
||||||
reader.onerror = reject;
|
|
||||||
reader.onload = () => {
|
|
||||||
resolve(reader.result)
|
|
||||||
}
|
|
||||||
reader.readAsDataURL(blob)
|
|
||||||
},)
|
|
||||||
} */
|
|
||||||
|
|
||||||
getBase64(file) {
|
getBase64(file) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
@@ -632,8 +587,13 @@ export class NewPublicationPage implements OnInit {
|
|||||||
return parseInt(sizeInMB)
|
return parseInt(sizeInMB)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteFromSeletedContent(index) {
|
deleteFromSeletedContent(index, file?: IPublicationDocument) {
|
||||||
this.PublicationFromMvService.form.Files.splice(index, 1)
|
this.data.files.splice(index, 1)
|
||||||
|
|
||||||
|
if(this.publicationType == ActionType.edit) {
|
||||||
|
this.deleteFiles.push(file!);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chossePhotoOrVideo() {
|
chossePhotoOrVideo() {
|
||||||
@@ -781,16 +741,13 @@ console.log(stringGerada);
|
|||||||
this.filecontent = true;
|
this.filecontent = true;
|
||||||
this.photoOrVideo = false;
|
this.photoOrVideo = false;
|
||||||
|
|
||||||
const newAttachment = new PublicationAttachmentEntity(
|
// console.log(res.data.base64ToCroppe);
|
||||||
{
|
|
||||||
base64: res.data.base64ToCroppe,
|
|
||||||
extension: 'jpeg',
|
|
||||||
OriginalFileName: "image",
|
|
||||||
FileType: 'image'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
this.PublicationFromMvService.form.Files.push(newAttachment)
|
this.data.files.push({
|
||||||
|
fileBase64: res.data.base64ToCroppe.split(",")[1],
|
||||||
|
fileExtension: 'jpeg',
|
||||||
|
originalFileName: "image",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
@@ -798,14 +755,6 @@ console.log(stringGerada);
|
|||||||
|
|
||||||
await modal.present();
|
await modal.present();
|
||||||
|
|
||||||
// let fileObject = new PublicationAttachmentEntity({
|
|
||||||
// base64: this.removeTextBeforeSlash(this.capturedImage, ',') ,
|
|
||||||
// extension: 'jpeg',
|
|
||||||
// OriginalFileName: 'video',
|
|
||||||
// FileType: 'image'
|
|
||||||
// })
|
|
||||||
// this.PublicationFromMvService.form.Files.push(fileObject)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,6 +763,15 @@ console.log(stringGerada);
|
|||||||
import { Observable, of, Subject } from 'rxjs';
|
import { Observable, of, Subject } from 'rxjs';
|
||||||
import { tap, switchMap, delay, map } from 'rxjs/operators';
|
import { tap, switchMap, delay, map } from 'rxjs/operators';
|
||||||
import { CropImagePage } from 'src/app/modals/crop-image/crop-image.page';
|
import { CropImagePage } from 'src/app/modals/crop-image/crop-image.page';
|
||||||
|
import { PublicationCreateInputDto } from 'src/app/core/actions/use-case/publication-create-use-case.service';
|
||||||
|
import { SessionStore } from 'src/app/store/session.service';
|
||||||
|
import { IPublication } from 'src/app/core/actions/entity/publicationEntity';
|
||||||
|
import { PublicationFileGetByDocumentIdService } from 'src/app/core/actions/use-case/publication-file-get-by-document-id.service';
|
||||||
|
import { PublicationFileLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-file-local-repository.service';
|
||||||
|
import { PublicationUpdateInputDto } from 'src/app/core/actions/use-case/publication-update-use-case.service';
|
||||||
|
import { days } from '../../../models/agenda/AgendaEventList';
|
||||||
|
import { IPublicationDocument } from 'src/app/core/actions/entity/publicationDocument';
|
||||||
|
import { SafeResourceUrl } from '@angular/platform-browser';
|
||||||
|
|
||||||
function shareResponse(): MethodDecorator {
|
function shareResponse(): MethodDecorator {
|
||||||
return function (
|
return function (
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import { ObjectMergeNotification } from 'src/app/services/socket-connection-mcr.
|
|||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { Result } from 'neverthrow';
|
import { Result } from 'neverthrow';
|
||||||
import { IPublicationFormModelEntity } from '../new-publication/interface/interface';
|
import { IPublicationFormModelEntity } from '../new-publication/interface/interface';
|
||||||
import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service"
|
import { ModalController, Platform } from '@ionic/angular';
|
||||||
import { App } from '@capacitor/app';
|
|
||||||
import { ModalController, NavParams, Platform, LoadingController } from '@ionic/angular';
|
|
||||||
import { Router } from '@angular/router';
|
|
||||||
|
|
||||||
enum ActionType {
|
enum ActionType {
|
||||||
newRapid = "1",
|
newRapid = "1",
|
||||||
@@ -33,23 +30,16 @@ export class PublicationFromMvService {
|
|||||||
publicationType: ActionType
|
publicationType: ActionType
|
||||||
folderId: string
|
folderId: string
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private publications: PublicationsService,
|
private publications: PublicationsService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private httpErroHandle: HttpErrorHandle,
|
private httpErroHandle: HttpErrorHandle,
|
||||||
public PublicationFolderService: PublicationFolderService,
|
public PublicationFolderService: PublicationFolderService,
|
||||||
private CMAPIService: CMAPIService,
|
|
||||||
public publicationFolderService: PublicationFolderService,
|
public publicationFolderService: PublicationFolderService,
|
||||||
private platform: Platform,
|
private platform: Platform,
|
||||||
private modalController: ModalController,
|
|
||||||
private router: Router,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
|
|
||||||
this.id = uuidv4()
|
this.id = uuidv4()
|
||||||
this.UploadFileUseCase = new UploadFileUseCase()
|
this.UploadFileUseCase = new UploadFileUseCase()
|
||||||
this.form = new PublicationFormModel()
|
this.form = new PublicationFormModel()
|
||||||
@@ -65,7 +55,6 @@ export class PublicationFromMvService {
|
|||||||
window['upload-header-set-remove'](this.id)
|
window['upload-header-set-remove'](this.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setFolderId(folderId) {
|
setFolderId(folderId) {
|
||||||
this.folderId = folderId
|
this.folderId = folderId
|
||||||
}
|
}
|
||||||
@@ -99,7 +88,6 @@ export class PublicationFromMvService {
|
|||||||
e.FileExtension = e.FileExtension || "mp4"
|
e.FileExtension = e.FileExtension || "mp4"
|
||||||
e.Base64 = ''
|
e.Base64 = ''
|
||||||
|
|
||||||
|
|
||||||
if(e.FileType == 'video' && !e.toUpload) {
|
if(e.FileType == 'video' && !e.toUpload) {
|
||||||
e.Base64 = e.url
|
e.Base64 = e.url
|
||||||
}
|
}
|
||||||
@@ -142,7 +130,6 @@ export class PublicationFromMvService {
|
|||||||
window['publicationEdit']()
|
window['publicationEdit']()
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.publicationFolderService.getPublicationsIds(this.folderId)
|
|
||||||
window['upload-header-set-remove'](this.id);
|
window['upload-header-set-remove'](this.id);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -153,23 +140,16 @@ export class PublicationFromMvService {
|
|||||||
} else {
|
} else {
|
||||||
window['upload-header-set-retry'](this.id)
|
window['upload-header-set-retry'](this.id)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {}
|
||||||
// loader.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let time = new Date()
|
|
||||||
if (this.form.Files.length >= 1) {
|
if (this.form.Files.length >= 1) {
|
||||||
|
|
||||||
// const loader = this.toastService.loading()
|
|
||||||
|
|
||||||
this.form.send = true
|
this.form.send = true
|
||||||
const upload = await this.uploadVideosFiles()
|
const upload = await this.uploadVideosFiles()
|
||||||
|
|
||||||
@@ -180,8 +160,6 @@ export class PublicationFromMvService {
|
|||||||
window['upload-header-set-percentage'](this.id, 100)
|
window['upload-header-set-percentage'](this.id, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('release chunk')
|
|
||||||
|
|
||||||
if(upload) {
|
if(upload) {
|
||||||
this.form.Files = this.form.Files.map((e:PublicationAttachmentEntity) => {
|
this.form.Files = this.form.Files.map((e:PublicationAttachmentEntity) => {
|
||||||
if(e.FileType == 'video' && e.toUpload) {
|
if(e.FileType == 'video' && e.toUpload) {
|
||||||
@@ -194,18 +172,14 @@ export class PublicationFromMvService {
|
|||||||
e.Base64 = e.url
|
e.Base64 = e.url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return e
|
return e
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
window['upload-header-set-retry'](this.id)
|
window['upload-header-set-retry'](this.id)
|
||||||
this.toastService._badRequest("ocorreu um erro ao enviar o ficheiro")
|
this.toastService._badRequest("ocorreu um erro ao enviar o ficheiro")
|
||||||
return true
|
return true
|
||||||
// loader.remove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const publication: any = Object.assign({}, this.form)
|
const publication: any = Object.assign({}, this.form)
|
||||||
|
|
||||||
publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({
|
publication.Files = publication.Files.map( (e:PublicationAttachmentEntity) => ({
|
||||||
@@ -228,27 +202,18 @@ export class PublicationFromMvService {
|
|||||||
|
|
||||||
this.httpErroHandle.httpsSucessMessagge('Criar publicação')
|
this.httpErroHandle.httpsSucessMessagge('Criar publicação')
|
||||||
|
|
||||||
// this.goBackToViewPublications.emit();
|
|
||||||
window['upload-header-set-remove'](this.id);
|
window['upload-header-set-remove'](this.id);
|
||||||
this.doneUpload()
|
this.doneUpload()
|
||||||
this.publicationFolderService.loadPublication(publicationsId, this.folderId)
|
this.publicationFolderService.loadPublication(publicationsId, this.folderId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window['upload-header-set-retry'](this.id)
|
window['upload-header-set-retry'](this.id)
|
||||||
this.httpErroHandle.httpStatusHandle(error)
|
this.httpErroHandle.httpStatusHandle(error)
|
||||||
} finally {
|
|
||||||
// loader.remove()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
this.toastService._badRequest("É necessário adicionar uma imagem ou vídeo")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// this.PublicationHolderService.setPublication(this.publicationFormMV)
|
|
||||||
|
|
||||||
this.ObjectMergeNotification.close()
|
this.ObjectMergeNotification.close()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
<ion-header class="ion-no-border">
|
<ion-header class="ion-no-border">
|
||||||
<div *ngIf="publication.title != ''" class="title-content d-flex pl-20 pt-25">
|
<div *ngIf="publication != null " class="title-content d-flex pl-20 pt-25">
|
||||||
<div class="back-icon cursor-pointer" (click)="goBack()">
|
<div class="back-icon cursor-pointer" (click)="goBack()">
|
||||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " slot="end" src='assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<p class="post-data">{{publication.datePublication | date: 'dd-MM-yyyy | h:mm'}}</p>
|
<p class="post-data">{{publication.datePublication | date: 'dd-MM-yyyy | h:mm'}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="publication.title == ''" class="title-contentd-flex pl-20 pt-25">
|
<div *ngIf="publication != null" class="title-contentd-flex pl-20 pt-25">
|
||||||
<div class="back-icon cursor-pointer">
|
<div class="back-icon cursor-pointer">
|
||||||
<ion-icon (click)="goBack()" slot="end" src='assets/images/assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
<ion-icon (click)="goBack()" slot="end" src='assets/images/assets/images/theme/gov/icons-calendar-arrow-left.svg'></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
<ion-content>
|
<ion-content>
|
||||||
|
|
||||||
<div class="content-container" #ScrollContainer>
|
<div class="content-container" #ScrollContainer>
|
||||||
<div *ngIf="publication.title != ''">
|
<div *ngIf="publication != null">
|
||||||
<div class="post-item px-20">
|
<div class="post-item px-20">
|
||||||
|
|
||||||
<div style="width: 100%; height: 395px;overflow:hidden">
|
<div style="width: 100%; height: 395px;overflow:hidden">
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
|||||||
import { PublicationFolderService } from 'src/app/store/publication-folder.service';
|
import { PublicationFolderService } from 'src/app/store/publication-folder.service';
|
||||||
import { AskModalPage } from 'src/app/modals/ask-modal/ask-modal.page';
|
import { AskModalPage } from 'src/app/modals/ask-modal/ask-modal.page';
|
||||||
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
import { checkFileTypeService } from 'src/app/services/checkFileType.service';
|
||||||
import { PublicationVideoManagerService } from "src/app/services/publication/publication-video-manager.service";
|
|
||||||
import { StopvideoService } from "src/app/services/stopvideo.service";
|
import { StopvideoService } from "src/app/services/stopvideo.service";
|
||||||
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
|
import { PublicationHolderService } from 'src/app/services/publication/publication-holder.service'
|
||||||
import { PublicationListByProcessIdService } from 'src/app/core/actions/use-case/publication-list-by-process-id.service'
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-view-publications',
|
selector: 'app-view-publications',
|
||||||
templateUrl: './view-publications.page.html',
|
templateUrl: './view-publications.page.html',
|
||||||
@@ -71,10 +69,8 @@ export class ViewPublicationsPage implements OnInit {
|
|||||||
private httpErrorHandle: HttpErrorHandle,
|
private httpErrorHandle: HttpErrorHandle,
|
||||||
public publicationFolderService: PublicationFolderService,
|
public publicationFolderService: PublicationFolderService,
|
||||||
public checkFileType: checkFileTypeService,
|
public checkFileType: checkFileTypeService,
|
||||||
private publicationVideoManagerService: PublicationVideoManagerService,
|
|
||||||
public StopvideoService: StopvideoService,
|
public StopvideoService: StopvideoService,
|
||||||
public PublicationHolderService: PublicationHolderService,
|
public PublicationHolderService: PublicationHolderService
|
||||||
private publicationListByProcessIdService: PublicationListByProcessIdService
|
|
||||||
) {
|
) {
|
||||||
this.createPublicationList()
|
this.createPublicationList()
|
||||||
}
|
}
|
||||||
@@ -116,11 +112,6 @@ export class ViewPublicationsPage implements OnInit {
|
|||||||
this.getPublicationDetail();
|
this.getPublicationDetail();
|
||||||
this.getPublicationsIds();
|
this.getPublicationsIds();
|
||||||
this.stopVideo();
|
this.stopVideo();
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.doRefresh({})
|
|
||||||
}, 1500);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +127,7 @@ export class ViewPublicationsPage implements OnInit {
|
|||||||
|
|
||||||
doRefresh = (event) => {
|
doRefresh = (event) => {
|
||||||
|
|
||||||
|
this.publicationFolderService.loadPublications(this.folderId);
|
||||||
this.getPublicationDetail();
|
this.getPublicationDetail();
|
||||||
this.getPublicationsIds();
|
this.getPublicationsIds();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,20 @@
|
|||||||
[src]="'data:image/jpg;base64,' + files.file" loading="lazy">
|
[src]="'data:image/jpg;base64,' + files.file" loading="lazy">
|
||||||
|
|
||||||
|
|
||||||
<video #videoElements [appVisibility]="onVisibilityChange" *ngIf="checkFileType.checkFileType(files.extension ) == 'video'" class="post-video" controls="controls" preload="none"
|
<video
|
||||||
playsinline webkit-playsinline="webkit-playsinline" (play)="stopvideoService.registerVideoWithEvent($event)"q>
|
#videoElements
|
||||||
|
[appVisibility]="onVisibilityChange"
|
||||||
|
*ngIf="checkFileType.checkFileType(files.extension) == 'video'"
|
||||||
|
class="post-video"
|
||||||
|
controls
|
||||||
|
preload="metadata"
|
||||||
|
playsinline
|
||||||
|
webkit-playsinline
|
||||||
|
(loadeddata)="videoElements.currentTime = 0.1"
|
||||||
|
(play)="stopvideoService.registerVideoWithEvent($event)"
|
||||||
|
>
|
||||||
<source
|
<source
|
||||||
*ngIf="files.extension === 'MP4'"
|
*ngIf="files.extension === 'mp4'"
|
||||||
[src]="'data:video/mp4;base64,' + files.file"
|
[src]="'data:video/mp4;base64,' + files.file"
|
||||||
type="video/mp4"
|
type="video/mp4"
|
||||||
>
|
>
|
||||||
@@ -21,18 +31,9 @@
|
|||||||
>
|
>
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</swiper-slide>
|
</swiper-slide>
|
||||||
</swiper-container>
|
</swiper-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-footer>
|
|
||||||
<div *ngIf="pagination && publicationList?.length > 1" class="dots-container">
|
|
||||||
<span *ngFor="let files of publicationList; let k = index"
|
|
||||||
[class.dotsSwiper]="true"
|
|
||||||
[class.active-dot]="swiperIndex === k"
|
|
||||||
(click)="goToSlide(k)"
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</ion-footer>
|
|
||||||
|
|||||||
@@ -64,8 +64,21 @@ export class SwiperPage implements OnInit {
|
|||||||
}
|
}
|
||||||
} else if(e.isOk()) {
|
} else if(e.isOk()) {
|
||||||
this.publicationList = e.value;
|
this.publicationList = e.value;
|
||||||
|
|
||||||
|
var a = e.value.find(e => e.datePublication != this.datePublication)
|
||||||
|
if(a) {
|
||||||
|
var result = await this.publicationFileGetByDocumentIdService.execute({
|
||||||
|
documentId: this.documentId,
|
||||||
|
processId: this.processId,
|
||||||
|
datePublication: this.datePublication
|
||||||
|
});
|
||||||
|
|
||||||
|
if(result.isOk()) {
|
||||||
|
this.publicationList = result.value.added;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
|
|||||||
@@ -41,41 +41,49 @@ export class PublicationFolderService {
|
|||||||
|
|
||||||
async loadPublications(processId: number) {
|
async loadPublications(processId: number) {
|
||||||
|
|
||||||
|
var id = processId+0
|
||||||
|
|
||||||
this.showLoader = true;
|
this.showLoader = true;
|
||||||
|
|
||||||
if (!this.publications[processId]) {
|
if (!this.publications[id]) {
|
||||||
this.publications[processId] = []
|
this.publications[id] = []
|
||||||
|
|
||||||
const result = await this.publicationLocalRepo.find({processId});
|
const result = await this.publicationLocalRepo.find({processId: id});
|
||||||
|
|
||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
this.publications[processId] = result.value;
|
this.publications[id] = result.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.publicationListByProcessIdService.execute(processId);
|
const result = await this.publicationListByProcessIdService.execute(id);
|
||||||
|
|
||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
for(const item of result.value.added) {
|
for(const item of result.value.added) {
|
||||||
this.publications[processId].push(item);
|
this.publications[id].push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle removed
|
// handle removed
|
||||||
for (const item of result.value.remove) {
|
for (const item of result.value.remove) {
|
||||||
this.publications[processId] = this.publications[processId].filter(f => f.documentId !== item.documentId);
|
this.publications[id] = this.publications[id].filter(f => f.documentId !== item.documentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle updated
|
// handle updated
|
||||||
for (const item of result.value.updated) {
|
for (const item of result.value.updated) {
|
||||||
const index = this.publications[processId].findIndex(f => f.documentId === item.documentId);
|
const index = this.publications[id].findIndex(f => f.documentId === item.documentId);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.publications[processId][index] = item; // replace with updated version
|
this.publications[id][index] = item; // replace with updated version
|
||||||
} else {
|
} else {
|
||||||
this.publications[processId].push(item); // if not found, just add it
|
this.publications[id].push(item); // if not found, just add it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.publications[id] = this.publications[id].sort((a, b) => {
|
||||||
|
const dateA = new Date(a.datePublication).getTime();
|
||||||
|
const dateB = new Date(b.datePublication).getTime();
|
||||||
|
return dateB - dateA; // Revertendo a ordem aqui
|
||||||
|
});
|
||||||
|
|
||||||
this.showLoader = false;
|
this.showLoader = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ import { isHttpError } from 'src/app/services/http.service';
|
|||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
import { NotificationRepositoryService } from 'src/app/module/notification/data/notification-repository.service';
|
import { NotificationRepositoryService } from 'src/app/module/notification/data/notification-repository.service';
|
||||||
import { EEventFilterStatus } from 'src/app/module/agenda/data/dto/enums';
|
import { EEventFilterStatus } from 'src/app/module/agenda/data/dto/enums';
|
||||||
// import { Unsubscribable } from '../../../../android/app/build/intermediates/assets/debug/public/assets/dexie/dist/dexie';
|
import { ProcessesService } from 'src/app/services/processes.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-agenda',
|
selector: 'app-agenda',
|
||||||
templateUrl: './agenda.page.html',
|
templateUrl: './agenda.page.html',
|
||||||
@@ -204,7 +203,7 @@ export class AgendaPage implements OnInit {
|
|||||||
public RoleIdService: RoleIdService,
|
public RoleIdService: RoleIdService,
|
||||||
public AgendaDataRepositoryService: AgendaDataRepositoryService,
|
public AgendaDataRepositoryService: AgendaDataRepositoryService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private notificationRepository: NotificationRepositoryService
|
private notificationRepository: NotificationRepositoryService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.NotificationUpdate.pipe(
|
this.NotificationUpdate.pipe(
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
<!-- {{ expirationDate[room.$id] !== null ? expirationDate[room.$id] + ' seconds left' : 'No expiration' }} -->
|
<!-- {{ expirationDate[room.$id] !== null ? expirationDate[room.$id] + ' seconds left' : 'No expiration' }} -->
|
||||||
<span *ngIf="expirationDate[room.$id]"> {{ expirationDate[room.$id] !== null ? expirationDate[room.$id] + ' seconds left' : '' }} </span>
|
<span *ngIf="expirationDate[room.$id]"> {{ expirationDate[room.$id] !== null ? expirationDate[room.$id] + ' seconds left' : '' }} </span>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted!=true" class="item-description d-flex align-items-center" [class.item-description-active]="room.$id ==selectedRoomId">
|
<div *ngIf="room?.messages?.length >= 1 && room.messages[0]._isDeleted!=true" class="item-description d-flex align-items-center" [class.item-description-active]="room.$id ==selectedRoomId">
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- <div *ngIf="room?.messages?.[0]?.message" class="item-description d-flex align-items-center" [class.item-description-active]="room.$id ==selectedRoomId"> -->
|
<!-- <div *ngIf="room?.messages?.[0]?.message" class="item-description d-flex align-items-center" [class.item-description-active]="room.$id ==selectedRoomId"> -->
|
||||||
<!-- <div class="item-message" *ngIf="group.otherUserType == false">{{room?.messages?.[0]?.message.u.name}}: {{room?.messages?.[0]?.message.msg}} </div> -->
|
<!-- <div class="item-message" *ngIf="group.otherUserType == false">{{room?.messages?.[0]?.message.u.name}}: {{room?.messages?.[0]?.message.msg}} </div> -->
|
||||||
@@ -94,7 +94,6 @@
|
|||||||
<!-- <div *ngIf="group.otherUserType == true">{{group.userThatIsTyping}} está escrever ...</div> -->
|
<!-- <div *ngIf="group.otherUserType == true">{{group.userThatIsTyping}} está escrever ...</div> -->
|
||||||
|
|
||||||
<div class="item-files add-ellipsis" *ngIf="room.messages[0]?.attachments?.length >= 1">
|
<div class="item-files add-ellipsis" *ngIf="room.messages[0]?.attachments?.length >= 1">
|
||||||
|
|
||||||
<fa-icon *ngIf="room.lastMessageDocument" icon="file-alt" class="file-icon" [class.set-active-item-font-to-white]="room.$id == selectedRoomId"></fa-icon>
|
<fa-icon *ngIf="room.lastMessageDocument" icon="file-alt" class="file-icon" [class.set-active-item-font-to-white]="room.$id == selectedRoomId"></fa-icon>
|
||||||
<fa-icon *ngIf="room.lastMessageAudio" icon="file-audio" class="file-icon" [class.set-active-item-font-to-white]="room.$id == selectedRoomId"></fa-icon>
|
<fa-icon *ngIf="room.lastMessageAudio" icon="file-audio" class="file-icon" [class.set-active-item-font-to-white]="room.$id == selectedRoomId"></fa-icon>
|
||||||
<span *ngIf="room.lastMessageAudio" class="item-files-title font-13-em"> audio </span>
|
<span *ngIf="room.lastMessageAudio" class="item-files-title font-13-em"> audio </span>
|
||||||
@@ -103,20 +102,14 @@
|
|||||||
<span class="pl-2 font-13-em add-ellipsis" *ngIf="!room.lastMessageAudio && !room.lastMessageImage">{{ room.messages[0].attachments[0].description }}</span>
|
<span class="pl-2 font-13-em add-ellipsis" *ngIf="!room.lastMessageAudio && !room.lastMessageImage">{{ room.messages[0].attachments[0].description }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="item-files" *ngIf="room.attachments">
|
|
||||||
<div *ngIf="room.value.lastMessage.attachments[0].image_url">
|
|
||||||
<fa-icon icon="image" class="file-icon" [class.set-active-item-font-to-white]="room.$id == selectedRoomId"></fa-icon>
|
|
||||||
<span> Fotografia</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
<div *ngIf="room?.messages?.length >= 1 && room.messages[0]._isDeleted==true && room.messages[0].oneShot == false">
|
||||||
</div>
|
|
||||||
<div *ngIf="room?.messages?.length >= 1 && room.messages[0].isDeleted==true">
|
|
||||||
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> Mensagem foi eliminada </div>
|
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> Mensagem foi eliminada </div>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<div *ngIf="room?.messages?.length >= 1 && room.messages[0]._isDeleted==true && room.messages[0].oneShot == true">
|
||||||
|
<div class="item-message font-13-em add-ellipsis white-space-nowrap"> Mensagem de visualizada </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <div class="item-message font-13-em add-ellipsis white-space-nowrap" *ngIf="room.otherUserType == false"> {{room.messages[0].message}} </div> -->
|
|
||||||
<!-- <div class="font-13-em" *ngIf="room.otherUserType == true">está escrever ...</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { MessageLocalDataSourceService } from 'src/app/module/chat/data/reposito
|
|||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
import { Logger } from 'src/app/services/logger/main/service';
|
import { Logger } from 'src/app/services/logger/main/service';
|
||||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||||
|
import { MessageViewModal } from './store/model/message';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-chat',
|
selector: 'app-chat',
|
||||||
templateUrl: './chat.page.html',
|
templateUrl: './chat.page.html',
|
||||||
@@ -156,7 +157,12 @@ export class ChatPage implements OnInit {
|
|||||||
// ]);
|
// ]);
|
||||||
|
|
||||||
this.roomLocalDataSourceService.getItemsLive().pipe(
|
this.roomLocalDataSourceService.getItemsLive().pipe(
|
||||||
map((roomList) => roomList.map((room)=> new RoomViewModel(room))),
|
map((roomList) => roomList.map((room)=> {
|
||||||
|
room.messages = room.messages.map( e => {
|
||||||
|
return new MessageViewModal(e);
|
||||||
|
});
|
||||||
|
return new RoomViewModel(room);
|
||||||
|
})),
|
||||||
tap((roomList) => {
|
tap((roomList) => {
|
||||||
this.updatemessage(roomList)
|
this.updatemessage(roomList)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { ZodError } from 'zod';
|
|||||||
|
|
||||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||||
|
import { GetRoomListUseCaseService } from 'src/app/core/chat/usecase/room/room-get-list-use-case.service';
|
||||||
|
import { GetRoomByIdUseCaseService } from 'src/app/core/chat/usecase/room/room-get-by-id-use-case.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -39,6 +41,8 @@ export class EditGroupPage implements OnInit {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private chatServiceService: ChatServiceService,
|
private chatServiceService: ChatServiceService,
|
||||||
private RoomLocalDataSourceService: IRoomLocalRepository,
|
private RoomLocalDataSourceService: IRoomLocalRepository,
|
||||||
|
private GetRoomListUseCaseService: GetRoomListUseCaseService,
|
||||||
|
private getRoomByIdUseCaseService: GetRoomByIdUseCaseService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -75,6 +79,9 @@ export class EditGroupPage implements OnInit {
|
|||||||
roomType: 0
|
roomType: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.GetRoomListUseCaseService.execute();
|
||||||
|
//this.getRoomByIdUseCaseService.execute(this.roomId);
|
||||||
|
|
||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
this.openGroupMessage.emit(this.roomId);
|
this.openGroupMessage.emit(this.roomId);
|
||||||
} else if (result.error instanceof HttpResponse) {
|
} else if (result.error instanceof HttpResponse) {
|
||||||
@@ -84,7 +91,6 @@ export class EditGroupPage implements OnInit {
|
|||||||
console.log(result.error.errors)
|
console.log(result.error.errors)
|
||||||
} else {
|
} else {
|
||||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||||
console.log(result.error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showLoader = false
|
this.showLoader = false
|
||||||
|
|||||||
@@ -152,16 +152,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="message-container rotate-div" *ngIf="message.isDeleted == true">
|
<div class="message-container rotate-div" *ngIf="message._isDeleted == true && message.id != '' && message.oneShot == false">
|
||||||
Mensagem foi eliminada
|
Mensagem foi eliminada
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="message-container rotate-div" *ngIf="message._isDeleted == true && message.id != '' && message.oneShot == true">
|
||||||
|
Mensagem de visualizada
|
||||||
|
</div>
|
||||||
|
|
||||||
<div *ngIf="message.messageType == IMessageType.information && !message.ballon" class="text-center">
|
<div *ngIf="message.messageType == IMessageType.information && !message.ballon" class="text-center">
|
||||||
{{ message.message }}
|
{{ message.message }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="message.ballon" class="text-center ballon">
|
<div *ngIf="message.ballon" class="text-center ballon">
|
||||||
{{ message.message }}
|
{{ message.message }}
|
||||||
</div>
|
</div>
|
||||||
<div class="rotate-div emoji-container" *ngIf="message.isDeleted != true && message.messageType != IMessageType.information && message.ballon != true">
|
<div class="rotate-div emoji-container" *ngIf="message._isDeleted != true && message.messageType != IMessageType.information && message.ballon != true">
|
||||||
<span *ngFor="let reaction of message.reactions" class="emoji-icon">
|
<span *ngFor="let reaction of message.reactions" class="emoji-icon">
|
||||||
{{ reaction.reaction }}
|
{{ reaction.reaction }}
|
||||||
</span>
|
</span>
|
||||||
@@ -232,7 +237,7 @@
|
|||||||
|
|
||||||
<div class="width-100">
|
<div class="width-100">
|
||||||
<div *ngIf="!recording && !lastAudioRecorded" class="type-message">
|
<div *ngIf="!recording && !lastAudioRecorded" class="type-message">
|
||||||
<ion-textarea *ngIf="allowTyping" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="textField" (ionChange)="sendTyping()" (click)="sendReadAt()"></ion-textarea>
|
<ion-textarea *ngIf="allowTyping" (keyup.enter)="sendMessage()" clearOnEdit="true" placeholder="Escrever uma mensagem" class="message-input" rows="1" [(ngModel)]="textField" (ionChange)="sendTyping()"></ion-textarea>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="recording" class="d-flex align-items-center justify-content-center">
|
<div *ngIf="recording" class="d-flex align-items-center justify-content-center">
|
||||||
<button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center">
|
<button (click)="stopRecording()" class="btn-no-color d-flex align-items-center justify-content-center">
|
||||||
|
|||||||
@@ -194,9 +194,11 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
|||||||
this.roomData$ = this.RoomLocalRepository.getRoomByIdLive(this.room.$id)
|
this.roomData$ = this.RoomLocalRepository.getRoomByIdLive(this.room.$id)
|
||||||
|
|
||||||
this.roomData$.subscribe(e => {
|
this.roomData$.subscribe(e => {
|
||||||
if(e) {
|
if(e && this.room.$id == e?.$id) {
|
||||||
this.room = new RoomViewModel(e)
|
this.room = new RoomViewModel(e)
|
||||||
this.roomType = e.roomType;
|
this.roomType = e.roomType;
|
||||||
|
} else {
|
||||||
|
console.log(e);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -433,6 +435,12 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
|||||||
modal.present()
|
modal.present()
|
||||||
|
|
||||||
return modal.onDidDismiss().then((res) => {
|
return modal.onDidDismiss().then((res) => {
|
||||||
|
this.chatServiceService.sendReadAt({
|
||||||
|
memberId: SessionStore.user.UserId,
|
||||||
|
messageId: message.id,
|
||||||
|
requestId: '',
|
||||||
|
roomId: this.room.id
|
||||||
|
})
|
||||||
this.messageDelete(message)
|
this.messageDelete(message)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -446,21 +454,19 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
|||||||
const me = message.haveSeen(message.info)
|
const me = message.haveSeen(message.info)
|
||||||
|
|
||||||
if(!me) {
|
if(!me) {
|
||||||
// Logger.info('send read at, sender '+ message.sender.wxFullName+ ' '+ message.message +'message id'+ message.id)
|
|
||||||
|
|
||||||
|
if(message.oneShot == false) {
|
||||||
this.chatServiceService.sendReadAt({
|
this.chatServiceService.sendReadAt({
|
||||||
memberId: SessionStore.user.UserId,
|
memberId: SessionStore.user.UserId,
|
||||||
messageId: message.id,
|
messageId: message.id,
|
||||||
requestId: uuidv4(),
|
requestId: uuidv4(),
|
||||||
roomId: this.room.id
|
roomId: this.room.id
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
// console.log('no need', message )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.log('dont read for this room')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,12 +501,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(message.oneShot == false) {
|
||||||
this.chatServiceService.sendReadAt({
|
this.chatServiceService.sendReadAt({
|
||||||
memberId: SessionStore.user.UserId,
|
memberId: SessionStore.user.UserId,
|
||||||
messageId: message.id,
|
messageId: message.id,
|
||||||
requestId: '',
|
requestId: '',
|
||||||
roomId: this.room.id
|
roomId: this.room.id
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToBottomClicked()
|
this.scrollToBottomClicked()
|
||||||
@@ -612,12 +620,6 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sendReadAt() {
|
|
||||||
// this.chatServiceService.messageMarkAsRead({roomId: this.room.$id}).then((e) => {
|
|
||||||
// console.log(e)
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
sendTyping() {
|
sendTyping() {
|
||||||
if(this.room.local == IDBoolean.false) {
|
if(this.room.local == IDBoolean.false) {
|
||||||
this.UserTypingRemoteRepositoryService.sendTyping(this.room.id)
|
this.UserTypingRemoteRepositoryService.sendTyping(this.room.id)
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
|||||||
import { ThemeService } from 'src/app/services/theme.service'
|
import { ThemeService } from 'src/app/services/theme.service'
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
import { ZodError } from 'zod';
|
import { ZodError } from 'zod';
|
||||||
|
import { GetRoomListUseCaseService } from 'src/app/core/chat/usecase/room/room-get-list-use-case.service';
|
||||||
|
import { GetRoomByIdUseCaseService } from 'src/app/core/chat/usecase/room/room-get-by-id-use-case.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-edit-group',
|
selector: 'app-edit-group',
|
||||||
@@ -31,6 +34,8 @@ export class EditGroupPage implements OnInit {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private chatServiceService: ChatServiceService,
|
private chatServiceService: ChatServiceService,
|
||||||
private RoomLocalDataSourceService: IRoomLocalRepository,
|
private RoomLocalDataSourceService: IRoomLocalRepository,
|
||||||
|
private GetRoomListUseCaseService: GetRoomListUseCaseService,
|
||||||
|
private getRoomByIdUseCaseService: GetRoomByIdUseCaseService
|
||||||
) {
|
) {
|
||||||
this.roomId = this.navParams.get('roomId');
|
this.roomId = this.navParams.get('roomId');
|
||||||
}
|
}
|
||||||
@@ -67,6 +72,10 @@ export class EditGroupPage implements OnInit {
|
|||||||
roomType: 0
|
roomType: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
this.GetRoomListUseCaseService.execute();
|
||||||
|
//this.getRoomByIdUseCaseService.execute(this.roomId);
|
||||||
|
|
||||||
if(result.isOk()) {
|
if(result.isOk()) {
|
||||||
this.modalController.dismiss();
|
this.modalController.dismiss();
|
||||||
} else if (result.error instanceof HttpResponse) {
|
} else if (result.error instanceof HttpResponse) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import { RoomStore } from '../../store/roomStore'
|
|||||||
import { EditGroupPage } from '../edit-group/edit-group.page';
|
import { EditGroupPage } from '../edit-group/edit-group.page';
|
||||||
import { imageMimeTypes } from 'src/app/utils/allowedImageExtension';
|
import { imageMimeTypes } from 'src/app/utils/allowedImageExtension';
|
||||||
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-contacts/group-contacts.page';
|
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-contacts/group-contacts.page';
|
||||||
|
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-messages',
|
selector: 'app-messages',
|
||||||
@@ -121,6 +122,7 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
private file: File,
|
private file: File,
|
||||||
private fileSystemMobileService: FileSystemMobileService,
|
private fileSystemMobileService: FileSystemMobileService,
|
||||||
public RoomStore: RoomStore,
|
public RoomStore: RoomStore,
|
||||||
|
private chatServiceService: ChatServiceService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
this.room = this.navParams.get('room');
|
this.room = this.navParams.get('room');
|
||||||
@@ -750,6 +752,12 @@ export class MessagesPage implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
modal.present()
|
modal.present()
|
||||||
|
|
||||||
return modal.onDidDismiss().then((res) => {
|
return modal.onDidDismiss().then((res) => {
|
||||||
|
this.chatServiceService.sendReadAt({
|
||||||
|
memberId: SessionStore.user.UserId,
|
||||||
|
messageId: message.id,
|
||||||
|
requestId: '',
|
||||||
|
roomId: this.room.id
|
||||||
|
})
|
||||||
this.messageDelete(message)
|
this.messageDelete(message)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ export class MessageViewModal {
|
|||||||
}
|
}
|
||||||
this.setMessageUIType()
|
this.setMessageUIType()
|
||||||
|
|
||||||
if(this.isDeleted != true && this.messageType != IMessageType.information) {
|
if(this._isDeleted == false && this.messageType != IMessageType.information) {
|
||||||
this.showReaction = true
|
this.showReaction = true
|
||||||
}
|
}
|
||||||
if(this.isDeleted == false && this.messageType == IMessageType.normal) {
|
if(this._isDeleted == false && this.messageType == IMessageType.normal) {
|
||||||
this.showMessage = true
|
this.showMessage = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,4 +118,8 @@ export class MessageViewModal {
|
|||||||
meSender() {
|
meSender() {
|
||||||
return this.sender.wxUserId == SessionStore.user.UserId
|
return this.sender.wxUserId == SessionStore.user.UserId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _isDeleted() {
|
||||||
|
return this.isDeleted || this.info.filter(e =>e.memberId == SessionStore.user.UserId && e.isDeleted).length == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { IRoom, RoomEntitySchema } from "src/app/core/chat/entity/group";
|
import { IRoom, RoomEntitySchema } from "src/app/core/chat/entity/group";
|
||||||
import { MessageAttachmentSource } from "src/app/core/chat/entity/message";
|
import { MessageAttachmentSource } from "src/app/core/chat/entity/message";
|
||||||
import { isDocument } from "src/app/utils/document-mimetype";
|
import { isDocument } from "src/app/utils/document-mimetype";
|
||||||
|
import { MessageViewModal } from "./message";
|
||||||
|
|
||||||
export class RoomViewModel implements IRoom {
|
export class RoomViewModel implements IRoom {
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ export class RoomViewModel implements IRoom {
|
|||||||
expirationDate: typeof RoomEntitySchema._input.expirationDate
|
expirationDate: typeof RoomEntitySchema._input.expirationDate
|
||||||
roomType: typeof RoomEntitySchema._input.roomType
|
roomType: typeof RoomEntitySchema._input.roomType
|
||||||
members: typeof RoomEntitySchema._input.members
|
members: typeof RoomEntitySchema._input.members
|
||||||
messages: typeof RoomEntitySchema._input.messages
|
messages: MessageViewModal[]
|
||||||
local: typeof RoomEntitySchema._input.local
|
local: typeof RoomEntitySchema._input.local
|
||||||
receiverId?: typeof RoomEntitySchema._input.receiverId
|
receiverId?: typeof RoomEntitySchema._input.receiverId
|
||||||
displayDate = ''
|
displayDate = ''
|
||||||
|
|||||||
@@ -224,12 +224,15 @@ export class RoomStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(message.oneShot == false) {
|
||||||
this.chatServiceService.sendReadAt({
|
this.chatServiceService.sendReadAt({
|
||||||
memberId: SessionStore.user.UserId,
|
memberId: SessionStore.user.UserId,
|
||||||
messageId: message.id,
|
messageId: message.id,
|
||||||
requestId: uuidv4(),
|
requestId: uuidv4(),
|
||||||
roomId: this.room.id
|
roomId: this.room.id
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToBottomClicked()
|
this.scrollToBottomClicked()
|
||||||
@@ -348,12 +351,15 @@ export class RoomStore {
|
|||||||
if(!me) {
|
if(!me) {
|
||||||
// Logger.info('send read at, sender '+ message.sender.wxFullName+ ' '+ message.message +'message id'+ message.id)
|
// Logger.info('send read at, sender '+ message.sender.wxFullName+ ' '+ message.message +'message id'+ message.id)
|
||||||
|
|
||||||
|
if(message.oneShot == false) {
|
||||||
this.chatServiceService.sendReadAt({
|
this.chatServiceService.sendReadAt({
|
||||||
memberId: SessionStore.user.UserId,
|
memberId: SessionStore.user.UserId,
|
||||||
messageId: message.id,
|
messageId: message.id,
|
||||||
requestId: uuidv4(),
|
requestId: uuidv4(),
|
||||||
roomId: this.room.id
|
roomId: this.room.id
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// console.log('no need', message )
|
// console.log('no need', message )
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<div class="main-tab pb-10 ion-toolbar header-color">
|
<div class="main-tab pb-10 ion-toolbar header-color">
|
||||||
|
|
||||||
<div class="mobile pt-20 d-flex div-top-header justify-space-between">
|
<div class="mobile pt-20 d-flex div-top-header justify-space-between">
|
||||||
|
|
||||||
<div title="Pesquisa" *ngIf="!hideSearchBtn" class="div-search viewport-font-size">
|
<div title="Pesquisa" *ngIf="!hideSearchBtn" class="div-search viewport-font-size">
|
||||||
<div (click)="openSearch()" class="{{Cy.header.b.search}}">
|
<div (click)="openSearch()" class="{{Cy.header.b.search}}">
|
||||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="font-45-em"
|
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="font-45-em"
|
||||||
@@ -54,7 +53,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div (click)="openProfile()" *ngIf="(profilePictureSubject | async) as calendarData" class="profile-image">
|
<div (click)="openProfile()" *ngIf="(profilePictureSubject | async) as calendarData" class="profile-image">
|
||||||
<img *ngIf="calendarData.base64 != null" class="profile-image image-prety" src={{calendarData.base64}}>
|
<img *ngIf="calendarData.base64 != null" class="profile-image image-prety" [src]="getSafeImage(calendarData.base64)">
|
||||||
<ion-icon *ngIf="calendarData.base64 == null"
|
<ion-icon *ngIf="calendarData.base64 == null"
|
||||||
class="icon font-45-em" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
class="icon font-45-em" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -189,7 +188,7 @@
|
|||||||
|
|
||||||
<div title="Perfil" class="div-profile d-flex cursor-pointer font-45-rem" (click)="openProfile()">
|
<div title="Perfil" class="div-profile d-flex cursor-pointer font-45-rem" (click)="openProfile()">
|
||||||
<div *ngIf="(profilePictureSubject | async) as calendarData" class="profile-image d-flex">
|
<div *ngIf="(profilePictureSubject | async) as calendarData" class="profile-image d-flex">
|
||||||
<img *ngIf="calendarData.base64 != null" class="profile-image image-prety" src={{calendarData.base64}}>
|
<img *ngIf="calendarData.base64 != null" class="profile-image image-prety" [src]="getSafeImage(calendarData.base64)">
|
||||||
<ion-icon *ngIf="calendarData.base64 == null"
|
<ion-icon *ngIf="calendarData.base64 == null"
|
||||||
class="icon font-45-rem image-prety" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
class="icon font-45-rem image-prety" src='assets/images/theme/gov/icons-profile.svg'></ion-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { UserRepositoryService } from 'src/app/module/user/data/user-repository.
|
|||||||
import { UserProfilePicture } from 'src/app/module/user/data/datasource/user-local-repository.service';
|
import { UserProfilePicture } from 'src/app/module/user/data/datasource/user-local-repository.service';
|
||||||
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
import { TracingType, XTracerAsync } from 'src/app/services/monitoring/opentelemetry/tracer';
|
||||||
import { isHttpError } from 'src/app/services/http.service';
|
import { isHttpError } from 'src/app/services/http.service';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
@@ -80,7 +81,8 @@ export class HeaderPage implements OnInit {
|
|||||||
public HeaderSettingsService: HeaderSettingsService,
|
public HeaderSettingsService: HeaderSettingsService,
|
||||||
public PublicationHolderService: PublicationHolderService,
|
public PublicationHolderService: PublicationHolderService,
|
||||||
private notificationRepositoryService: NotificationRepositoryService,
|
private notificationRepositoryService: NotificationRepositoryService,
|
||||||
private UserRepositoryService: UserRepositoryService
|
private UserRepositoryService: UserRepositoryService,
|
||||||
|
private sanitizer: DomSanitizer
|
||||||
) {
|
) {
|
||||||
this.profilePictureSubject = this.UserRepositoryService.getProfilePictureLive() as any
|
this.profilePictureSubject = this.UserRepositoryService.getProfilePictureLive() as any
|
||||||
this.notificationCount$ = this.notificationRepositoryService.getNotificationLiveCount()
|
this.notificationCount$ = this.notificationRepositoryService.getNotificationLiveCount()
|
||||||
@@ -106,6 +108,10 @@ export class HeaderPage implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSafeImage(base64: string) {
|
||||||
|
return this.sanitizer.bypassSecurityTrustUrl(base64);
|
||||||
|
}
|
||||||
|
|
||||||
updateCount = () => {
|
updateCount = () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ import { environment as oaprProd } from './suport/oapr'
|
|||||||
// import { environment as doneITProd } from './suport/doneIt'
|
// import { environment as doneITProd } from './suport/doneIt'
|
||||||
|
|
||||||
|
|
||||||
export const environment: Environment = DevDev;
|
export const environment: Environment = oaprProd;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
<httpProtocol>
|
<httpProtocol>
|
||||||
<customHeaders>
|
<customHeaders>
|
||||||
<!-- Iframe on the same host only -->
|
<!-- Iframe on the same host only -->
|
||||||
<add name="Content-Security-Policy" value="frame-ancestors https://gdviewer-dev.dyndns.info/" />
|
<add name="Content-Security-Policy" value="frame-ancestors https://gdqas-api.oapr.gov.ao/" />
|
||||||
<!-- HTTPS on -->
|
<!-- HTTPS on -->
|
||||||
<add name="Strict-Transport-Security" value="max-age=31536000" />
|
<add name="Strict-Transport-Security" value="max-age=31536000" />
|
||||||
<add name="Referrer-Policy" value="no-referrer" />
|
<add name="Referrer-Policy" value="no-referrer" />
|
||||||
|
|||||||
Reference in New Issue
Block a user