Skip to content

Commit

Permalink
✔ Ticket Detail ~
Browse files Browse the repository at this point in the history
  • Loading branch information
bifeldy committed Nov 5, 2023
1 parent 9c71d3f commit 7796c88
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 18 deletions.
21 changes: 14 additions & 7 deletions src/api/controllers/ticket.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ export class TicketController {
@HttpCode(200)
@FilterApiKeyAccess()
@VerifiedOnly()
@Roles(RoleModel.ADMIN, RoleModel.MODERATOR)
@Roles(RoleModel.ADMIN, RoleModel.MODERATOR, RoleModel.FANSUBBER, RoleModel.USER)
async getAll(@Req() req: Request, @Res({ passthrough: true }) res: Response): Promise<any> {
const searchQuery = req.query['q'] || '';
try {
const user: UserModel = res.locals['user'];
const queryPage = parseInt(req.query['page'] as string);
const queryRow = parseInt(req.query['row'] as string);
const sqlWhere: any[] = [
Expand All @@ -51,10 +52,15 @@ export class TicketController {
{ final_decision: ILike(`%${searchQuery}%`) },
{ contact_email: ILike(`%${searchQuery}%`) }
];
if (req.query['finished'] === 'true') {
for (const sw of sqlWhere) {
for (const sw of sqlWhere) {
if (req.query['finished'] === 'true') {
sw.finished = true;
}
if (user.role !== RoleModel.ADMIN && user.role !== RoleModel.MODERATOR) {
sw.user_ = {
id: Equal(user.id)
};
}
}
const [tickets, count] = await this.ticketRepo.findAndCount({
where: sqlWhere,
Expand All @@ -63,7 +69,7 @@ export class TicketController {
[req.query['sort'] as string]: (req.query['order'] as string).toUpperCase()
} : {
created_at: 'DESC',
title: 'ASC'
url: 'ASC'
})
},
relations: ['user_'],
Expand Down Expand Up @@ -178,8 +184,6 @@ export class TicketController {
@Get('/:id')
@HttpCode(200)
@FilterApiKeyAccess()
@VerifiedOnly()
@Roles(RoleModel.ADMIN, RoleModel.MODERATOR, RoleModel.FANSUBBER, RoleModel.USER)
async getById(@Req() req: Request, @Res({ passthrough: true }) res: Response): Promise<any> {
const secretQuery = req.query['secret'] || '';
try {
Expand All @@ -188,14 +192,17 @@ export class TicketController {
where: [
{
id: Equal(parseInt(req.params['id'])),
...((user.role === RoleModel.ADMIN || user.role === RoleModel.MODERATOR) ? {
...((user?.role === RoleModel.ADMIN || user?.role === RoleModel.MODERATOR) ? {
// Admin, Moderator Can See All Reports
} : {
secret: Equal(secretQuery)
})
}
]
});
if (!ticket.url.startsWith('http')) {
ticket.url = `http://${ticket.url}`;
}
if ('user_' in ticket && ticket.user_) {
delete ticket.user_.created_at;
delete ticket.user_.updated_at;
Expand Down
74 changes: 71 additions & 3 deletions src/app/_pages/ticket/ticket-detail/ticket-detail.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,71 @@
<p>ticket-detail works!</p>
<p>cooming-soon!</p>
<p>please-come-back-later!</p>
<!-- Notification -->
<app-notifications></app-notifications>

<!-- Content -->
<div class="container" *ngIf="ticketData">

<!-- Detail -->
<div class="row pb-3 px-0">
<div class="col-12">
<div class="row">
<div class="sticky-top bg-bifeldy">
<div class="col-12">
<h2 class="pt-3 m-0">
<b class="text-bifeldy">Ticket #{{ ticketData.id }}</b>
</h2>
</div>
<div class="col-12">
<hr class="my-1 border-bottom-dotted" style="height: 4px; background: url('/assets/img/stripe.png');" />
</div>
<div class="col-12">
<h5 class="pb-3 m-0 text-bifeldy">
.:
<a routerLink="/user/{{ ticketData.user_.username }}" class="text-warning text-decoration-none" *ngIf="ticketData.user_">
{{ ticketData.user_.username }}
</a>
<span class="text-warning" *ngIf="!ticketData.user_">Anonim!</span>
::
{{ ticketData.created_at | date:'d MMMM y, hh:mm:ss a z' }}
:.
</h5>
</div>
</div>
<div class="col-12 pt-3 mt-3">
URL Terkait ::
<br />
<a href="{{ ticketData.url }}" class="text-warning text-decoration-none" target="_blank">
{{ ticketData.url }}
</a>
</div>
<div class="col-12 pt-3 mt-3" *ngIf="ticketData.expected_solution">
Ekspektasi Tindakan ::
<br />
{{ ticketData.expected_solution }}
</div>
<div class="col-12 pt-3 mt-3" *ngIf="ticketData.final_decision">
Hasil Putusan ::
<br />
{{ ticketData.final_decision }}
</div>
<div class="col-12 pt-3 mt-3">
Isi Laporan ::
<br />
<div [innerHTML]="ticketData.reported_issue | safeInnerHtml"></div>
</div>
</div>
</div>
</div>
<div class="row pt-3">
<div class="col-12 sticky-top bg-bifeldy">
<h2 class="pt-3 border-bottom-dotted">
<b class="text-bifeldy">Komentar</b>
</h2>
</div>
<div class="col-12">
<div class="p-3">
<app-discussion></app-discussion>
</div>
</div>
</div>

</div>
65 changes: 62 additions & 3 deletions src/app/_pages/ticket/ticket-detail/ticket-detail.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,74 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { GlobalService } from '../../../_shared/services/global.service';
import { TicketService } from '../../../_shared/services/ticket.service';
import { PageInfoService } from '../../../_shared/services/page-info.service';
import { BusyService } from '../../../_shared/services/busy.service';

@Component({
selector: 'app-ticket-detail',
templateUrl: './ticket-detail.component.html',
styleUrls: ['./ticket-detail.component.css']
})
export class TicketDetailComponent implements OnInit {
export class TicketDetailComponent implements OnInit, OnDestroy {

ticketId = 0;
ticketSecret = '';
ticketData = null;

subsActRoute = null;
subsTicket = null;
subsParam = null;

constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private bs: BusyService,
private gs: GlobalService,
private pi: PageInfoService,
private ticket: TicketService
) {
this.gs.bannerImg = null;
this.gs.sizeContain = false;
this.gs.bgRepeat = false;
}

constructor() { }
ngOnDestroy(): void {
this.subsActRoute?.unsubscribe();
this.subsTicket?.unsubscribe();
this.subsParam?.unsubscribe();
}

ngOnInit(): void {
this.ticketId = Number(this.activatedRoute.snapshot.paramMap.get('ticketId') || '');
this.ticketSecret = this.activatedRoute.snapshot.queryParamMap.get('secret') || '';
this.getTicket();
}

getTicket(): void {
this.bs.busy();
this.subsTicket = this.ticket.getTicket(this.ticketId, this.ticketSecret).subscribe({
next: res => {
this.gs.log('[TICKET_DETAIL_SUCCESS]', res);
this.ticketData = res.result;
this.pi.updatePageMetaData(
`Ticket #${this.ticketData.id}`,
this.ticketData.reported_issue,
this.ticketData.url
);
this.bs.idle();
},
error: err => {
this.gs.log('[TICKET_DETAIL_ERROR]', err, 'error');
this.bs.idle();
this.router.navigate(['/error'], {
queryParams: {
returnUrl: '/ticket'
}
});
}
});
}

}
35 changes: 32 additions & 3 deletions src/app/_pages/ticket/ticket.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { Routes, RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { MaterialFileInputModule } from 'ngx-material-file-input';
import { AngularEditorModule } from '@kolkov/angular-editor';

import { CONSTANTS } from '../../../constants';

import { RoleModel } from '../../../models/req-res.model';

import { RolesGuard } from '../../_shared/guards/roles.guard';
import { VerifiedGuard } from '../../_shared/guards/verified.guard';

import { RoleModel } from '../../../models/req-res.model';
import { SharedMaterialModule } from '../../_shared/modules/shared-material.module';

import { CustomPipeModule } from '../../_shared/pipes/custom-pipe.module';

import { MaterialChipModule } from '../../_shared/components/material-chip/material-chip.module';
import { MaterialTabModule } from '../../_shared/components/material-tab/material-tab.module';
import { NotificationsModule } from '../../_shared/components/notifications/notifications.module';
import { StatsServerModule } from '../../_shared/components/stats-server/stats-server.module';
import { BannerDiscordModule } from '../../_shared/components/banner-discord/banner-discord.module';
import { DiscussionModule } from '../../_shared/components/discussion/discussion.module';
import { BannerDonasiModule } from '../../_shared/components/banner-donasi/banner-donasi.module';

import { TicketListComponent } from './ticket-list/ticket-list.component';
import { TicketDetailComponent } from './ticket-detail/ticket-detail.component';
Expand Down Expand Up @@ -41,7 +57,20 @@ const routes: Routes = [
],
imports: [
CommonModule,
RouterModule.forChild(routes)
RouterModule.forChild(routes),
BannerDonasiModule,
SharedMaterialModule,
MaterialTabModule,
FormsModule,
ReactiveFormsModule,
MaterialFileInputModule,
NotificationsModule,
AngularEditorModule,
BannerDiscordModule,
StatsServerModule,
MaterialChipModule,
DiscussionModule,
CustomPipeModule
]
})
export class TicketModule { }
4 changes: 2 additions & 2 deletions src/app/_shared/services/ticket.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export class TicketService {
return this.api.putData(`/ticket/${ticketId}`, ticketData);
}

getTicket(ticketId: number): Observable<JsonResponse<TicketModel>> {
return this.api.getData(`/ticket/${ticketId}`);
getTicket(ticketId: number, secret: string): Observable<JsonResponse<TicketModel>> {
return this.api.getData(`/ticket/${ticketId}?secret=${secret}`);
}

}

0 comments on commit 7796c88

Please sign in to comment.