mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 12:37:53 +00:00
add viewer do task details
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
|
||||
## Dev
|
||||
<div class="upper-content" [ngClass]="{'upper-content-no-margin': DeviceService.isDesktop(), 'upper-content-margin': !DeviceService.isDesktop()}">
|
||||
></div>
|
||||
@@ -14,9 +14,6 @@
|
||||
},
|
||||
{
|
||||
"path": "../sih"
|
||||
},
|
||||
{
|
||||
"path": "../Ionic-Video-Capture-Play-main"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { DespachoPage } from './despacho.page';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { TaskDetailsPageModule } from 'src/app/shared/gabinete-digital/generic/task-details/task-details.module'
|
||||
import { ViewerAttachmentPageModule } from '../../viewer-attachment/viewer-attachment.module';
|
||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -19,7 +20,8 @@ import { ViewerAttachmentPageModule } from '../../viewer-attachment/viewer-attac
|
||||
DespachoPageRoutingModule,
|
||||
ViewerAttachmentPageModule,
|
||||
TaskDetailsPageModule,
|
||||
SharedModule
|
||||
SharedModule,
|
||||
FontAwesomeModule,
|
||||
],
|
||||
declarations: [
|
||||
DespachoPage,
|
||||
|
||||
@@ -18,23 +18,113 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upper-content">
|
||||
<div class="content-details">
|
||||
<ion-label>
|
||||
<p><span class="date">{{customDate}}</span></p>
|
||||
</ion-label>
|
||||
<ion-label>
|
||||
<p><span class="color-red">{{ task.DeadlineType }}</span></p>
|
||||
</ion-label>
|
||||
<ion-label>
|
||||
<p class="d-flex mt-10"><span class="label">{{ task.activityInstanceName }}</span></p>
|
||||
</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
<div class="overflow-y-auto height-100" style="margin-right: -20px; margin-left: -20px; overflow: hidden">
|
||||
<app-viewer-attachment class="height-100" ></app-viewer-attachment>
|
||||
<div class="d-flex height-100 width-100">
|
||||
<div class="overflow-y-auto height-100 width-60" style="overflow: hidden; margin-left: -20px; margin-right:20px;" *ngIf="DeviceService.isDesktop()">
|
||||
<!-- <ion-row class="timeline-date align-center pr-10">
|
||||
<button class="no-color" style="
|
||||
position: absolute;
|
||||
background: transparent;
|
||||
margin: 53px;
|
||||
">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-up.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-up.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-up.svg"></ion-icon>
|
||||
</button>
|
||||
|
||||
|
||||
</ion-row> -->
|
||||
<app-viewer-attachment [selectedIndex]="selectedIndex" [taskViewerAttachment]="mergedArray" class="height-100" ></app-viewer-attachment>
|
||||
</div>
|
||||
|
||||
<div class=" flex-1 d-flex flex-column height-100" [ngClass]="{'overflow-y-auto ': DeviceService.isDesktop()}" >
|
||||
<div class="upper-content" [ngClass]="{'upper-content-no-margin': DeviceService.isDesktop(), 'upper-content-margin': !DeviceService.isDesktop()}">
|
||||
<div class="content-details" [ngClass]="{'d-flex': !DeviceService.isDesktop()}">
|
||||
<div [ngClass]="{'flex-1': !DeviceService.isDesktop()}">
|
||||
<ion-label>
|
||||
<p><span class="date">{{customDate}}</span></p>
|
||||
</ion-label>
|
||||
<ion-label>
|
||||
<p><span class="color-red">{{ task.DeadlineType }}</span></p>
|
||||
</ion-label>
|
||||
</div>
|
||||
|
||||
<ion-label>
|
||||
<p class="d-flex mt-10"><span class="label">{{ task.activityInstanceName }}</span></p>
|
||||
</ion-label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
|
||||
<div class="middle-content" *ngIf="dropButton">
|
||||
<h5 *ngIf="intervenientes">Intervenientes</h5>
|
||||
<ion-item class="ion-no-margin ion-no-padding">
|
||||
<ion-label>
|
||||
<div *ngFor="let task of intervenientes">
|
||||
<p>{{task.Name}}</p>
|
||||
</div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<div *ngIf="cc.length > 0">
|
||||
<h5 class="font-17-rem">Com conhecimento</h5>
|
||||
<ion-item class="ion-no-margin ion-no-padding">
|
||||
<ion-label>
|
||||
<div *ngFor="let c of cc">
|
||||
<p>{{c.Name}}</p>
|
||||
</div>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
<div *ngIf="fulltask.workflowInstanceDataFields.TaskMessage">
|
||||
<h5 class="font-17-rem">Detalhes</h5>
|
||||
<ion-item class="ion-no-margin ion-no-padding">
|
||||
<pre class="width-100 text">{{ fulltask.workflowInstanceDataFields.TaskMessage }} </pre>
|
||||
</ion-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="bottom-content width-100 flex-1" [ngClass]="{'expand': !DeviceService.isDesktop()}">
|
||||
<ion-list *ngIf="DeviceService.isDesktop()">
|
||||
<h5 class="font-17-rem">Documentos Anexados</h5>
|
||||
<ion-item class="ion-no-margin ion-no-padding cursor-pointer" *ngFor="let Document of mergedArray; let i = index" (click)="clickDocumentUPdateIndex(i)" [ngClass]="{'selected-card': i === selectedIndex}">
|
||||
<ion-label class="d-block" >
|
||||
<div class="d-flex" >
|
||||
|
||||
<div class="flex-1">
|
||||
<p class="attach-title-item overflow-hidden">{{ Document.Assunto || "Sem assunto" }} <span class="document-type" >Rascunho</span></p>
|
||||
<p class="overflow-hidden"><span class="span-left">{{ Document.Sender}}</span><span class="span-right">{{ Document.DocDate | date: 'dd-MM-yyyy HH:mm' }}</span></p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-center align-center font-25" (click)="clickAttachment()">
|
||||
<fa-icon icon="ellipsis-v" class="menu-icon font-awesome-1"></fa-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<div style="border-radius: 50px;position: relative;top: 3px;left: 50px;">
|
||||
|
||||
<ion-row class="timeline-date align-center pr-10" *ngIf="!DeviceService.isDesktop()">
|
||||
<button class="no-color" *ngIf="dropButton" (click)="dropButton=!dropButton" >
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-up.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-up.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-up.svg"></ion-icon>
|
||||
</button>
|
||||
<button class="no-color" *ngIf="!dropButton" (click)="dropButton=!dropButton">
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'default' " class="collaps font-25" src="assets/images/icons-collaps-down.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'gov' " class="collaps font-25" src="assets/images/theme/gov/icons-collaps-down.svg" ></ion-icon>
|
||||
<ion-icon *ngIf="ThemeService.currentTheme == 'doneIt' " class="collaps font-25" src="assets/images/theme/{{ThemeService.currentTheme}}/icons-collaps-down.svg" ></ion-icon>
|
||||
</button >
|
||||
</ion-row>
|
||||
|
||||
</div>
|
||||
<app-viewer-attachment *ngIf="!DeviceService.isDesktop()" [selectedIndex]="selectedIndex" [taskViewerAttachment]="mergedArray" class="height-100" ></app-viewer-attachment>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -60,10 +60,13 @@ ion-button{
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.upper-content-margin {
|
||||
margin-left: 36px;
|
||||
}
|
||||
|
||||
.upper-content{
|
||||
font-family: Roboto;
|
||||
margin-top: 15px;
|
||||
margin-left: 36px;
|
||||
font-size: rem(18);
|
||||
|
||||
.label{
|
||||
@@ -219,3 +222,18 @@ ion-button{
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.expand {
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
width: calc(100% + 40px);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.selected-card {
|
||||
border: 3px solid #ffb703;
|
||||
color: #3498db;
|
||||
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@ import { RouteService } from 'src/app/services/route.service';
|
||||
import { HttpErrorHandle } from 'src/app/services/http-error-handle.service';
|
||||
import { TaskService } from 'src/app/services/task.service'
|
||||
import { TinyMCEPage } from 'src/app/tiny-mce/tiny-mce.page';
|
||||
|
||||
|
||||
import { DeviceService } from "src/app/services/device.service"
|
||||
@Component({
|
||||
selector: 'app-despacho',
|
||||
templateUrl: './despacho.page.html',
|
||||
@@ -50,6 +49,9 @@ export class DespachoPage implements OnInit {
|
||||
executadoText: string = "Executado";
|
||||
gerarText: string = "Gerar"
|
||||
draftDocumentIds;
|
||||
selectedIndex = 0
|
||||
|
||||
dropButton = false
|
||||
|
||||
|
||||
constructor(private activateRoute: ActivatedRoute,
|
||||
@@ -65,7 +67,8 @@ export class DespachoPage implements OnInit {
|
||||
private backgroundservice: BackgroundService,
|
||||
public ThemeService: ThemeService,
|
||||
private httpErrorHandle: HttpErrorHandle,
|
||||
public TaskService: TaskService
|
||||
public TaskService: TaskService,
|
||||
public DeviceService: DeviceService
|
||||
|
||||
|
||||
) {
|
||||
@@ -245,6 +248,10 @@ export class DespachoPage implements OnInit {
|
||||
|
||||
// }
|
||||
|
||||
clickDocumentUPdateIndex(index) {
|
||||
return this.selectedIndex = index
|
||||
}
|
||||
|
||||
async viewDocument(docId: string, Document, content) {
|
||||
|
||||
if (Document.content == "") {
|
||||
@@ -280,6 +287,11 @@ export class DespachoPage implements OnInit {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
clickAttachment() {
|
||||
|
||||
}
|
||||
|
||||
openMenu() {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const Bodyschema = z.object({
|
||||
SerialNumber: z.string(),
|
||||
DispatchDocId: z.number(),
|
||||
FolderID: z.any(),
|
||||
Subject: z.string(),
|
||||
Comment: z.string().optional(),
|
||||
DelegatedUserEmail: z.string().email(),
|
||||
UserId: z.any(),
|
||||
DraftIds: z.string(),
|
||||
export const ViewerAttachmentParams = z.object({
|
||||
ApplicationId: z.string().optional(),
|
||||
Assunto: z.string({}).nonempty(),
|
||||
DocDate: z.string(),
|
||||
DocId: z.string().nonempty(),
|
||||
DocNumber: z.string(),
|
||||
FolderId: z.string(),
|
||||
Sender: z.string(),
|
||||
SourceDocId: z.string(),
|
||||
content: z.string().nonempty(),
|
||||
path: z.string().nonempty(),
|
||||
ownerId: z.string().nonempty(),
|
||||
status: z.string().nonempty(),
|
||||
})
|
||||
|
||||
export type ViewerAttachment = z.infer<typeof ViewerAttachmentParams>;
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
<div class="height-100 d-flex flex-column overflow-hidden">
|
||||
|
||||
<div class="overflow-x-auto d-flex pa-10" style="background-color: #d9d9d9;">
|
||||
<div class="pa-10 mx-10 card-text selected-card ">
|
||||
<div style="overflow: auto;">
|
||||
Attachment 1 sdhnfjanshdfhnasdhfahsdfja shdf asdf
|
||||
123123
|
||||
<div class="overflow-x-auto d-flex pa-10" style="background-color: #d9d9d9;" *ngIf="!DeviceService.isDesktop()">
|
||||
|
||||
<div *ngFor="let attachment of taskViewerAttachment; let i = index"
|
||||
class="ion-no-margin ion-no-padding cursor-pointer" class="pa-10 mx-10 card-text"
|
||||
[ngClass]="{'selected-card': i === selectedIndex}" (click)="clickDocumentUPdateIndex(i)">
|
||||
<div (click)="clickDocument(attachment)">
|
||||
|
||||
<div *ngIf="attachment.Assunto" class="attach-title-item tex-left">
|
||||
{{ attachment.Assunto }}<span class="document-type" *ngIf="attachment.content != ''">Rascunho</span>
|
||||
<br>
|
||||
{{ attachment.Sender }}
|
||||
<br>
|
||||
{{ attachment.DocDate | date: 'dd/MM/yy' }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="pa-10 mx-10 card-text">
|
||||
<div style="overflow: auto;"s>Attachment 2</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="height-100" >
|
||||
<div #iframeContainer class="height-100" >
|
||||
|
||||
<iframe _ngcontent-lxc-c492="" height="100%" width="100%" title="Iframe Example" class="iframe" src="https://gdviewer-dev.dyndns.info/pdfjs/web/viewpdf.aspx?file=/arq/638429873997432492.pdf&i=MjYxIzgjMTA2IzE3IzEyODA5MSNEb2N1bWVudENlbnRlcg==&e=MA==&p=MA==&m=cGF1bG8ucGludG9AZ2FiaW5ldGVkaWdpdGFsLmxvY2Fs&d=MA==&n=UGF1bG8gUGludG8=&mId=MA==&al=MA==&cn=T0E=&wm=RmFsc2U=&L=MA==&attInstance=MA==&OpenFromMail=MA=="></iframe>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
|
||||
|
||||
.card-text {
|
||||
width: 150px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
max-width: 250px;
|
||||
border: 1px solid #3498db;
|
||||
color: #3498db;
|
||||
background: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
p {
|
||||
|
||||
margin: 0px;
|
||||
@@ -17,6 +18,16 @@
|
||||
|
||||
.selected-card {
|
||||
border: 3px solid #ffb703;
|
||||
color: blue;
|
||||
color: #3498db;
|
||||
|
||||
}
|
||||
|
||||
iframe {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.selected-attachment {
|
||||
border: 2px solid #3498db; /* You can customize the border style and color */
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Component, OnInit, CUSTOM_ELEMENTS_SCHEMA, Input } from '@angular/core';
|
||||
import { Component, OnInit, CUSTOM_ELEMENTS_SCHEMA, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
import { IonicSlides } from '@ionic/angular';
|
||||
|
||||
import { ViewerAttachment, ViewerAttachmentParams } from './prop';
|
||||
import { MiddlewareRepositoryService } from "src/app/shared/repository/middleware/middleware-repository.service"
|
||||
import { DeviceService } from "src/app/services/device.service"
|
||||
@Component({
|
||||
selector: 'app-viewer-attachment',
|
||||
templateUrl: './viewer-attachment.page.html',
|
||||
@@ -8,12 +10,72 @@ import { IonicSlides } from '@ionic/angular';
|
||||
})
|
||||
export class ViewerAttachmentPage implements OnInit {
|
||||
|
||||
@Input() selectedIndex = 0;
|
||||
swiperModules = [IonicSlides];
|
||||
@Input() task: string;
|
||||
@Input() taskViewerAttachment: ViewerAttachment[];
|
||||
viewer: {[key: string]: HTMLDivElement} = {}
|
||||
@ViewChild('iframeContainer') iframeContainer: ElementRef<HTMLDivElement>;
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
public middlewareRepositoryService: MiddlewareRepositoryService,
|
||||
public DeviceService: DeviceService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.validateParams()
|
||||
}
|
||||
|
||||
|
||||
clickDocumentUPdateIndex(index: number) {
|
||||
// Update the selected index
|
||||
this.selectedIndex = index;
|
||||
}
|
||||
|
||||
async clickDocument(viewerAttachment: ViewerAttachment) {
|
||||
const hasIframe = this.iframeContainer.nativeElement.querySelector("iframe")
|
||||
if(hasIframe) {}
|
||||
|
||||
this.iframeContainer.nativeElement.innerHTML = ""
|
||||
this.iframeContainer
|
||||
|
||||
|
||||
const linkRequest = await this.middlewareRepositoryService.getViewerLink({
|
||||
ApplicationId: viewerAttachment.ApplicationId,
|
||||
DocId: viewerAttachment.DocId
|
||||
})
|
||||
|
||||
if(linkRequest.isOk()) {
|
||||
|
||||
// Optionally, you can add new content or recreate the iframe
|
||||
var newIframe = document.createElement('iframe');
|
||||
newIframe.src = linkRequest.value;
|
||||
|
||||
newIframe.width = '100%'
|
||||
newIframe.height = '100%'
|
||||
|
||||
this.iframeContainer.nativeElement.appendChild(newIframe)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
validateParams() {
|
||||
console.log(this.taskViewerAttachment)
|
||||
try {
|
||||
const validatedObjects = this.taskViewerAttachment.map((item, index) => {
|
||||
return ViewerAttachmentParams.parse(item);
|
||||
});
|
||||
|
||||
console.log('Validation successful for all elements:', validatedObjects);
|
||||
} catch (error) {
|
||||
// console.error('Validation failed:', error, this.taskViewerAttachment);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngOnChanges() {
|
||||
this.clickDocumentUPdateIndex(this.selectedIndex)
|
||||
const task = this.taskViewerAttachment[this.selectedIndex]
|
||||
|
||||
this.clickDocument(task)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DeviceService } from './device.service';
|
||||
|
||||
describe('DeviceService', () => {
|
||||
let service: DeviceService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(DeviceService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Platform } from '@ionic/angular';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DeviceService {
|
||||
|
||||
constructor( private platform: Platform,) { }
|
||||
|
||||
|
||||
isTableDivice() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isDesktop() {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -182,4 +182,19 @@ export class MiddlewareServiceService {
|
||||
|
||||
return this.http.post<IuploadFileLK>(`${geturl}`, formData, options)
|
||||
}
|
||||
|
||||
|
||||
GetViewer(DocId: string, FsId: string) {
|
||||
|
||||
const geturl = environment.apiURL + 'ecm/document/viewfile';
|
||||
let params = new HttpParams();
|
||||
|
||||
params = params.set("docId", DocId);
|
||||
params = params.set("applicationId", FsId);
|
||||
|
||||
let options = {
|
||||
params: params
|
||||
};
|
||||
return this.http.get<string>(`${geturl}`, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export class CMAPIService {
|
||||
} catch (error) {
|
||||
return err(error)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MiddlewareRepositoryService } from './middleware-repository.service';
|
||||
|
||||
describe('MiddlewareRepositoryService', () => {
|
||||
let service: MiddlewareRepositoryService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(MiddlewareRepositoryService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service"
|
||||
import { ok, err, Result } from 'neverthrow';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MiddlewareRepositoryService {
|
||||
|
||||
constructor(private MiddlewareServiceService: MiddlewareServiceService) { }
|
||||
|
||||
|
||||
async getViewerLink({DocId, ApplicationId}): Promise<Result<string, any>> {
|
||||
try {
|
||||
const result = await this.MiddlewareServiceService.GetViewer(DocId, ApplicationId).toPromise();
|
||||
return ok(result.replace('//pdfjs/web/', '/pdfjs/web/'))
|
||||
|
||||
} catch (error) {
|
||||
return err(error)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -30,4 +30,4 @@
|
||||
"src/sql",
|
||||
"src/connection",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user