Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/app/core/guards/router-protected/role.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ import { Observable } from 'rxjs';
import { decodeJWT } from '../../../shared/utils/stringProcess';
import { sendNotification } from '../../../shared/utils/notification';
import { Store } from '@ngrx/store';
import { Location } from '@angular/common';

@Injectable({
providedIn: 'root',
})
export class RoleGuard implements CanActivate {
constructor(private router: Router, private store: Store) {}
constructor(
private router: Router,
private store: Store,
private location: Location
) {}

canActivate(
next: ActivatedRouteSnapshot,
Expand Down Expand Up @@ -44,7 +49,9 @@ export class RoleGuard implements CanActivate {
'warning'
);
// nếu không đủ quyền, redirect sang trang 403 hoặc trang chủ
return this.router.createUrlTree(['/']);
this.location.back();
// return this.router.createUrlTree(['/']); // về trang chủ
return false;
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion src/app/core/models/organization.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ export type EditOrgRequest = {
email?: string;
phone?: string;
address?: string;
status?: string;
status?: number;
logo?: File;
};

export type ParamGetAllBlockOfOrg = {
blocksPage?: number;
blocksSize?: number;
membersPage?: number;
membersSize?: number;
activeOnlyMembers?: boolean;
includeUnassigned?: boolean;
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { SidebarItem } from '../../models/data-handle';

export function sidebarExercises(role: string): SidebarItem[] {
export function sidebarExercises(roles: string[]): SidebarItem[] {
return [
// {
// id: 'exam',
// path: 'exercise/exam-list',
// label: 'Bài thi',
// icon: 'fas fa-file-alt',
// },
{
id: 'exercise',
path: '/exercise/exercise-layout/my-assign-list',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export function sidebarOrgRouter(roles: string[]): SidebarItem[] {
{
id: 'list-orgs',
path: '/organization/orgs-list',
label: 'Nạp tiền',
label: 'Danh sách tổ chức',
icon: 'fa-solid fa-tasks',
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function sidebarPaymentRouter(role: string): SidebarItem[] {
{
id: 'purchase-history',
path: '/service-and-payment/purchase-history',
label: 'Lịch sử giao dịch',
label: 'Lịch sử đã mua',
icon: 'fa-solid fa-cart-shopping',
},
];
Expand Down
52 changes: 49 additions & 3 deletions src/app/core/services/api-service/organization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { ApiMethod } from '../config-service/api.methods';
import { ApiResponse, IPaginationResponse } from '../../models/api-response';
import { API_CONFIG } from '../config-service/api.enpoints';
import {
BlockResponse,
CreateOrgRequest,
EditOrgRequest,
FilterOrgs,
OrganizationInfo,
OrganizationResponse,
ParamGetAllBlockOfOrg,
} from '../../models/organization.model';
import { PostResponse } from '../../models/post.models';

Expand Down Expand Up @@ -45,9 +47,12 @@ export class OrganizationService {
}

editOrg(orgId: string, data: EditOrgRequest) {
return this.api.put<ApiResponse<null>>(
API_CONFIG.ENDPOINTS.PUT.EDIT_ORG(orgId),
data
const { logo, ...otherData } = data;

return this.api.patchWithFormData<ApiResponse<null>>(
API_CONFIG.ENDPOINTS.PATCH.EDIT_ORG(orgId),
otherData,
logo
);
}

Expand All @@ -56,4 +61,45 @@ export class OrganizationService {
API_CONFIG.ENDPOINTS.DELETE.DELETE_ORG(orgId)
);
}

createBlockInOrg(
orgId: string,
data: { name: string; code: string; description: string }
) {
return this.api.post<ApiResponse<null>>(
API_CONFIG.ENDPOINTS.POST.CREATE_BLOCK_IN_ORG(orgId),
data
);
}

getAllBlockOfOrg(orgId: string, params: ParamGetAllBlockOfOrg) {
return this.api.get<ApiResponse<IPaginationResponse<BlockResponse[]>>>(
API_CONFIG.ENDPOINTS.GET.SEACH_ALL_BLOCKS(orgId, params)
);
}

updateBlock(
id: string,
data: { name?: string; code?: string; description?: string }
) {
return this.api.patch<ApiResponse<null>>(
API_CONFIG.ENDPOINTS.PATCH.EDIT_BLOCK(id),
data
);
}

deleteBlock(id: string) {
return this.api.delete<ApiResponse<null>>(
API_CONFIG.ENDPOINTS.DELETE.DELETE_BLOCK(id)
);
}

getBlockDetails(
blockId: string,
data: { membersPage: number; membersSize: number; activeOnly: boolean }
) {
return this.api.get<ApiResponse<BlockResponse>>(
API_CONFIG.ENDPOINTS.GET.GET_BLOCK_DETAILS(blockId, data)
);
}
}
41 changes: 37 additions & 4 deletions src/app/core/services/config-service/api.enpoints.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { environment } from '../../../../environments/environment';
import { EnumType } from '../../models/data-handle';
import { FilterOrgs } from '../../models/organization.model';
import {
FilterOrgs,
ParamGetAllBlockOfOrg,
} from '../../models/organization.model';
import { SearchingUser } from '../../models/user.models';

export const version = '/v1';
Expand Down Expand Up @@ -168,8 +171,35 @@ export const API_CONFIG = {

return query;
},
GET_ORG_DETAILS_BY_ID: (orgId: string) =>
`/org/api/Organization/${orgId}`,
GET_ORG_DETAILS_BY_ID: (orgId: string) => `/org/organization/${orgId}`,
SEACH_ALL_BLOCKS: (orgId: string, params: ParamGetAllBlockOfOrg) => {
let query = `/org/${orgId}/blocks?`;
if (
params?.blocksPage !== undefined &&
params?.blocksSize !== undefined
) {
query += `blocksPage=${params.blocksPage}&blocksSize=${params.blocksSize}&`;
}
if (
params?.membersPage !== undefined &&
params?.membersSize !== undefined
) {
query += `membersPage=${params.membersPage}&membersSize=${params.membersSize}&`;
}
if (params?.activeOnlyMembers !== undefined) {
query += `activeOnlyMembers=${params.activeOnlyMembers}&`;
}
if (params?.includeUnassigned !== undefined) {
query += `includeUnassigned=${params.includeUnassigned}&`;
}
// Xóa dấu `&` hoặc `?` cuối cùng nếu có
return query.replace(/[&?]$/, '');
},
GET_BLOCK_DETAILS: (
blockId: string,
data: { membersPage: number; membersSize: number; activeOnly: boolean }
) =>
`/org/block/${blockId}?membersPage=${data.membersPage}&membersSize=${data.membersSize}&activeOnly=${data.activeOnly}`,
},
POST: {
LOGIN: '/identity/auth/login',
Expand Down Expand Up @@ -236,10 +266,10 @@ export const API_CONFIG = {
TOPUP: '/payment/topup',
PURCHASE: '/payment/purchase',
CREATE_ORGANIZATION: '/org/organization',
CREATE_BLOCK_IN_ORG: (orgId: string) => `/org/${orgId}/block`,
},
PUT: {
EDIT_FILE: (id: string) => `/file/api/FileDocument/edit/${id}`,
EDIT_ORG: (id: string) => `/org/api/Organization/${id}`,
},
PATCH: {
UPDATE_EXERCISE: (exerciseId: string) =>
Expand All @@ -257,6 +287,8 @@ export const API_CONFIG = {
`/submission/coding/exercise/${exerciseId}/coding-detail`,
RENAME_THREAD: (threadId: string) => `/ai/chat/thread/${threadId}`,
CHANGE_MY_PASSWORD: `/identity/user/password`,
EDIT_ORG: (id: string) => `/org/organization/${id}`,
EDIT_BLOCK: (blockId: string) => `/org/block/${blockId}`,
},
DELETE: {
DELETE_QUESTION: (exerciseId: string, questionId: string) =>
Expand All @@ -277,6 +309,7 @@ export const API_CONFIG = {
UNSAVE_EXERCISE: (exerciseId: string) =>
`/profile/exercise/${exerciseId}/save`,
DELETE_ORG: (orgId: string) => `/org/organization/${orgId}`,
DELETE_BLOCK: (blockId: string) => `/org/block/${blockId}`,
},
},
HEADERS: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,6 @@ <h3>{{ selectedConversation.conversationName }}</h3>
</div>

<form class="message-form" (ngSubmit)="handleSendMessage()">
<input
type="text"
class="message-input"
placeholder="Type a message"
[(ngModel)]="message"
name="message"
autocomplete="off"
/>
<button
class="btn btn--icon btn--primary"
type="submit"
Expand All @@ -206,6 +198,14 @@ <h3>{{ selectedConversation.conversationName }}</h3>
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
</svg>
</button>
<input
type="text"
class="message-input"
placeholder="Type a message"
[(ngModel)]="message"
name="message"
autocomplete="off"
/>
</form>
</ng-container>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export class ExerciseLayoutComponent implements OnInit, OnDestroy {
private routerSubscription!: Subscription;

constructor(private router: Router) {
const role = decodeJWT(localStorage.getItem('token') ?? '')?.payload.scope;
this.sidebarData = sidebarExercises(role);
const roles = decodeJWT(localStorage.getItem('token') ?? '')?.payload.roles;
this.sidebarData = sidebarExercises(roles);
}

ngOnInit() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import {
SearchUserProfileResponse,
User,
Expand All @@ -18,7 +18,6 @@ import {
import { forkJoin } from 'rxjs/internal/observable/forkJoin';
import { catchError } from 'rxjs/internal/operators/catchError';
import { of } from 'rxjs/internal/observable/of';
import { Subscription } from 'rxjs/internal/Subscription';
import {
AssignedStudentsListResponse,
MySubmissionsHistoryResponse,
Expand All @@ -33,10 +32,6 @@ import { CodingService } from '../../../../core/services/api-service/coding.serv
})
export class AssignExerciseComponent implements OnInit {
private debounceTimer: ReturnType<typeof setTimeout> | null = null;
private checkTypeExercise: string[] = [
'/assign-exercise-code',
'/assign-exercise-quiz',
];

avatarUrlDefault: string = avatarUrlDefault;
exerciseTypeCall: MySubmissionsHistoryResponse['exerciseType'] = 'QUIZ';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Component } from '@angular/core';
import { MainSidebarComponent } from '../../../shared/components/fxdonad-shared/main-sidebar/main-sidebar.component';
import { sidebarOrganizations } from '../../../core/constants/menu-router.data';
import { CommonModule } from '@angular/common';
import { AdminRoutingModule } from '../../dashboard/dashboard-routing.module';
import { RouterOutlet } from '@angular/router';
import { Router, RouterOutlet } from '@angular/router';
import { sidebarOrgRouter } from '../../../core/router-manager/vetical-menu-dynamic/org-vertical-menu';
import { SidebarItem } from '../../../core/models/data-handle';
import { decodeJWT } from '../../../shared/utils/stringProcess';

@Component({
selector: 'app-layout-organization',
Expand All @@ -18,7 +20,12 @@ import { RouterOutlet } from '@angular/router';
})
export class LayoutOrganizationComponent {
isSidebarCollapsed = true;
sidebarData = sidebarOrganizations;
sidebarData: SidebarItem[] = [];

showSidebar = true;

constructor(private router: Router) {
const roles = decodeJWT(localStorage.getItem('token') ?? '')?.payload.roles;
this.sidebarData = sidebarOrgRouter(roles);
}
}
Loading