mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 12:37:53 +00:00
remove expired room
This commit is contained in:
@@ -4,6 +4,12 @@
|
||||
"name": "gabinete-digital-fo",
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../sentium"
|
||||
},
|
||||
{
|
||||
"path": "../../../Desktop/contacts"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"nuxt.isNuxtApp": false,
|
||||
|
||||
@@ -107,6 +107,7 @@ import { openTelemetryLogging, OpenTelemetryLogging } from './services/monitorin
|
||||
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localePt from '@angular/common/locales/pt';
|
||||
import { LogsDatabase } from './infra/database/dexie/instance/logs/service';
|
||||
|
||||
// Register the locale data
|
||||
registerLocaleData(localePt, 'pt');
|
||||
@@ -126,8 +127,14 @@ registerLocaleData(localePt, 'pt');
|
||||
}) as Integration,
|
||||
],
|
||||
beforeSend(event) {
|
||||
console.log('event.exception.values[0].value', event.exception.values[0].value);
|
||||
|
||||
if (event.level === 'error') {
|
||||
// console.log(event.exception.values[0].value)
|
||||
|
||||
LogsDatabase.sentryError.add(event as any).then(() => {
|
||||
console.log('event', event)
|
||||
})
|
||||
|
||||
openTelemetryLogging.send({
|
||||
type: 'graylog',
|
||||
payload: {
|
||||
@@ -143,9 +150,7 @@ registerLocaleData(localePt, 'pt');
|
||||
// Return event to send it to Sentry
|
||||
return event;
|
||||
},
|
||||
},
|
||||
// Forward the init method to the sibling Framework.
|
||||
SentrySibling.init,
|
||||
}
|
||||
);
|
||||
|
||||
export const increment = createAction('[Counter Component] Increment');
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { HttpErrorResponse } from "@angular/common/http";
|
||||
import { Result } from "neverthrow";
|
||||
import { HttpResult } from "src/app/infra/http/type";
|
||||
import { PresidentialActionsCreateInput } from "../use-case/presidential-actions-create-use-case.service";
|
||||
|
||||
|
||||
export abstract class IActionsRepository {
|
||||
|
||||
// POST /api/v2/PresidentialActions
|
||||
abstract createPresidentialAction(body: PresidentialActionsCreateInput): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
|
||||
// GET /api/v2/PresidentialActions
|
||||
abstract getPresidentialActions(): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
|
||||
// GET /api/v2/PresidentialActions/{processId}
|
||||
abstract getPresidentialActionById(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
// DELETE /api/v2/PresidentialActions/{processId}
|
||||
abstract deletePresidentialAction(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
|
||||
// PUT /api/v2/PresidentialActions/{processId}
|
||||
abstract updatePresidentialAction(processId: number, body: any): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
|
||||
// GET /api/v2/PresidentialActions/{processId}/Posts
|
||||
abstract getPostsByProcessId(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
|
||||
// DELETE /api/v2/PresidentialActions/{processId}/Posts/{documentId}
|
||||
abstract deletePostByDocumentId(processId: number, documentId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
const PresidentialActionsCreateInputSchema = z.object({
|
||||
userId: z.number(),
|
||||
description: z.string(),
|
||||
detail: z.string(),
|
||||
location: z.string(),
|
||||
dateBegin: z.string().datetime(), // or use `.refine` for specific date format validation
|
||||
dateEnd: z.string().datetime(), // or use `.refine` for specific date format validation
|
||||
actionType: z.string(),
|
||||
});
|
||||
|
||||
// Type inference (optional, but useful if you need the TypeScript type)
|
||||
export type PresidentialActionsCreateInput = z.infer<typeof PresidentialActionsCreateInputSchema>;
|
||||
|
||||
|
||||
const PresidentialActionsCreateOutputSchema = z.object({});
|
||||
export type PresidentialActionsCreateOutput = z.infer<typeof PresidentialActionsCreateOutputSchema>;
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PresidentialActionsCreateUseCaseService {
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
const PresidentialActionsGetCreateInputSchema = z.object({
|
||||
userId: z.number(),
|
||||
description: z.string(),
|
||||
detail: z.string(),
|
||||
location: z.string(),
|
||||
dateBegin: z.string().datetime(), // or use `.refine` for specific date format validation
|
||||
dateEnd: z.string().datetime(), // or use `.refine` for specific date format validation
|
||||
actionType: z.string(),
|
||||
});
|
||||
|
||||
// Type inference (optional, but useful if you need the TypeScript type)
|
||||
export type PresidentialActionsGetCreateInput = z.infer<typeof PresidentialActionsGetCreateInputSchema>;
|
||||
|
||||
|
||||
const PresidentialActionsGetCreateOutputSchema = z.object({});
|
||||
export type PresidentialActionsGetCreateOutput = z.infer<typeof PresidentialActionsGetCreateOutputSchema>;
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PresidentialActionsGetGetService {
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
import { HttpErrorResponse } from "@angular/common/http";
|
||||
import { Result } from "neverthrow";
|
||||
import { HttpResult } from "src/app/infra/http/type";
|
||||
import { DataSourceReturn } from "src/app/services/Repositorys/type";
|
||||
|
||||
export abstract class IAttachmentRemoteRepository {
|
||||
abstract getAttachment(id: string | number): DataSourceReturn<Blob>
|
||||
abstract getAttachment(id: string | number): Promise<Result<HttpResult<Blob>, HttpErrorResponse>>
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DistributionTable, DistributionTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/destribution";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/instance/chat/service";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -6,9 +6,9 @@ import { DexieRoomsTable, RoomTableColumn } from 'src/app/infra/database/dexie/i
|
||||
import { DexieTypingsTable, TypingTableColumn } from 'src/app/infra/database/dexie/instance/chat/schema/typing';
|
||||
import { MessageEntity } from 'src/app/core/chat/entity/message';
|
||||
import { AttachmentTableColumn, DexieAttachmentsTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/attachment';
|
||||
import { DexieDistributionTable, DistributionTable, DistributionTableColumn } from './instance/chat/schema/destribution';
|
||||
import { BoldTableColumn, DexieBoldTable } from './instance/chat/schema/bold';
|
||||
import { DexieUserPhotoTable, UserPhotoTable, UserPhotoTableColumn } from './instance/chat/schema/user-foto';
|
||||
import { DexieDistributionTable, DistributionTable, DistributionTableColumn } from './schema/destribution';
|
||||
import { BoldTableColumn, DexieBoldTable } from './schema/bold';
|
||||
import { DexieUserPhotoTable, UserPhotoTable, UserPhotoTableColumn } from './schema/user-foto';
|
||||
// import FDBFactory from 'fake-indexeddb/lib/FDBFactory';
|
||||
// import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange';
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
import { EntityTable } from 'Dexie';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
const DscSchema = z.object({
|
||||
environment: z.string(),
|
||||
public_key: z.string(),
|
||||
release: z.string(),
|
||||
replay_id: z.any(),
|
||||
sample_rate: z.string(),
|
||||
sampled: z.boolean(),
|
||||
trace_id: z.string(),
|
||||
transaction: z.any(),
|
||||
});
|
||||
|
||||
const MetaSchema = z.object({
|
||||
breadcrumbs: z.object({
|
||||
values: z.record(z.string(), z.any()),
|
||||
}),
|
||||
});
|
||||
|
||||
const Breadcrumbs2Schema = z.object({
|
||||
values: z.array(z.object({
|
||||
timestamp: z.number(),
|
||||
type: z.string(),
|
||||
category: z.string(),
|
||||
level: z.string(),
|
||||
message: z.string().optional(),
|
||||
data: z.object({
|
||||
method: z.string().optional(),
|
||||
status_code: z.number().optional(),
|
||||
url: z.string().optional(),
|
||||
arguments: z.array(z.any()).optional(),
|
||||
logger: z.string().optional(),
|
||||
from: z.string().optional(),
|
||||
to: z.string().optional(),
|
||||
__span: z.string().optional(),
|
||||
}).optional(),
|
||||
event_id: z.string().optional(),
|
||||
})),
|
||||
});
|
||||
|
||||
const MetricsSchema = z.object({
|
||||
"bytes.ingested.event": z.number(),
|
||||
"bytes.stored.event": z.number(),
|
||||
});
|
||||
|
||||
const ContextsSchema = z.object({
|
||||
angular: z.object({
|
||||
type: z.string(),
|
||||
version: z.number(),
|
||||
}),
|
||||
browser: z.object({
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
type: z.string(),
|
||||
}),
|
||||
os: z.object({
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
type: z.string(),
|
||||
}),
|
||||
trace: z.object({
|
||||
trace_id: z.string(),
|
||||
span_id: z.string(),
|
||||
op: z.string(),
|
||||
status: z.string(),
|
||||
client_sample_rate: z.number(),
|
||||
type: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const ExceptionSchema = z.object({
|
||||
values: z.array(z.object({
|
||||
type: z.string(),
|
||||
value: z.string(),
|
||||
stacktrace: z.object({
|
||||
frames: z.array(z.object({
|
||||
function: z.string(),
|
||||
module: z.string(),
|
||||
filename: z.string(),
|
||||
abs_path: z.string(),
|
||||
lineno: z.number().optional(),
|
||||
colno: z.number().optional(),
|
||||
pre_context: z.array(z.string()).optional(),
|
||||
context_line: z.string().optional(),
|
||||
post_context: z.array(z.string()).optional(),
|
||||
in_app: z.boolean(),
|
||||
data: z.object({
|
||||
sourcemap: z.string(),
|
||||
resolved_with: z.string(),
|
||||
sourcemap_origin: z.object({
|
||||
scraped_file: z.string(),
|
||||
}),
|
||||
symbolicated: z.boolean(),
|
||||
orig_in_app: z.number().optional(),
|
||||
}).optional(),
|
||||
})),
|
||||
}),
|
||||
raw_stacktrace: z.object({
|
||||
frames: z.array(z.object({
|
||||
function: z.string().optional(),
|
||||
filename: z.string(),
|
||||
abs_path: z.string(),
|
||||
lineno: z.number().optional(),
|
||||
colno: z.number().optional(),
|
||||
context_line: z.string().optional(),
|
||||
post_context: z.array(z.string()).optional(),
|
||||
in_app: z.boolean(),
|
||||
})),
|
||||
}),
|
||||
mechanism: z.object({
|
||||
type: z.string(),
|
||||
handled: z.boolean(),
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
const GroupingConfigSchema = z.object({
|
||||
enhancements: z.string(),
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const IngestPathSchema = z.array(z.object({
|
||||
version: z.string(),
|
||||
public_key: z.string(),
|
||||
}));
|
||||
|
||||
const MetadataSchema = z.object({
|
||||
display_title_with_tree_label: z.boolean(),
|
||||
filename: z.string(),
|
||||
function: z.string(),
|
||||
in_app_frame_mix: z.string(),
|
||||
type: z.string(),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
const RequestSchema = z.object({
|
||||
url: z.string(),
|
||||
headers: z.array(z.tuple([z.string(), z.string()])),
|
||||
});
|
||||
|
||||
const ScrapingAttemptSchema = z.array(z.object({
|
||||
status: z.string(),
|
||||
url: z.string(),
|
||||
}));
|
||||
|
||||
const SdkSchema = z.object({
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
integrations: z.array(z.string()),
|
||||
packages: z.array(z.object({
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
})),
|
||||
});
|
||||
|
||||
const UserSchema = z.object({
|
||||
ip_address: z.string(),
|
||||
geo: z.object({
|
||||
country_code: z.string(),
|
||||
city: z.string(),
|
||||
subdivision: z.string(),
|
||||
region: z.string(),
|
||||
}),
|
||||
sentry_user: z.string(),
|
||||
});
|
||||
|
||||
const SentryErrorTableSchema = z.object({
|
||||
event_id: z.string(),
|
||||
project: z.number(),
|
||||
release: z.string(),
|
||||
dist: z.string(),
|
||||
platform: z.string(),
|
||||
message: z.string(),
|
||||
datetime: z.string(),
|
||||
tags: z.array(z.array(z.string())),
|
||||
_dsc: DscSchema,
|
||||
_meta: MetaSchema,
|
||||
_metrics: MetricsSchema,
|
||||
breadcrumbs: Breadcrumbs2Schema,
|
||||
contexts: ContextsSchema,
|
||||
culprit: z.string(),
|
||||
environment: z.string(),
|
||||
exception: ExceptionSchema,
|
||||
fingerprint: z.array(z.string()),
|
||||
grouping_config: GroupingConfigSchema,
|
||||
hashes: z.array(z.string()),
|
||||
ingest_path: IngestPathSchema,
|
||||
key_id: z.string(),
|
||||
level: z.string(),
|
||||
location: z.string(),
|
||||
logger: z.string(),
|
||||
metadata: MetadataSchema,
|
||||
nodestore_insert: z.number(),
|
||||
received: z.number(),
|
||||
request: RequestSchema,
|
||||
scraping_attempts: ScrapingAttemptSchema,
|
||||
sdk: SdkSchema,
|
||||
timestamp: z.number(),
|
||||
title: z.string(),
|
||||
type: z.string(),
|
||||
user: UserSchema,
|
||||
version: z.string(),
|
||||
});
|
||||
|
||||
export type SentryErrorTable = z.infer<typeof SentryErrorTableSchema>;
|
||||
export type DexieSentryErrorTable = EntityTable<SentryErrorTable, 'event_id'>;
|
||||
export const SentryErrorTableColumn = 'event_id';
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Dexie } from 'Dexie';
|
||||
import { DexieSentryErrorTable, SentryErrorTableColumn } from './schema/SentryErrors';
|
||||
// import FDBFactory from 'fake-indexeddb/lib/FDBFactory';
|
||||
// import FDBKeyRange from 'fake-indexeddb/lib/FDBKeyRange';
|
||||
|
||||
// Database declaration (move this to its own module also)
|
||||
export const LogsDatabase = new Dexie('logs-analytics', {
|
||||
// indexedDB: new FDBFactory,
|
||||
// IDBKeyRange: FDBKeyRange, // Mocking IDBKeyRange
|
||||
}) as Dexie & {
|
||||
sentryError: DexieSentryErrorTable
|
||||
};
|
||||
|
||||
LogsDatabase.version(1).stores({
|
||||
sentryError: SentryErrorTableColumn
|
||||
});
|
||||
|
||||
@@ -6,9 +6,17 @@ import { Observable } from 'rxjs';
|
||||
|
||||
export abstract class HttpAdapter {
|
||||
abstract post<T>(url: string, body: any): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract get<T>(url: string, options?: Object): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract get<T>(url: string, options?: IHttpOptions): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract put<T>(url: string, body: any): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract patch<T>(url: string, body?: Object): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract delete<T>(url: string, body?: Object): Promise<Result<HttpResult<T>, HttpErrorResponse>>
|
||||
abstract listen():Observable<Result<HttpResult<any>, HttpErrorResponse>>
|
||||
}
|
||||
|
||||
|
||||
// Define the interface for HTTP options
|
||||
export interface IHttpOptions {
|
||||
params?: { [param: string]: string | number };
|
||||
headers?: HttpHeaders;
|
||||
responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { ok, err, Result } from 'neverthrow';
|
||||
import { HttpResult } from './type';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { IHttpOptions } from './adapter';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -32,9 +34,22 @@ export class HttpService {
|
||||
}
|
||||
}
|
||||
|
||||
async get<T>(url: string, options = {}): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
|
||||
async get<T>(url: string, options?: IHttpOptions): Promise<Result<HttpResult<T>, HttpErrorResponse>> {
|
||||
try {
|
||||
const response = await this.http.get<T>(url, { ...options, observe: 'response' }).toPromise();
|
||||
let httpParams = new HttpParams();
|
||||
if (options?.params) {
|
||||
Object.keys(options.params).forEach(key => {
|
||||
httpParams = httpParams.append(key, String(options.params[key]));
|
||||
});
|
||||
}
|
||||
|
||||
const httpOptions = {
|
||||
params: httpParams,
|
||||
headers: options?.headers || new HttpHeaders(),
|
||||
responseType: options?.responseType || 'json' as any,
|
||||
};
|
||||
|
||||
const response = await this.http.get<T>(url, { ...httpOptions, observe: 'response', responseType: httpOptions.responseType }).toPromise();
|
||||
|
||||
const data = {
|
||||
method: 'GET',
|
||||
|
||||
@@ -20,7 +20,7 @@ export abstract class IDexieRepository<T, R, I = EntityTable<any, any>> {
|
||||
|
||||
abstract find(filter: Partial<T>): Promise<RepositoryResult<R[], T[]>>
|
||||
|
||||
abstract findOne(filter: Partial<T>): Promise<RepositoryResult<T | undefined, T>>
|
||||
abstract findOne(filter: Partial<T>): Promise<RepositoryResult<T & ILocalModel | undefined, T>>
|
||||
|
||||
abstract findAll(): Promise<RepositoryResult<T[], T>>
|
||||
|
||||
@@ -28,3 +28,8 @@ export abstract class IDexieRepository<T, R, I = EntityTable<any, any>> {
|
||||
|
||||
abstract clear(): Promise<Result<any, any>>
|
||||
}
|
||||
|
||||
export abstract class ILocalModel{
|
||||
abstract save()
|
||||
abstract delete()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Result, ok, err } from 'neverthrow';
|
||||
import Dexie, { EntityTable, Table } from 'Dexie';
|
||||
import { ZodError, ZodObject, ZodSchema } from 'zod';
|
||||
import { Logger } from 'src/app/services/logger/main/service';
|
||||
import { IDexieRepository, RepositoryResult } from '../adapter'
|
||||
import { IDexieRepository, ILocalModel, RepositoryResult } from '../adapter'
|
||||
import { IDBError, IDBErrorParams, IDexieError } from '../types';
|
||||
|
||||
// Define a type for the Result of repository operations
|
||||
@@ -150,6 +150,10 @@ export class DexieRepository<T, R, I = EntityTable<any, any>> implements IDexieR
|
||||
const schema = this.ZodSchema.array()
|
||||
const dataValidation = schema.safeParse(updatedDocument)
|
||||
|
||||
if(updatedDocument.length == 0) {
|
||||
console.log(`dexie.js failed to update many into ${this.table.name}, empty array)`)
|
||||
}
|
||||
|
||||
if(dataValidation.success) {
|
||||
try {
|
||||
const updatedCount = await this.table.bulkPut(dataValidation.data);
|
||||
@@ -157,7 +161,7 @@ export class DexieRepository<T, R, I = EntityTable<any, any>> implements IDexieR
|
||||
} catch (_error) {
|
||||
const error: IDexieError = _error
|
||||
return err(new DBError({
|
||||
message: `dexie.js Failed to update into ${this.table.name}, ${error.message} `,
|
||||
message: `dexie.js Failed to update many into ${this.table.name}, ${error.message} `,
|
||||
parameters: document,
|
||||
error: error
|
||||
}))
|
||||
@@ -214,7 +218,7 @@ export class DexieRepository<T, R, I = EntityTable<any, any>> implements IDexieR
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(filter: Partial<T>): Promise<RepositoryResult<T | undefined, T>> {
|
||||
async findOne(filter: Partial<T>): Promise<RepositoryResult<T & ILocalModel | undefined, T>> {
|
||||
try {
|
||||
const document = await this.table.where(filter).first();
|
||||
return ok(document);
|
||||
@@ -228,7 +232,7 @@ export class DexieRepository<T, R, I = EntityTable<any, any>> implements IDexieR
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(): Promise<RepositoryResult<T[], T>> {
|
||||
async findAll(): Promise<RepositoryResult<(T & ILocalModel)[], T>> {
|
||||
try {
|
||||
const documents = await this.table.toArray()
|
||||
return ok(documents);
|
||||
@@ -265,3 +269,23 @@ export class DexieRepository<T, R, I = EntityTable<any, any>> implements IDexieR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class LocalModel<T, R, I = EntityTable<any, any>> implements ILocalModel {
|
||||
|
||||
constructor(
|
||||
private table: EntityTable<any, any>,
|
||||
private repository: DexieRepository<T, R, I>,
|
||||
private db?:Dexie,
|
||||
) {}
|
||||
|
||||
save() {
|
||||
const primaryKey = this.db[this.table.name].schema.primKey.name
|
||||
return this.repository.update(primaryKey, this as any)
|
||||
}
|
||||
|
||||
delete() {
|
||||
const primaryKey = this.db[this.table.name].schema.primKey.name
|
||||
return this.repository.delete(primaryKey)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ import * as signalR from '@microsoft/signalr';
|
||||
import { BehaviorSubject, Observable, race, timer } from 'rxjs';
|
||||
import { ok, Result, err } from 'neverthrow';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { filter, first } from 'rxjs/operators';
|
||||
import { filter, first, map } from 'rxjs/operators';
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { ISignalRInput } from '../type';
|
||||
import { MessageOutPutDataDTO } from 'src/app/core/chat/repository/dto/messageOutputDTO';
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
export interface SocketMessage<T> {
|
||||
method: string,
|
||||
data: T
|
||||
@@ -170,7 +170,7 @@ export class SignalRConnection {
|
||||
}
|
||||
|
||||
public getConnectionState(): Observable<boolean> {
|
||||
return this.connectionStateSubject.asObservable();
|
||||
return this.connectionStateSubject.asObservable()
|
||||
}
|
||||
|
||||
public getDisconnectTrigger(): Observable<boolean> {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Result } from 'neverthrow';
|
||||
import { IActionsRepository } from 'src/app/core/actions/repository/actionsRepository';
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter'
|
||||
import { HttpResult } from 'src/app/infra/http/type';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ActionsRepositoryService implements IActionsRepository {
|
||||
|
||||
|
||||
private readonly baseUrl = '/api/v2/PresidentialActions';
|
||||
|
||||
constructor(
|
||||
private HttpAdapter: HttpAdapter
|
||||
) {}
|
||||
|
||||
// POST /api/v2/PresidentialActions
|
||||
async createPresidentialAction(body: any): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}`;
|
||||
return this.HttpAdapter.post<any>(url, body);
|
||||
}
|
||||
|
||||
// GET /api/v2/PresidentialActions
|
||||
async getPresidentialActions(): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}`;
|
||||
return this.HttpAdapter.get<any>(url);
|
||||
}
|
||||
|
||||
// GET /api/v2/PresidentialActions/{processId}
|
||||
async getPresidentialActionById(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}/${processId}`;
|
||||
return this.HttpAdapter.get<any>(url);
|
||||
}
|
||||
|
||||
// DELETE /api/v2/PresidentialActions/{processId}
|
||||
async deletePresidentialAction(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}/${processId}`;
|
||||
return this.HttpAdapter.delete<any>(url);
|
||||
}
|
||||
|
||||
// PUT /api/v2/PresidentialActions/{processId}
|
||||
async updatePresidentialAction(processId: number, body: any): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}/${processId}`;
|
||||
return this.HttpAdapter.put<any>(url, body);
|
||||
}
|
||||
|
||||
// GET /api/v2/PresidentialActions/{processId}/Posts
|
||||
async getPostsByProcessId(processId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}/${processId}/Posts`;
|
||||
return this.HttpAdapter.get<any>(url);
|
||||
}
|
||||
|
||||
// DELETE /api/v2/PresidentialActions/{processId}/Posts/{documentId}
|
||||
async deletePostByDocumentId(processId: number, documentId: number): Promise<Result<HttpResult<any>, HttpErrorResponse>> {
|
||||
const url = `${this.baseUrl}/${processId}/Posts/${documentId}`;
|
||||
return this.HttpAdapter.delete<any>(url);
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,6 @@ export class ChatModule {
|
||||
const connection = this.SignalRService.getConnectionState()
|
||||
|
||||
connection.pipe(
|
||||
skip(1) // Skip the first value
|
||||
).subscribe((value: boolean)=> {
|
||||
if(value) {
|
||||
// on reconnect
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { IAttachmentLocalRepository } from 'src/app/core/chat/repository/typing/typing-local-repository';
|
||||
import { AttachmentTable, AttachmentTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/attachment';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
|
||||
@Injectable({
|
||||
|
||||
+5
-4
@@ -2,7 +2,7 @@ import { Injectable, Input } from '@angular/core';
|
||||
import { IAttachmentRemoteRepository } from 'src/app/core/chat/repository/attachment/attachment-remote-repository';
|
||||
import { HttpService } from 'src/app/services/http.service';
|
||||
import { DataSourceReturn } from 'src/app/services/Repositorys/type';
|
||||
|
||||
import { HttpAdapter } from 'src/app/infra/http/adapter'
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
@@ -10,11 +10,12 @@ export class AttachmentRemoteDataSourceService implements IAttachmentRemoteRepos
|
||||
private baseUrl = 'https://gdapi-dev.dyndns.info/stage/api/v2/Chat'; // Your base URL
|
||||
|
||||
constructor(
|
||||
private httpService: HttpService
|
||||
private httpService: HttpService,
|
||||
private HttpAdapter: HttpAdapter
|
||||
) { }
|
||||
|
||||
async getAttachment(id: string | number): DataSourceReturn<Blob> {
|
||||
return await this.httpService.getFile(`${this.baseUrl}/attachment/${id}`, { responseType: 'blob' });
|
||||
async getAttachment(id: string | number) {
|
||||
return await this.HttpAdapter.get<Blob>(`${this.baseUrl}/attachment/${id}`, { responseType: 'blob' })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { from } from "rxjs";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
import { Dexie, EntityTable, liveQuery, Observable } from 'Dexie';
|
||||
import { BoldTable, BoldTableSchema } from "src/app/infra/database/dexie/instance/chat/schema/bold";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/instance/chat/service";
|
||||
import { IBoldLocalRepository } from "src/app/core/chat/repository/bold/bold-local-repository";
|
||||
|
||||
@Injectable({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DistributionTable, DistributionTableSchema,DistributionTableColumn } from "src/app/infra/database/dexie/instance/chat/schema/destribution";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/service";
|
||||
import { chatDatabase } from "src/app/infra/database/dexie/instance/chat/service";
|
||||
import { DexieRepository } from "src/app/infra/repository/dexie/dexie-repository.service";
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { err, Result } from 'neverthrow';
|
||||
import { MemberListUPdateStatusInputDTO } from '../../../domain/use-case/socket/member-list-update-status-use-case.service';
|
||||
import { from } from 'rxjs';
|
||||
import { MemberTable, MemberTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/members';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { IDirectMemberInput, IGetMemberLive, IMemberLocalRepository } from 'src/app/core/chat/repository/member/member-local-repository';
|
||||
|
||||
@Injectable({
|
||||
|
||||
@@ -4,7 +4,7 @@ import { MessageEntity } from '../../../../../core/chat/entity/message';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
import { Observable as DexieObservable, PromiseExtended } from 'Dexie';
|
||||
import { DexieMessageTable, MessageTable, MessageTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/message';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { IDirectMessages, IMessageLocalRepository } from 'src/app/core/chat/repository/message/message-local-repository';
|
||||
import { BehaviorSubject, combineLatest, from, Observable } from 'rxjs';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { liveQuery, Observable } from 'Dexie';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
import { BehaviorSubject, from } from 'rxjs';
|
||||
import { RoomTable, RoomTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/room';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
import { IDBoolean } from 'src/app/infra/database/dexie/type';
|
||||
import { RoomType } from 'src/app/core/chat/entity/group';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { z } from 'zod';
|
||||
import { Dexie, EntityTable, liveQuery, Observable } from 'Dexie';
|
||||
import { err, ok } from 'neverthrow';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { TypingTable, TypingTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/typing';
|
||||
import { ITypingLocalRepository } from 'src/app/core/chat/repository/attachment/attachment-local-repository';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import Dexie, { PromiseExtended } from 'Dexie';
|
||||
import { IUserPhotoLocalRepository } from 'src/app/core/chat/repository/user-photo/user-photo-local-repository';
|
||||
import { UserPhotoTable, UserPhotoTableSchema } from 'src/app/infra/database/dexie/instance/chat/schema/user-foto';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/service';
|
||||
import { chatDatabase } from 'src/app/infra/database/dexie/instance/chat/service';
|
||||
import { DexieRepository } from 'src/app/infra/repository/dexie/dexie-repository.service';
|
||||
|
||||
@Injectable({
|
||||
|
||||
@@ -164,7 +164,6 @@ export class ChatServiceService {
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.chatSync()
|
||||
this.SocketConnectUseCaseService.execute();
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -64,24 +64,24 @@ export class MessageAttachmentByMessageIdUseCase {
|
||||
tracing.setAttribute('download', 'true')
|
||||
tracing.setAttribute('attachmentId', input.attachments[0].id.toString())
|
||||
|
||||
const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.attachments[0].id)
|
||||
if(result.isErr()) {
|
||||
const httpResult = await this.AttachmentRemoteDataSourceService.getAttachment(input.attachments[0].id)
|
||||
if(httpResult.isErr()) {
|
||||
tracing.hasError('failed to download message attachment', {
|
||||
error: result.error,
|
||||
error: httpResult.error,
|
||||
data: 'document id '+ input.attachments[0].id,
|
||||
messageId: input.id,
|
||||
$messageId: input.$id
|
||||
})
|
||||
|
||||
if(isHttpResponse(result.error)) {
|
||||
tracing.setAttribute('attachmentUrl', result.error.message)
|
||||
if(isHttpResponse(httpResult.error)) {
|
||||
tracing.setAttribute('attachmentUrl', httpResult.error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(result.isOk()) {
|
||||
if(httpResult.isOk()) {
|
||||
|
||||
const dataUrl = await createBlobUrl(result.value)
|
||||
const dataUrl = await createBlobUrl(httpResult.value.data)
|
||||
|
||||
if(dataUrl.isOk()) {
|
||||
|
||||
@@ -92,7 +92,7 @@ export class MessageAttachmentByMessageIdUseCase {
|
||||
|
||||
this.AttachmentLocalDataSource.insert({
|
||||
$messageId: input.$id,
|
||||
file: result.value,
|
||||
file: httpResult.value.data,
|
||||
fileType: input.attachments[0].fileType,
|
||||
source: input.attachments[0].source,
|
||||
fileName: input.attachments[0].fileName,
|
||||
@@ -110,13 +110,13 @@ export class MessageAttachmentByMessageIdUseCase {
|
||||
|
||||
return dataUrl
|
||||
} else {
|
||||
console.log('dataUrl eerror', dataUrl.error)
|
||||
console.log('dataUrl eerror', dataUrl.error, 'url:,', httpResult.value)
|
||||
return err(false)
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return result as any
|
||||
return httpResult as any
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,10 +31,10 @@ export class DownloadMessageAttachmentUserCaseService {
|
||||
|
||||
if(validation.isOk()) {
|
||||
|
||||
const result = await this.AttachmentRemoteDataSourceService.getAttachment(input.id)
|
||||
return result.asyncMap(async (blob) => {
|
||||
const httpResult = await this.AttachmentRemoteDataSourceService.getAttachment(input.id)
|
||||
return httpResult.asyncMap(async (response) => {
|
||||
|
||||
const dataUrl = await createBlobUrl(blob)
|
||||
const dataUrl = await createBlobUrl(response.data)
|
||||
|
||||
if(dataUrl.isOk()) {
|
||||
|
||||
@@ -46,7 +46,7 @@ export class DownloadMessageAttachmentUserCaseService {
|
||||
this.AttachmentLocalDataSource.insert({
|
||||
$messageId: input.$messageId,
|
||||
id: input.id,
|
||||
file: blob,
|
||||
file: response.data,
|
||||
})
|
||||
|
||||
return dataUrl.value
|
||||
|
||||
@@ -27,6 +27,7 @@ export class MessageLocalGetByIdService {
|
||||
})
|
||||
}
|
||||
else if(input.roomId) {
|
||||
console.log('find(')
|
||||
return this.messageLocalRepository.find({roomId: input.roomId})
|
||||
} else if (input.receiverId) {
|
||||
return this.messageLocalRepository.find({receiverId: parseInt(input.receiverId)})
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ export class MessageMarkAsReadUseCaseService {
|
||||
) { }
|
||||
|
||||
|
||||
@XTracerAsync({name:'MessageMarkAsReadUseCaseService', module:'chat', bugPrint: true})
|
||||
@XTracerAsync({name:'MessageMarkAsReadUseCaseService', module:'chat', bugPrint: true, waitNThrow: 5000})
|
||||
async execute(sendReadAt: MessageMarkAsReadInput, tracing?: TracingType) {
|
||||
const result = await this.MessageSocketRepositoryService.sendReadAt(sendReadAt as any)
|
||||
|
||||
|
||||
@@ -105,30 +105,24 @@ export class RoomBoldSyncUseCaseService {
|
||||
|
||||
const room = await this.roomLocalDataSourceService.findOne({id: roomId})
|
||||
|
||||
if(room.isOk() && room.value) {
|
||||
const roomEntity = new RoomEntity(room.value)
|
||||
if (roomEntity.hasLastMessage()) {
|
||||
|
||||
const message = Object.assign(new MessageEntity(), roomEntity.messages[0])
|
||||
const message = Object.assign(new MessageEntity(), loadHistoryFirstMessage)
|
||||
const haveSeen = message.haveSeen()
|
||||
|
||||
if(!haveSeen && !message.meSender()) {
|
||||
if(haveSeen ===false && message.meSender() == false) {
|
||||
await this.boldLocalRepository.open()
|
||||
const result = await this.boldLocalRepository.findOne({roomId: roomEntity.id})
|
||||
const result = await this.boldLocalRepository.findOne({roomId: roomId})
|
||||
|
||||
if(result.isOk() && !result.value) {
|
||||
const result = await this.boldLocalRepository.insert({roomId: roomEntity.id, bold: 1})
|
||||
const result = await this.boldLocalRepository.insert({roomId: roomId, bold: 1})
|
||||
} else if(result.isOk() && result.value.bold == 0) {
|
||||
const result = await this.boldLocalRepository.update(roomEntity.id, {bold: 1})
|
||||
const result = await this.boldLocalRepository.update(roomId, {bold: 1})
|
||||
} else {
|
||||
// tracing.hasError("failed to set bold",{})
|
||||
}
|
||||
} else {
|
||||
const result = await this.boldLocalRepository.update(roomEntity.id, {bold: 0})
|
||||
}
|
||||
const result = await this.boldLocalRepository.update(roomId, {bold: 0})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
@@ -9,6 +9,7 @@ import { GetRoomByIdMapper } from 'src/app/core/chat/mapper/getRoomByIdMapper';
|
||||
import { RoomEntity, RoomType } from 'src/app/core/chat/entity/group';
|
||||
import { diff, addedDiff, deletedDiff, updatedDiff, detailedDiff } from 'deep-object-diff';
|
||||
import { zodSafeValidation } from 'src/app/utils/zodValidation';
|
||||
import { CronJobService } from 'src/app/utils/task-scheduler'
|
||||
|
||||
const UserSchema = z.object({
|
||||
wxUserId: z.number(),
|
||||
@@ -54,13 +55,13 @@ export class GetRoomByIdUseCaseService {
|
||||
constructor(
|
||||
private roomRemoteDataSourceService: IRoomRemoteRepository,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
private MemberListLocalRepository: IMemberLocalRepository
|
||||
private MemberListLocalRepository: IMemberLocalRepository,
|
||||
private CronJobService: CronJobService
|
||||
) { }
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/getRoomById')
|
||||
async execute(id: RoomByIdInputDTO) {
|
||||
|
||||
console.log('iiiiiiiiiiii', id)
|
||||
const result = await this.roomRemoteDataSourceService.getRoom(id)
|
||||
|
||||
if(result.isOk()) {
|
||||
@@ -92,16 +93,30 @@ export class GetRoomByIdUseCaseService {
|
||||
|
||||
} else if (getRoomById.isOk() && !getRoomById.value) {
|
||||
const room = GetRoomByIdMapper.toDomain(validData.value)
|
||||
this.roomLocalDataSourceService.insert(room)
|
||||
const createResult = await this.roomLocalDataSourceService.insert(room)
|
||||
|
||||
if(createResult.isErr()) {
|
||||
console.error('createResultErr', createResult.error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(validData.value.data.expirationDate) {
|
||||
this.CronJobService.createCronJob(`remove expired room ${id}`, new Date(validData.value.data.expirationDate), () => {
|
||||
setTimeout(() => {
|
||||
this.execute(id);
|
||||
}, 60000);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if (isHttpResponse(result.error) ) {
|
||||
if(result.error.status == 404) {
|
||||
await this.roomLocalDataSourceService.delete(id)
|
||||
|
||||
+18
-4
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { GetRoomListUseCaseService } from './room-get-list-use-case.service'
|
||||
import { RoomSocketRepositoryService } from '../../../data/repository/room/room-socket-repository.service'
|
||||
import { IRoomLocalRepository } from 'src/app/core/chat/repository/room/room-local-repository';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -9,7 +10,8 @@ export class RoomGetListOnCreateUseCaseService {
|
||||
|
||||
constructor(
|
||||
private RoomSocketRepositoryService: RoomSocketRepositoryService,
|
||||
private getRoomListUseCaseService: GetRoomListUseCaseService
|
||||
private getRoomListUseCaseService: GetRoomListUseCaseService,
|
||||
private roomLocalDataSourceService: IRoomLocalRepository,
|
||||
) {
|
||||
this.init()
|
||||
}
|
||||
@@ -21,10 +23,22 @@ export class RoomGetListOnCreateUseCaseService {
|
||||
}
|
||||
|
||||
|
||||
private OnReceiveCreateRoom() {
|
||||
this.RoomSocketRepositoryService.listenToCreateRoom().subscribe((data)=> {
|
||||
console.log('OnReceiveCreateRoom', data)
|
||||
private async OnReceiveCreateRoom() {
|
||||
this.RoomSocketRepositoryService.listenToCreateRoom().subscribe(async(data)=> {
|
||||
|
||||
setTimeout(async () => {
|
||||
const findLocally = await this.roomLocalDataSourceService.findOne({id:(data.data as any).id})
|
||||
|
||||
if(findLocally.isOk() && !findLocally.value) {
|
||||
this.getRoomListUseCaseService.execute()
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
|
||||
|
||||
// const result = await this.roomRemoteDataSourceService.getRoom(id)
|
||||
// console.log('OnReceiveCreateRoom', data)
|
||||
//this.getRoomListUseCaseService.execute()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ export class GetRoomListUseCaseService {
|
||||
|
||||
@captureAndReraiseAsync('RoomRepositoryService/list')
|
||||
async execute() {
|
||||
console.log('update===============')
|
||||
const result = await this.roomRemoteDataSourceService.getRoomList()
|
||||
|
||||
const localList = await this.roomLocalDataSourceService.findAll()
|
||||
@@ -108,22 +109,44 @@ export class GetRoomListUseCaseService {
|
||||
}
|
||||
|
||||
} else {
|
||||
this.roomLocalDataSourceService.insert(room)
|
||||
const createResult = this.roomLocalDataSourceService.insert(room)
|
||||
|
||||
createResult.then((result) => {
|
||||
if(result.isErr()) {
|
||||
console.log('error', result.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if(room.expirationDate) {
|
||||
this.CronJobService.createCronJob('remove expired room', new Date(room.expirationDate), this.execute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(roomsToUpdate.length >= 1) {
|
||||
const roomsToUpdateEntity = GetRoomListMapper.toDomain(roomsToUpdate)
|
||||
this.roomLocalDataSourceService.updateMany(roomsToUpdateEntity)
|
||||
}
|
||||
|
||||
for( const room of roomsToDelete) {
|
||||
if(room.local == IDBoolean.false) {
|
||||
this.roomLocalDataSourceService.delete(room.id)
|
||||
const findResult = this.roomLocalDataSourceService.findOne({id:room.id})
|
||||
findResult.then((result) => {
|
||||
if(result.isOk() && result.value) {
|
||||
this.roomLocalDataSourceService.delete(result.value.$id)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(const room of filterValidateRooms) {
|
||||
if(room.chatRoom.expirationDate) {
|
||||
|
||||
|
||||
this.CronJobService.createCronJob('remove expired room list', new Date(room.chatRoom.expirationDate), () => {
|
||||
setTimeout(() => {
|
||||
this.execute();
|
||||
}, 60000);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ if (window.location.protocol !== 'https:' && environment.apiURL != 'https://gdqa
|
||||
// const metricReader = new PeriodicExportingMetricReader({
|
||||
// exporter: new OTLPMetricExporter({
|
||||
// //url: 'https://5-180-182-151.cloud-xip.com:85/collector2/v1/metrics',
|
||||
// url: 'https://185-229-224-75.cloud-xip.com:85/collector2/v1/metrics',
|
||||
// // url: 'https://185-229-224-75.cloud-xip.com:85/collector2/v1/metrics',
|
||||
// //url: 'http://5-180-182-151.cloud-xip.com:4318/v1/metrics',
|
||||
// //url: 'http://185-229-224-75.cloud-xip.com:4318/v1/metrics'
|
||||
// // headers: {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
||||
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
|
||||
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
|
||||
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
|
||||
import { Resource } from '@opentelemetry/resources';
|
||||
//import { OTLPTraceExporter } from '@opentelemetry/exporter-otlp-http';
|
||||
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) {
|
||||
const provider = new WebTracerProvider({
|
||||
|
||||
@@ -11,10 +11,6 @@ const routes: Routes = [
|
||||
path: 'new-group',
|
||||
loadChildren: () => import('./modal/new-group/new-group.module').then( m => m.NewGroupPageModule)
|
||||
},
|
||||
{
|
||||
path: 'group-messages',
|
||||
loadChildren: () => import('./modal/group-messages/group-messages.module').then( m => m.GroupMessagesPageModule)
|
||||
},
|
||||
{
|
||||
path: 'messages',
|
||||
outlet:'message',
|
||||
@@ -28,14 +24,6 @@ const routes: Routes = [
|
||||
path: 'chat-options-popover',
|
||||
loadChildren:() => import('./modal/chat-options-popover/chat-options-popover.module').then( m => m.ChatOptionsPopoverPageModule)
|
||||
},
|
||||
{
|
||||
path: 'chat-debugging',
|
||||
loadChildren: () => import('./modal/chat-debugging/chat-debugging.module').then( m => m.ChatDebuggingPageModule)
|
||||
},
|
||||
{
|
||||
path: 'chat-message-debugging',
|
||||
loadChildren: () => import('./modal/chat-message-debugging/chat-message-debugging.module').then( m => m.ChatMessageDebuggingPageModule)
|
||||
},
|
||||
{
|
||||
path: 'empty-chat',
|
||||
loadChildren: () => import('./component/empty-chat/empty-chat.module').then( m => m.EmptyChatPageModule)
|
||||
|
||||
@@ -15,8 +15,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { ImageCropperModule } from 'ngx-image-cropper';
|
||||
import { EmptyChatPageModule } from './component/empty-chat/empty-chat.module';
|
||||
import { EditGroupPageModule } from './component/edit-group/edit-group.module';
|
||||
import { GroupContactsPageModule } from './component/group-messages/group-contacts/group-contacts.module';
|
||||
import { GroupMessagesPageModule } from './component/group-messages/group-messages.module';
|
||||
import { GroupContactsPageModule } from './component/group-contacts/group-contacts.module';
|
||||
import { MessagesPageModule } from './component/messages/messages.module';
|
||||
import { ContactsPageModule } from './component/contacts/contacts.module';
|
||||
import { NewGroupPageModule } from './component/new-group/new-group.module';
|
||||
@@ -35,7 +34,6 @@ import { BoldLocalRepository } from 'src/app/module/chat/data/repository/bold/bo
|
||||
RouterModule,
|
||||
MessagesPageModule,
|
||||
ContactsPageModule,
|
||||
GroupMessagesPageModule,
|
||||
NewGroupPageModule,
|
||||
EditGroupPageModule,
|
||||
GroupContactsPageModule,
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { GroupMessagesPage } from './modal/group-messages/group-messages.page';
|
||||
import { ContactsPage } from './modal/./messages/contacts/contacts.page';
|
||||
import { MessagesPage } from './modal/./messages/messages.page';
|
||||
import { INewGroupModalOutPut, NewGroupPage } from './modal/./new-group/new-group.page';
|
||||
@@ -551,22 +550,4 @@ export class ChatPage implements OnInit {
|
||||
|
||||
}
|
||||
|
||||
|
||||
async openGroupMessagesModal(roomId: any) {
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
component: GroupMessagesPage,
|
||||
cssClass: 'modal modal-desktop isGroupChatOpened',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
|
||||
modal.onDidDismiss().then(() => {
|
||||
// this.ChatSystemService.currentRoom.roomLeave()
|
||||
});
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import { ContactsPageRoutingModule } from './contacts-routing.module';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
import { FilterPipe } from 'src/app/pipes/filter.pipe';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -16,9 +17,9 @@ import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ContactsPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
PipesModule,
|
||||
],
|
||||
declarations: [ContactsPage],
|
||||
exports: [ContactsPage]
|
||||
exports: [ContactsPage],
|
||||
declarations: [ContactsPage]
|
||||
})
|
||||
export class ContactsPageModule {}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { GroupMessagesPage } from '../group-messages/group-messages.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
|
||||
+2
-10
@@ -80,11 +80,10 @@ export class GroupContactsPage implements OnInit {
|
||||
async loadUsers() {
|
||||
|
||||
const getallChatUsers = await this.contactsRepositoryService.getUsers()
|
||||
const getRoomById = await this.chatServiceService.getRoomById(this.roomId)
|
||||
|
||||
console.log({getallChatUsers, getRoomById})
|
||||
// console.log({getallChatUsers, getRoomById})
|
||||
|
||||
if(getallChatUsers.isOk() && getRoomById.isOk()) {
|
||||
if(getallChatUsers.isOk()) {
|
||||
|
||||
this.allChatUsers = getallChatUsers.value.data.result.sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
@@ -128,13 +127,6 @@ export class GroupContactsPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (getRoomById.isErr() && getRoomById.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() && getallChatUsers.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getallChatUsers.error)
|
||||
} else if (getRoomById.isErr() ) {
|
||||
console.log(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() ) {
|
||||
console.log(getallChatUsers.error)
|
||||
} else {
|
||||
@@ -1,21 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupMessagesPage
|
||||
},
|
||||
{
|
||||
path: 'group-contacts',
|
||||
loadChildren: () => import('./group-contacts/group-contacts.module').then( m => m.GroupContactsPageModule)
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
@@ -1,36 +0,0 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPageRoutingModule } from './group-messages-routing.module';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import { LettersAvatarModule } from "ngx-letters-avatar";
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
import { SafehtmlPipe } from 'src/app/pipes/safehtml.pipe';
|
||||
import { ChatPopoverPageModule } from '../../modal/chat-popover/chat-popover.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
FontAwesomeModule,
|
||||
ChatPopoverPageModule,
|
||||
GroupMessagesPageRoutingModule,
|
||||
MatMenuModule,
|
||||
LettersAvatarModule,
|
||||
PipesModule,
|
||||
//
|
||||
],
|
||||
exports: [GroupMessagesPage],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
declarations: [GroupMessagesPage]
|
||||
})
|
||||
export class GroupMessagesPageModule {}
|
||||
@@ -1,350 +0,0 @@
|
||||
@import '~src/function.scss';
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow:auto;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
//transform: translate3d(0, 1px, 0);
|
||||
|
||||
.header-top{
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
.middle{
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
width:calc(100% - 77px);
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.right{
|
||||
padding: 0!important;
|
||||
float: right;
|
||||
font-size: rem(25);
|
||||
color: #0782c9;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
}
|
||||
.header-bottom{
|
||||
width: 98%;
|
||||
overflow: auto;
|
||||
|
||||
.header-bottom-icon{
|
||||
width: rem(30);
|
||||
font-size: rem(25);
|
||||
float: left;
|
||||
padding: 2px;
|
||||
|
||||
}
|
||||
.header-bottom-contacts{
|
||||
width: calc(100% - 40px);
|
||||
font-size: rem(15);
|
||||
color: #797979;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
float: left;
|
||||
padding: 5px;
|
||||
margin: 1px;
|
||||
|
||||
.contacts-list{
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
float: left;
|
||||
}
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn-delete-recording{
|
||||
margin-left: 20px !important;
|
||||
}
|
||||
|
||||
ion-content{
|
||||
.welcome-text{
|
||||
/* width: 322px; */
|
||||
//width: em(422px);
|
||||
background: #ebebeb;
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #797979;
|
||||
padding: 10px;
|
||||
margin: 0 auto !important;
|
||||
line-height: 1.2rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.info-text{
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
}
|
||||
.info-text-leave{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
padding: 10px;
|
||||
background: #e0e9ee;
|
||||
border-radius: 8px;
|
||||
margin: 10px auto;
|
||||
color: #797979 !important;
|
||||
font-size: rem(13) !important;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
|
||||
.info-text-leave ion-label{
|
||||
font-size: rem(13) !important;
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.info-meeting{
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
|
||||
.info-meeting-small{
|
||||
font-size: rem(10);
|
||||
font-style: italic;
|
||||
}
|
||||
.info-meeting-medium{
|
||||
font-size: rem(12);
|
||||
}
|
||||
.info-meeting-normal{
|
||||
font-weight: 700;
|
||||
}
|
||||
.info-meeting-normal:hover{
|
||||
text-decoration: underline;
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
.messages{
|
||||
font-size: rem(13);
|
||||
font-family: Roboto;
|
||||
overflow: auto;
|
||||
|
||||
//set scroll do bottom
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
word-wrap: break-word;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.incoming-true, .incoming-false{
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.incoming-true{
|
||||
margin: 10px 75px 10px 20px;
|
||||
background: #ebebeb;
|
||||
float: left;
|
||||
}
|
||||
.container-width-100{
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.incoming-false{
|
||||
margin: 10px 20px 10px 75px;
|
||||
background: var(--chat-incoming-msg-color);
|
||||
float: right;
|
||||
}
|
||||
.title{
|
||||
display: inline;
|
||||
color: var(--title-text-color);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.time{
|
||||
color: #797979;
|
||||
text-align: right;
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.message{
|
||||
.message-attachments{
|
||||
.file{
|
||||
align-items: center;
|
||||
|
||||
.file-details{
|
||||
width: 100%;
|
||||
|
||||
.file-title{
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
.file-title:hover{
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-footer{
|
||||
padding-top: 7.5px;
|
||||
padding-bottom: 7.5px;
|
||||
|
||||
.container{
|
||||
justify-content: center;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.chat-icon-options{
|
||||
display:block !important;
|
||||
font-size: rem(35);
|
||||
float: right !important;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.chat-icon-send{
|
||||
font-size: rem(45);
|
||||
margin: 0 auto;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.type-message{
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
padding-left: 15px;
|
||||
margin: 0 15px 0 75px;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
|
||||
ion-textarea{
|
||||
margin: 0 !important;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-send{
|
||||
padding-right: 20px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.typing {
|
||||
position: relative;
|
||||
top: -25px;
|
||||
height: 0px;
|
||||
left: 0px;
|
||||
margin-left: 22px;
|
||||
display: flex;
|
||||
font-size: rem(12);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.typing ngx-letters-avatar {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.float-status{
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-image{
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.float-status-webtrix {
|
||||
position: relative !important;
|
||||
top: 0px !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-all {
|
||||
font-size: 10pt !important;
|
||||
}
|
||||
|
||||
|
||||
.try {
|
||||
color: red;
|
||||
background: #f3414159;
|
||||
padding: 6px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.dateLabel {
|
||||
background: #ebebeb !important;
|
||||
float: unset !important;
|
||||
margin: 0px auto !important;
|
||||
width: 111px !important;
|
||||
text-align: center;
|
||||
margin-top: 10px !important;
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.lido,
|
||||
.enviado {
|
||||
font-size: rem(11);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
describe('GroupMessagesPage', () => {
|
||||
let component: GroupMessagesPage;
|
||||
let fixture: ComponentFixture<GroupMessagesPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupMessagesPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GroupMessagesPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ContactsPageRoutingModule {}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPageRoutingModule } from './contacts-routing.module';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { FilterPipe } from 'src/app/pipes/filter.pipe';
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ContactsPageRoutingModule,
|
||||
PipesModule,
|
||||
],
|
||||
exports: [ContactsPage],
|
||||
declarations: [ContactsPage]
|
||||
})
|
||||
export class ContactsPageModule {}
|
||||
@@ -1,49 +0,0 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content">
|
||||
<div class="back-icon cursor-pointer" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/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>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<!-- Desktop -->
|
||||
<ion-label class="title">Nova Conversa</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" debounce="500" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<!-- <ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar> -->
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<div class="main-content">
|
||||
<ion-progress-bar class="position-absolute" type="indeterminate" *ngIf="loading"></ion-progress-bar>
|
||||
<ion-virtual-scroll [items]="userList" approxItemHeight="70px" [headerFn]="separateLetter">
|
||||
|
||||
<div class="item-divider" *virtualHeader="let header">
|
||||
<ion-label>{{ header }}</ion-label>
|
||||
</div>
|
||||
|
||||
<div (click)="openMessagesPage(user.wxFullName, user.wxUserId)" *virtualItem="let user" class="item-user cursor-pointer">
|
||||
<p>{{ user.wxFullName }}</p>
|
||||
<span class="icon">
|
||||
<ion-icon [class]="user.status" slot="end" name="ellipse"></ion-icon>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</ion-virtual-scroll>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
@@ -1,136 +0,0 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
height: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
/* border: 1px solid green; */
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: hidden;
|
||||
--icon-color:var( --font-awesome);
|
||||
}
|
||||
|
||||
}
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.main-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 0 0 0 0;
|
||||
overflow:auto;
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-user{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-user p{
|
||||
display: block;
|
||||
margin: 0 !important;
|
||||
width: 90%;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
.item-user .icon{
|
||||
width: 10%;
|
||||
font-size: rem(10);
|
||||
display: block;
|
||||
text-align: right;
|
||||
overflow: auto;
|
||||
}
|
||||
.online{
|
||||
color:#99e47b;
|
||||
}
|
||||
.offline{
|
||||
color:#cbced1;
|
||||
}
|
||||
.away{
|
||||
color:#ffd21f;
|
||||
}
|
||||
.invisible{
|
||||
color:#cbced1;
|
||||
}
|
||||
.busy{
|
||||
color:#f5455c;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
describe('ContactsPage', () => {
|
||||
let component: ContactsPage;
|
||||
let fixture: ComponentFixture<ContactsPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContactsPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ContactsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,203 +0,0 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { MessagesPage } from '../messages.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service'
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { ContactRepositoryService } from 'src/app/services/Repositorys/contacts/repository/contacts-repository.service';
|
||||
import { UserContacts } from 'src/app/services/Repositorys/contacts/data-source/contacts-data-source.service';
|
||||
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.service'
|
||||
|
||||
|
||||
class UserToSelect {
|
||||
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
templateUrl: './contacts.page.html',
|
||||
styleUrls: ['./contacts.page.scss'],
|
||||
})
|
||||
export class ContactsPage implements OnInit {
|
||||
loggedUser: any;
|
||||
|
||||
headers: HttpHeaders;
|
||||
options: any;
|
||||
textSearch: string;
|
||||
room: any;
|
||||
dm: any;
|
||||
sessionStore = SessionStore
|
||||
loading = false
|
||||
@Input() roomId: string;
|
||||
|
||||
@Output() openMessage: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() emptyTextDescriptionOpen: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() backToChat: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() closeAllDesktopComponents: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
userList: UserContacts[];
|
||||
originalUserList: any[] = [];
|
||||
|
||||
CoolList = []
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
public ThemeService: ThemeService,
|
||||
// public ChatSystemService: ChatSystemService,
|
||||
private contactsRepositoryService: ContactRepositoryService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
private toastService: ToastService,
|
||||
private ChatServiceService: ChatServiceService
|
||||
) {
|
||||
this.loggedUser = SessionStore.user.ChatData['data'];
|
||||
this.textSearch = "";
|
||||
this.dm = null;
|
||||
this.room = null;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.textSearch = event.detail.value.toLowerCase();
|
||||
this.userList = this.originalUserList.filter((e) => {
|
||||
const username = e.wxFullName.toLowerCase();
|
||||
return username.includes(this.textSearch);
|
||||
});
|
||||
|
||||
this.userList.sort((a, b) => a.wxFullName.toLowerCase().localeCompare(b.wxFullName.toLowerCase()));
|
||||
}
|
||||
|
||||
openMessagesPage(username: string, wxUserId: number) {
|
||||
this.createRoom(username, wxUserId);
|
||||
/* if (window.innerWidth < 701) {
|
||||
this.createRoom(username);
|
||||
}
|
||||
else {
|
||||
let body = {
|
||||
username: username,
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
this.chatService.createRoom(body).subscribe(res => {
|
||||
this.room = res['room'];
|
||||
|
||||
this.ChatSystemService.getAllRooms(() => {
|
||||
this.openMessage.emit(this.room._id);
|
||||
|
||||
this.loading = false
|
||||
}, this.room._id);
|
||||
|
||||
}, () => {
|
||||
this.loading = false
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
async loadUsers() {
|
||||
try {
|
||||
let users = await this.contactsRepositoryService.getUsers();
|
||||
if (users.isOk()) {
|
||||
const userData = users.value.data.result;
|
||||
console.log(userData)
|
||||
this.originalUserList = userData;
|
||||
this.userList = [...this.originalUserList];
|
||||
this.userList.sort((a, b) => a.wxFullName.toLowerCase().localeCompare(b.wxFullName.toLowerCase()));
|
||||
console.log('User data loaded successfully:', this.originalUserList);
|
||||
} else {
|
||||
console.error('Failed to fetch users:', users.error);
|
||||
}
|
||||
this.loading = false;
|
||||
} catch (error) {
|
||||
console.error('Error loading users', error);
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
separateLetter(record, recordIndex, records) {
|
||||
const normalize = (str) => str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
|
||||
if (recordIndex == 0) {
|
||||
return normalize(record.wxFullName[0]).toUpperCase();
|
||||
}
|
||||
|
||||
let firstPrev = normalize(records[recordIndex - 1].wxFullName[0]).toUpperCase();
|
||||
let firstCurrent = normalize(record.wxFullName[0]).toUpperCase();
|
||||
|
||||
if (firstPrev !== firstCurrent) {
|
||||
return firstCurrent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
doRefresh(event) {
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.roomId) {
|
||||
this.backToChat.emit({ roomId: this.roomId });
|
||||
} else {
|
||||
this.closeAllDesktopComponents.emit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clicked() {
|
||||
|
||||
}
|
||||
|
||||
async createRoom(username: string, wxUserId: number) {
|
||||
const result = await this.ChatServiceService.createRoom({
|
||||
roomName: username,
|
||||
createdBy: SessionStore.user.UserId,
|
||||
roomType: 0,
|
||||
expirationDate: null,
|
||||
members: [wxUserId]
|
||||
})
|
||||
|
||||
|
||||
console.log(result)
|
||||
|
||||
if(result.isOk()) {
|
||||
await this.ChatServiceService.getRoomById(result.value.id);
|
||||
this.openMessage.emit(result.value.id);
|
||||
|
||||
} else if(result.error instanceof HttpErrorResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(result.error)
|
||||
} else {
|
||||
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.chatService.createRoom(body).subscribe(res => {
|
||||
|
||||
this.room = res['room'];
|
||||
this.openMessagesModal(this.room._id);
|
||||
this.ChatSystemService.getAllRooms()
|
||||
}); */
|
||||
}
|
||||
|
||||
async openMessagesModal(roomId: any) {
|
||||
|
||||
|
||||
|
||||
const modal = await this.modalController.create({
|
||||
component: MessagesPage,
|
||||
cssClass: 'modal modal-desktop isMessagesChatOpened',
|
||||
componentProps: {
|
||||
roomId: roomId,
|
||||
},
|
||||
});
|
||||
|
||||
modal.onDidDismiss();
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -7,9 +7,10 @@ const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: MessagesPage
|
||||
},
{
|
||||
},
|
||||
{
|
||||
path: 'contacts',
|
||||
loadChildren: () => import('./contacts/contacts.module').then( m => m.ContactsPageModule)
|
||||
loadChildren: () => import('../contacts/contacts.module').then( m => m.ContactsPageModule)
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<!-- <button (click)="ChatMessageDebuggingPage()">Dev</button> -->
|
||||
<span *ngIf="roomStatus$ | async as roomStatus"><ion-icon *ngIf="roomStatus" class="online" name="ellipse"></ion-icon></span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="right" *ngIf="roomType == RoomTypeEnum.Group">
|
||||
<button title="Menu" class="btn-no-color" (click)="_openMessagesOptions()" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " src="assets/images/theme/blue/icons-menu.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " src="assets/images/theme/gov/icons-menu.svg">
|
||||
|
||||
@@ -223,7 +223,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
|
||||
setTimeout(() => {
|
||||
this.subscribeToChanges()
|
||||
}, 500)
|
||||
}, 500);
|
||||
|
||||
})
|
||||
}
|
||||
@@ -243,6 +243,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
|
||||
subscribeToChanges() {
|
||||
|
||||
this.listenToIncomingMessage();
|
||||
this.listenToDeleteMessage();
|
||||
this.listenToUpdateMessage();
|
||||
@@ -281,7 +282,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
|
||||
removeBold() {
|
||||
if(!this.room?.local) {
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.room.$id})
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.room.id})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +330,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
this.date = {}
|
||||
const allMessage = [];
|
||||
|
||||
console.time("mappingTime");
|
||||
//console.time("mappingTime");
|
||||
const sortMessages = messages.value.sort((a, b) => new Date(a.sentAt).getTime() - new Date(b.sentAt).getTime())
|
||||
|
||||
for(const message of sortMessages) {
|
||||
@@ -342,12 +343,10 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
|
||||
allMessage.push(new MessageViewModal(message))
|
||||
}
|
||||
console.timeEnd("mappingTime");
|
||||
//console.timeEnd("mappingTime");
|
||||
this.messages1[this.room.$id]
|
||||
this.messages1[this.room.$id] = allMessage
|
||||
|
||||
|
||||
|
||||
// if(messages.length >= 1) {
|
||||
// this.messages1[this.room.$id].push(LastMessage)
|
||||
// }
|
||||
@@ -451,7 +450,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
roomId: this.room.id
|
||||
})
|
||||
} else {
|
||||
console.log('no need', message )
|
||||
// console.log('no need', message )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -491,7 +490,12 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
}
|
||||
}
|
||||
|
||||
//this.sendReadMessage()
|
||||
this.chatServiceService.sendReadAt({
|
||||
memberId: SessionStore.user.UserId,
|
||||
messageId: message.id,
|
||||
requestId: '',
|
||||
roomId: this.room.id
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
this.scrollToBottomClicked()
|
||||
@@ -535,7 +539,7 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
listenToUpdateMessage() {
|
||||
this.messageUpdateSubject?.unsubscribe();
|
||||
|
||||
console.log('liste to update')
|
||||
// console.log('liste to update')
|
||||
this.messageUpdateSubject = this.chatServiceService.listenToUpdateMessage(this.room.id).subscribe((updateMessage) => {
|
||||
|
||||
const index = this.messages1[this.room.$id].findIndex(e => e?.id === updateMessage.id); // Use triple equals for comparison
|
||||
@@ -829,14 +833,14 @@ export class MessagesPage implements OnInit, OnChanges, AfterViewInit, OnDestroy
|
||||
if(message.isOk() && this.room.local == IDBoolean.true) {
|
||||
this.room.local = IDBoolean.false;
|
||||
|
||||
// console.log('enter')
|
||||
// await this.chatServiceService.roomSetLocalToFalseById({
|
||||
// $roomId: this.room.$id,
|
||||
// roomId: message.value.roomId
|
||||
// })
|
||||
console.log('enter')
|
||||
await this.chatServiceService.roomSetLocalToFalseById({
|
||||
$roomId: this.room.$id,
|
||||
roomId: message.value.roomId
|
||||
})
|
||||
|
||||
this.room.id = message.value.roomId
|
||||
// this.subscribeToChanges()
|
||||
this.subscribeToChanges()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatDebuggingPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatDebuggingPageRoutingModule {}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatDebuggingPageRoutingModule } from './chat-debugging-routing.module';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatDebuggingPageRoutingModule
|
||||
],
|
||||
declarations: [ChatDebuggingPage]
|
||||
})
|
||||
export class ChatDebuggingPageModule {}
|
||||
@@ -1,9 +0,0 @@
|
||||
<!-- <ion-content>
|
||||
<ul>
|
||||
<li>Chat login</li>
|
||||
<li>Chat user list {{ ChatSystemService.users | json }}</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li *ngFor="let room of ChatSystemService._dm">chat Name: {{room.name}}; subcribe: {{room.status.receive.message}}; </li>
|
||||
</ul>
|
||||
</ion-content> -->
|
||||
@@ -1,24 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatDebuggingPage } from './chat-debugging.page';
|
||||
|
||||
describe('ChatDebuggingPage', () => {
|
||||
let component: ChatDebuggingPage;
|
||||
let fixture: ComponentFixture<ChatDebuggingPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatDebuggingPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatDebuggingPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-debugging',
|
||||
templateUrl: './chat-debugging.page.html',
|
||||
styleUrls: ['./chat-debugging.page.scss'],
|
||||
})
|
||||
export class ChatDebuggingPage implements OnInit {
|
||||
|
||||
constructor(
|
||||
// public ChatSystemService: ChatSystemService
|
||||
) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ChatMessageDebuggingPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ChatMessageDebuggingPageRoutingModule {}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatMessageDebuggingPageRoutingModule } from './chat-message-debugging-routing.module';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ChatMessageDebuggingPageRoutingModule
|
||||
],
|
||||
declarations: [ChatMessageDebuggingPage]
|
||||
})
|
||||
export class ChatMessageDebuggingPageModule {}
|
||||
@@ -1,10 +0,0 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>chatMessageDebugging</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<button (click)="loadHistory()">Load History</button>
|
||||
</ion-content>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ChatMessageDebuggingPage } from './chat-message-debugging.page';
|
||||
|
||||
describe('ChatMessageDebuggingPage', () => {
|
||||
let component: ChatMessageDebuggingPage;
|
||||
let fixture: ComponentFixture<ChatMessageDebuggingPage>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChatMessageDebuggingPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ChatMessageDebuggingPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NavParams } from '@ionic/angular';
|
||||
// import { ChatSystemService } from 'src/app/services/chat/chat-system.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-chat-message-debugging',
|
||||
templateUrl: './chat-message-debugging.page.html',
|
||||
styleUrls: ['./chat-message-debugging.page.scss'],
|
||||
})
|
||||
export class ChatMessageDebuggingPage implements OnInit {
|
||||
|
||||
roomId: string
|
||||
|
||||
constructor(
|
||||
// public ChatSystemService: ChatSystemService,
|
||||
private navParams: NavParams
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.roomId = this.navParams.get('roomId')
|
||||
|
||||
|
||||
}
|
||||
|
||||
loadHistory() {
|
||||
// this.ChatSystemService.getDmRoom(this.roomId).loadHistory({});
|
||||
}
|
||||
|
||||
}
|
||||
+1
-11
@@ -85,11 +85,8 @@ export class GroupContactsPage implements OnInit {
|
||||
async loadUsers() {
|
||||
|
||||
const getallChatUsers = await this.contactsRepositoryService.getUsers()
|
||||
const getRoomById = await this.chatServiceService.getRoomById(this.roomId)
|
||||
|
||||
console.log({getallChatUsers, getRoomById})
|
||||
|
||||
if(getallChatUsers.isOk() && getRoomById.isOk()) {
|
||||
if(getallChatUsers.isOk()) {
|
||||
|
||||
this.allChatUsers = getallChatUsers.value.data.result.sort((a,b) => {
|
||||
if(a.wxFullName < b.wxFullName) {
|
||||
@@ -133,15 +130,8 @@ export class GroupContactsPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (getRoomById.isErr() && getRoomById.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() && getallChatUsers.error instanceof HttpResponse) {
|
||||
this.httpErrorHandle.httpStatusHandle(getallChatUsers.error)
|
||||
} else if (getRoomById.isErr() ) {
|
||||
console.log(getRoomById.error)
|
||||
} else if (getallChatUsers.isErr() ) {
|
||||
console.log(getallChatUsers.error)
|
||||
} else {
|
||||
this.toastService._badRequest("Pedimos desculpa mas não foi possível executar a acção. Por favor, contacte o apoio técnico.")
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: GroupMessagesPage
|
||||
},
{
|
||||
path: 'group-contacts',
|
||||
loadChildren: () => import('./group-contacts/group-contacts.module').then( m => m.GroupContactsPageModule)
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class GroupMessagesPageRoutingModule {}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPageRoutingModule } from './group-messages-routing.module';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
import { BtnModalDismissPageModule } from 'src/app/shared/btn-modal-dismiss/btn-modal-dismiss.module';
|
||||
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
import { LettersAvatarModule } from "ngx-letters-avatar";
|
||||
import { PipesModule } from 'src/app/pipes/pipes.module';
|
||||
import { ChatPopoverPageModule } from '../chat-popover/chat-popover.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
FontAwesomeModule,
|
||||
IonicModule,
|
||||
GroupMessagesPageRoutingModule,
|
||||
ChatPopoverPageModule,
|
||||
BtnModalDismissPageModule,
|
||||
LettersAvatarModule,
|
||||
PipesModule,
|
||||
/* ImageCropperModule,
|
||||
AngularCropperjsModule */
|
||||
|
||||
],
|
||||
declarations: [GroupMessagesPage]
|
||||
})
|
||||
export class GroupMessagesPageModule {}
|
||||
@@ -1,441 +0,0 @@
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar {
|
||||
--background: transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header {
|
||||
width: 100%;
|
||||
/* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color: #000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.header-top {
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
background: #fff;
|
||||
|
||||
.left {
|
||||
width: fit-content;
|
||||
float: left;
|
||||
//font-size: rem(35);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.middle-container {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
height: auto;
|
||||
width: calc(100% - 47px);
|
||||
float: left;
|
||||
|
||||
/* white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important; */
|
||||
|
||||
.middle {
|
||||
width: 100%;
|
||||
padding: 0 !important;
|
||||
margin: 0 0 0 10px;
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
|
||||
.middle-container-options {
|
||||
padding: 0 !important;
|
||||
float: left;
|
||||
width: calc(100% - 67px);
|
||||
text-align: right;
|
||||
|
||||
.middle-container-options-icons {
|
||||
color: #0782c9;
|
||||
font-size: rem(23);
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
padding: 0 !important;
|
||||
float: right;
|
||||
font-size: rem(25);
|
||||
color: #0782c9;
|
||||
}
|
||||
|
||||
.header-top-btn {
|
||||
background: transparent;
|
||||
font-size: rem(25) !important;
|
||||
font-weight: 100 !important;
|
||||
/* color: #0782c9; */
|
||||
color: #42b9fe;
|
||||
padding: 0 5px 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-bottom {
|
||||
padding-left: 10px;
|
||||
overflow: auto;
|
||||
margin: 0 auto;
|
||||
|
||||
.header-bottom-icon {
|
||||
width: rem(30);
|
||||
font-size: rem(25);
|
||||
float: left;
|
||||
padding: 2px;
|
||||
|
||||
}
|
||||
|
||||
.header-bottom-contacts {
|
||||
width: calc(100% - 40px);
|
||||
font-size: rem(15);
|
||||
color: #797979;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
float: left;
|
||||
padding: 5px;
|
||||
margin: 1px;
|
||||
|
||||
.contacts-list {
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.div-icon {
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.div-icon ion-icon {
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ion-content {
|
||||
.welcome-text {
|
||||
/* width: 322px; */
|
||||
width: em(422px);
|
||||
background: #ebebeb;
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #797979;
|
||||
padding: 10px;
|
||||
margin: 0 auto !important;
|
||||
line-height: 1.2rem;
|
||||
// margin: 20px 39px 25px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
height: auto;
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.info-text-leave {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
padding: 10px;
|
||||
background: #e0e9ee;
|
||||
border-radius: 8px;
|
||||
margin: 10px auto;
|
||||
color: #797979 !important;
|
||||
font-size: rem(13) !important;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
|
||||
.info-text-leave ion-label {
|
||||
font-size: rem(13) !important;
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.messages {
|
||||
font-size: rem(13);
|
||||
font-family: Roboto;
|
||||
overflow: auto;
|
||||
|
||||
//set scroll do bottom
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
word-wrap: break-word;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.messages-list-item-wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.messages-list-item-wrapper-active {
|
||||
background: #e6f6ff75 !important;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
//border: 1px solid red;
|
||||
}
|
||||
|
||||
|
||||
.incoming-true,
|
||||
.incoming-false {
|
||||
width: 305px;
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.incoming-true {
|
||||
margin: 10px 35px 10px 20px;
|
||||
background: #ebebeb;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.incoming-false {
|
||||
margin: 10px 20px 10px 35px;
|
||||
background: var(--chat-incoming-msg-color);
|
||||
float: right;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--title-text-color);
|
||||
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.time {
|
||||
color: #797979;
|
||||
text-align: right;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.online {
|
||||
color: #99e47b !important;
|
||||
}
|
||||
|
||||
.offline {
|
||||
color: #cbced1 !important;
|
||||
}
|
||||
|
||||
.away {
|
||||
color: #ffd21f !important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
color: #cbced1 !important;
|
||||
}
|
||||
|
||||
.busy {
|
||||
color: #f5455c !important;
|
||||
}
|
||||
}
|
||||
|
||||
.info-meeting {
|
||||
/* width: 322px; */
|
||||
width: em(422);
|
||||
background: var(--chat-alert-msg-color);
|
||||
text-align: center;
|
||||
font-size: rem(13);
|
||||
color: #262420;
|
||||
padding: 10px;
|
||||
margin: 10px auto;
|
||||
line-height: 1.2rem;
|
||||
/* margin: 15px 0px 15px 0px; */
|
||||
border-radius: 8px;
|
||||
|
||||
.info-meeting-small {
|
||||
font-size: rem(10);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.info-meeting-medium {
|
||||
font-size: rem(12);
|
||||
}
|
||||
|
||||
.info-meeting-normal {
|
||||
color: #0782c9;
|
||||
font-weight: 700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.info-meeting-normal:hover {
|
||||
text-decoration: underline;
|
||||
color: #0782c9;
|
||||
}
|
||||
}
|
||||
|
||||
ion-footer {
|
||||
padding-top: 7.5px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.container {
|
||||
justify-content: center;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
|
||||
.message-box {
|
||||
margin: 0 5px 0 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.chat-icon-options {
|
||||
display: block !important;
|
||||
font-size: rem(35);
|
||||
float: right !important;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.chat-icon-send {
|
||||
font-size: rem(40);
|
||||
margin: 0 auto;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.type-message {
|
||||
display: flex;
|
||||
border: 1px solid #ebebeb;
|
||||
border-radius: 25px;
|
||||
padding-left: 15px;
|
||||
align-items: center;
|
||||
|
||||
overflow: auto;
|
||||
|
||||
ion-textarea {
|
||||
margin: 0 !important;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.preview-slides {
|
||||
margin-top: 20%;
|
||||
background: #e6e6e6;
|
||||
|
||||
img {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.transparent-modal {
|
||||
.modal-wrapper {
|
||||
--background: rgba(44, 39, 45, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.image-slide,
|
||||
.image-card {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.image-card {
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
height: 200%;
|
||||
width: 100%;
|
||||
background: black;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
|
||||
.typing {
|
||||
position: relative;
|
||||
top: -25px;
|
||||
height: 0px;
|
||||
left: 0px;
|
||||
margin-left: 22px;
|
||||
display: flex;
|
||||
font-size: rem(12);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.typing ngx-letters-avatar {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.float-status {
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-image {
|
||||
position: relative !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.float-status-webtrix {
|
||||
position: relative !important;
|
||||
top: 0px !important;
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: self-end;
|
||||
}
|
||||
|
||||
.float-status-all {
|
||||
font-size: rem(13) !important;
|
||||
}
|
||||
|
||||
.try {
|
||||
color: red;
|
||||
background: #f3414159;
|
||||
padding: 6px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.font-40-rem {
|
||||
font-size: 2.5rem !important;
|
||||
}
|
||||
|
||||
|
||||
.dateLabel {
|
||||
background: #ebebeb !important;
|
||||
float: unset !important;
|
||||
margin: 0px auto !important;
|
||||
width: 111px;
|
||||
text-align: center;
|
||||
margin-top: 10px !important;
|
||||
padding: 15px 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { GroupMessagesPage } from './group-messages.page';
|
||||
|
||||
describe('GroupMessagesPage', () => {
|
||||
let component: GroupMessagesPage;
|
||||
let fixture: ComponentFixture<GroupMessagesPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ GroupMessagesPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GroupMessagesPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -161,7 +161,7 @@ export class ContactsPage implements OnInit {
|
||||
|
||||
|
||||
close() {
|
||||
this.modalController.dismiss({});
|
||||
this.modalController.dismiss(null);
|
||||
}
|
||||
|
||||
async select(user: UserContacts) {
|
||||
|
||||
@@ -44,9 +44,9 @@ import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
|
||||
import { FileSystemMobileService } from 'src/app/infra/file-system/mobile/file-system-mobile.service';
|
||||
import { RoomViewModel } from '../../store/model/room';
|
||||
import { RoomStore } from '../../store/roomStore'
|
||||
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-messages/group-contacts/group-contacts.page';
|
||||
import { EditGroupPage } from '../edit-group/edit-group.page';
|
||||
import { imageMimeTypes } from 'src/app/utils/allowedImageExtension';
|
||||
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-contacts/group-contacts.page';
|
||||
|
||||
const IMAGE_DIR = 'stored-images';
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: ContactsPage
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ContactsPageRoutingModule {}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPageRoutingModule } from './contacts-routing.module';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
|
||||
import { BtnSeguintePageModule } from 'src/app/shared/btn-seguinte/btn-seguinte.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
|
||||
ContactsPageRoutingModule,
|
||||
BtnSeguintePageModule,
|
||||
],
|
||||
declarations: [ContactsPage]
|
||||
})
|
||||
export class ContactsPageModule {}
|
||||
@@ -1,57 +0,0 @@
|
||||
<ion-header class="ion-no-border">
|
||||
<ion-toolbar class="header-toolbar">
|
||||
<div class="main-header">
|
||||
<div class="title-content width-100">
|
||||
<div class="back-icon">
|
||||
<button class="btn-no-color cursor-pointer" (click)="close()">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " slot="end" src='assets/images/icons-arrow-arrow-left.svg'></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " src="assets/images/theme/doneIt/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>
|
||||
</button>
|
||||
</div>
|
||||
<div class="div-title">
|
||||
<ion-label class="title">Contactos</ion-label>
|
||||
</div>
|
||||
<app-btn-seguinte (click)="groupMessages()" class="cursor-pointer"></app-btn-seguinte>
|
||||
</div>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar class="toolbar-search">
|
||||
<div class="search">
|
||||
<ion-searchbar search-icon="undefined" (ionChange)="onChange($event)" placeholder="Pesquisar por contacto" ></ion-searchbar>
|
||||
</div>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-refresher name="refresher" slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-progress-bar type="indeterminate" *ngIf="showLoader"></ion-progress-bar>
|
||||
<ion-refresher-content>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<div class="main-content">
|
||||
|
||||
<!-- <ion-list>
|
||||
<ion-item *ngFor="let user of searchedItem">
|
||||
{{user.name}}
|
||||
</ion-item>
|
||||
</ion-list> -->
|
||||
|
||||
<ion-virtual-scroll [items]="users" approxItemHeight="70px" [headerFn]="separateLetter">
|
||||
|
||||
<div class="item-divider" *virtualHeader="let header">
|
||||
<ion-label>{{header}}</ion-label>
|
||||
</div>
|
||||
|
||||
<div *virtualItem="let user" class="item-checkbox">
|
||||
<ion-checkbox color="primary"></ion-checkbox>
|
||||
<p>{{user.first}} {{user.last}}</p>
|
||||
<ion-icon name="ellipse"></ion-icon>
|
||||
</div>
|
||||
|
||||
</ion-virtual-scroll>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
|
||||
@import '~src/function.scss';
|
||||
|
||||
.header-toolbar{
|
||||
--background:transparent;
|
||||
--opacity: 1;
|
||||
|
||||
.main-header{
|
||||
width: 100%; /* 400px */
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
border-top-left-radius: 25px;
|
||||
border-top-right-radius: 25px;
|
||||
background-color: #fff;
|
||||
overflow:hidden;
|
||||
padding: 30px 20px 0px 20px;
|
||||
color:#000;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
.div-icon{
|
||||
width: rem(40);
|
||||
float: right;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
.div-icon ion-icon{
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.title-content{
|
||||
margin: 0px auto;
|
||||
overflow: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.back-icon{
|
||||
width: 37px;
|
||||
float: left;
|
||||
font-size: rem(35);
|
||||
overflow: auto;
|
||||
|
||||
}
|
||||
.div-title{
|
||||
width: 221px;
|
||||
padding: 0!important;
|
||||
float: left;
|
||||
margin: 2.5px 0 0 5px;
|
||||
}
|
||||
.title{
|
||||
font-size: rem(25);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-search{
|
||||
--padding-top:0 !important;
|
||||
--padding-bottom:0 !important;
|
||||
--padding-start:0 !important;
|
||||
--padding-end:0 !important;
|
||||
|
||||
.search{
|
||||
border: 1px solid #ebebeb;
|
||||
margin: 5px 20px 5px 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.search ion-searchbar{
|
||||
/* border: 1px solid green; */
|
||||
width: 100%;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
--border-radius: 5px;
|
||||
--box-shadow: none;
|
||||
overflow: auto;
|
||||
--icon-color:var(--title-text-color);
|
||||
}
|
||||
|
||||
}
|
||||
ion-content{
|
||||
--background:transparent;
|
||||
}
|
||||
.main-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: Roboto;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
overflow:auto;
|
||||
padding: 0 0 0 0;
|
||||
|
||||
.item-divider{
|
||||
background: #ebebeb;
|
||||
font-size: rem(15);
|
||||
margin: 10px 0 10px 0;
|
||||
padding:5px 0 5px 20px;
|
||||
|
||||
}
|
||||
|
||||
.item-checkbox{
|
||||
display: flex;
|
||||
margin: 10px 20px 10px 20px !important;
|
||||
overflow: auto;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.item-checkbox ion-checkbox{
|
||||
--border-color: var(--title-text-color);
|
||||
--background-checked:var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.item-checkbox p{
|
||||
display: block;
|
||||
margin: 0 !important;
|
||||
width: 330px;
|
||||
padding-left: 10px;
|
||||
font-size: rem(15);
|
||||
color: var(--title-text-color);
|
||||
float: left;
|
||||
}
|
||||
.item-checkbox ion-icon{
|
||||
font-size: rem(10);
|
||||
float: left;
|
||||
color:#99e47b;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { ContactsPage } from './contacts.page';
|
||||
|
||||
describe('ContactsPage', () => {
|
||||
let component: ContactsPage;
|
||||
let fixture: ComponentFixture<ContactsPage>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ContactsPage ],
|
||||
imports: [IonicModule.forRoot()]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ContactsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,120 +0,0 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalController } from '@ionic/angular';
|
||||
import { GroupMessagesPage } from '../../group-messages/group-messages.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
templateUrl: './contacts.page.html',
|
||||
styleUrls: ['./contacts.page.scss'],
|
||||
})
|
||||
export class ContactsPage implements OnInit {
|
||||
showLoader: boolean;
|
||||
users = [];
|
||||
|
||||
contact: string[] = [" Ana M.", "Andre F.", "Bruno G.", "Catarina T", "Tiago"];
|
||||
|
||||
headers: HttpHeaders;
|
||||
options:any;
|
||||
|
||||
contacts = [
|
||||
{
|
||||
first: 'Ana',
|
||||
last: 'Manuel',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
},
|
||||
{
|
||||
first: 'Abdullah',
|
||||
last: 'Hill',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
},
|
||||
{
|
||||
first: 'Batur',
|
||||
last: 'Oymen',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
},
|
||||
{
|
||||
first: 'Bianca',
|
||||
last: 'Costa',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
},
|
||||
{
|
||||
first: 'Zaya',
|
||||
last: 'Mary',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
},
|
||||
{
|
||||
first: 'Tiago',
|
||||
last: 'Kayaya',
|
||||
url: 'https://randomuser.me/api/portraits/med/women/54.jpg',
|
||||
}
|
||||
];
|
||||
|
||||
constructor(
|
||||
private modalController: ModalController,
|
||||
public ThemeService: ThemeService
|
||||
)
|
||||
{ }
|
||||
|
||||
ngOnInit() {
|
||||
this.loadUsers();
|
||||
|
||||
}
|
||||
|
||||
loadUsers(){
|
||||
|
||||
this.users = this.contacts.sort((a,b) => {
|
||||
if(a.first < b.first){
|
||||
return -1;
|
||||
}
|
||||
if(a.first > b.first){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
separateLetter(record, recordIndex, records){
|
||||
|
||||
if(recordIndex == 0){
|
||||
return record.first[0];
|
||||
}
|
||||
|
||||
let first_prev = records[recordIndex - 1].first[0];
|
||||
let first_current = record.first[0];
|
||||
|
||||
if(first_prev != first_current){
|
||||
return first_current;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
doRefresh(event){
|
||||
|
||||
}
|
||||
close(){
|
||||
this.modalController.dismiss();
|
||||
}
|
||||
onChange(event){
|
||||
|
||||
}
|
||||
clicked(){
|
||||
|
||||
|
||||
}
|
||||
async groupMessages(){
|
||||
const modal = await this.modalController.create({
|
||||
component: GroupMessagesPage,
|
||||
componentProps: {},
|
||||
cssClass: 'contacts',
|
||||
backdropDismiss: false
|
||||
});
|
||||
|
||||
|
||||
|
||||
modal.onDidDismiss();
|
||||
await modal.present();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,10 +7,6 @@ const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: NewGroupPage
|
||||
},
|
||||
{
|
||||
path: 'contacts',
|
||||
loadChildren: () => import('./contacts/contacts.module').then( m => m.ContactsPageModule)
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ModalController, NavParams, PickerController, PopoverController } from '@ionic/angular';
|
||||
import { GroupDurationPage } from 'src/app/shared/popover/group-duration/group-duration.page';
|
||||
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-messages/group-contacts/group-contacts.page';
|
||||
import { ThemeService } from 'src/app/services/theme.service';
|
||||
import { SessionStore } from 'src/app/store/session.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
@@ -10,6 +9,7 @@ import { ChatServiceService } from 'src/app/module/chat/domain/chat-service.serv
|
||||
import { UDate } from 'src/app/utils/date';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { z } from 'zod';
|
||||
import { GroupContactsPage, IGroupContactsPageOutPutSchema } from '../group-contacts/group-contacts.page';
|
||||
|
||||
|
||||
const NewGroupModalOutPutSchema = z.object({
|
||||
@@ -25,7 +25,8 @@ export type INewGroupModalOutPut = z.infer<typeof NewGroupModalOutPutSchema>
|
||||
export class NewGroupPage implements OnInit {
|
||||
isGroupCreated: boolean;
|
||||
showLoader: boolean;
|
||||
displayDuration: any;
|
||||
expirationDate: Date = null;
|
||||
displayDuration = ''
|
||||
showDuration: boolean;
|
||||
selectedDuration = ['', '', ''];
|
||||
thedate: any;
|
||||
@@ -70,7 +71,7 @@ export class NewGroupPage implements OnInit {
|
||||
roomName: this.groupName,
|
||||
createdBy: SessionStore.user.UserId,
|
||||
roomType: 0,
|
||||
expirationDate: this.displayDuration?.toISOString() ? UDate.GetDateWithTimeZone(this.displayDuration) : null,
|
||||
expirationDate: this.expirationDate?.toISOString() ? UDate.GetDateWithTimeZone(this.expirationDate) : null,
|
||||
members: []
|
||||
})
|
||||
|
||||
@@ -133,7 +134,7 @@ export class NewGroupPage implements OnInit {
|
||||
handler:(value:any)=>{
|
||||
|
||||
let now = new Date();
|
||||
this.thedate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + value.days.value, now.getHours() + value.hours.value, now.getMinutes() + value.minutes.value, now.getSeconds(), now.getMilliseconds());
|
||||
this.expirationDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + value.days.value, now.getHours() + value.hours.value, now.getMinutes() + value.minutes.value, now.getSeconds(), now.getMilliseconds())
|
||||
|
||||
this.selectedDuration = [
|
||||
value.days.value,
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<ion-toolbar>
|
||||
<ion-title class="title" *ngIf="roomData$ | async as roomData"> {{ roomData.roomName }}</ion-title>
|
||||
</ion-toolbar>
|
||||
<div class="btn-close d-flex cursor-pointer pr-20" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon"
|
||||
<div class="btn-close d-flex cursor-pointer pr-20 align-center" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="icon font-30-em"
|
||||
src="assets/images/icons-search-close.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon"
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="icon font-30-em"
|
||||
src="assets/images/theme/gov/icons-search-close.svg"></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="icon"
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="icon font-30-em"
|
||||
src="assets/images/theme/{{ThemeService.currentTheme}}/icons-search-close.svg"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -178,7 +178,7 @@ export class RoomStore {
|
||||
listenToUpdateMessage() {
|
||||
this.messageUpdateSubject?.unsubscribe();
|
||||
|
||||
console.log('liste to update')
|
||||
// console.log('liste to update')
|
||||
this.messageUpdateSubject = this.chatServiceService.listenToUpdateMessage(this.room.id).subscribe((updateMessage) => {
|
||||
|
||||
const index = this.messages1[this.room.$id].findIndex(e => e?.id === updateMessage.id); // Use triple equals for comparison
|
||||
@@ -225,7 +225,12 @@ export class RoomStore {
|
||||
}
|
||||
}
|
||||
|
||||
this.sendReadMessage()
|
||||
this.chatServiceService.sendReadAt({
|
||||
memberId: SessionStore.user.UserId,
|
||||
messageId: message.id,
|
||||
requestId: '',
|
||||
roomId: this.room.id
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
this.scrollToBottomClicked()
|
||||
@@ -241,7 +246,7 @@ export class RoomStore {
|
||||
|
||||
removeBold() {
|
||||
if(!this.room?.local) {
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.room.$id})
|
||||
this.chatServiceService.removeBoldFromRoom({roomId: this.room.id})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +284,7 @@ export class RoomStore {
|
||||
this.date = {}
|
||||
const allMessage = [];
|
||||
|
||||
console.time("mappingTime");
|
||||
//console.time("mappingTime");
|
||||
const sortMessages = messages.value.sort((a, b) => new Date(a.sentAt).getTime() - new Date(b.sentAt).getTime())
|
||||
|
||||
for(const message of sortMessages) {
|
||||
@@ -292,7 +297,7 @@ export class RoomStore {
|
||||
|
||||
allMessage.push(new MessageViewModal(message))
|
||||
}
|
||||
console.timeEnd("mappingTime");
|
||||
//console.timeEnd("mappingTime");
|
||||
this.messages1[this.room.$id]
|
||||
this.messages1[this.room.$id] = allMessage
|
||||
|
||||
@@ -351,7 +356,7 @@ export class RoomStore {
|
||||
roomId: this.room.id
|
||||
})
|
||||
} else {
|
||||
console.log('no need', message )
|
||||
// console.log('no need', message )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -417,14 +422,14 @@ export class RoomStore {
|
||||
if(message.isOk() && this.room.local == IDBoolean.true) {
|
||||
this.room.local = IDBoolean.false;
|
||||
|
||||
// console.log('enter')
|
||||
// await this.chatServiceService.roomSetLocalToFalseById({
|
||||
// $roomId: this.room.$id,
|
||||
// roomId: message.value.roomId
|
||||
// })
|
||||
console.log('enter')
|
||||
await this.chatServiceService.roomSetLocalToFalseById({
|
||||
$roomId: this.room.$id,
|
||||
roomId: message.value.roomId
|
||||
})
|
||||
|
||||
this.room.id = message.value.roomId
|
||||
// this.subscribeToChanges()
|
||||
this.subscribeToChanges()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user