feat(deps): Add support for more departments

This commit is contained in:
pakintada@gmail.com 2024-06-19 13:56:56 +07:00
parent bdf2fac1ad
commit 4369ebb2a5
19 changed files with 296 additions and 169 deletions

View file

@ -1,4 +1,4 @@
import { inject, NgModule } from '@angular/core';
import { inject, NgModule } from "@angular/core";
import {
ActivatedRouteSnapshot,
CanActivateFn,
@ -6,14 +6,14 @@ import {
RouterModule,
RouterStateSnapshot,
Routes,
} from '@angular/router';
import { UserService } from './core/services/user.service';
import { map } from 'rxjs';
import { UserPermissions } from './core/auth/userPermissions';
} from "@angular/router";
import { UserService } from "./core/services/user.service";
import { map } from "rxjs";
import { UserPermissions } from "./core/auth/userPermissions";
const authGuard: CanActivateFn = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
state: RouterStateSnapshot,
) => {
const userService: UserService = inject(UserService);
const router: Router = inject(Router);
@ -23,12 +23,12 @@ const authGuard: CanActivateFn = (
if (isAuth) {
return true;
}
return router.createUrlTree(['/login'], {
return router.createUrlTree(["/login"], {
queryParams: {
redirectUrl: state.url,
},
});
})
}),
);
};
@ -42,21 +42,23 @@ const permissionsGuard: (
const user = userService.getCurrentUser();
if (user == null)
return router.createUrlTree(['/login'], {
return router.createUrlTree(["/login"], {
queryParams: {
redirectUrl: state.url,
},
});
console.log("require following permissions", requiredPermissions);
if (
requiredPermissions.every((permission) =>
user.permissions.includes(permission)
user.permissions.includes(permission),
)
) {
return true;
}
return router.createUrlTree(['/unauthorized'], {
return router.createUrlTree(["/unauthorized"], {
queryParams: {
redirectUrl: state.url,
},
@ -73,47 +75,47 @@ const loginGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
return true;
}
// redirect to redirectUrl query param
console.log("redirectURL", route.queryParams['redirectUrl']);
console.log("redirectURL", route.queryParams["redirectUrl"]);
return router.createUrlTree([
router.parseUrl(route.queryParams['redirectUrl'] ?? 'departments'),
router.parseUrl(route.queryParams["redirectUrl"] ?? "departments"),
]);
// return false;
})
}),
);
};
const routes: Routes = [
{
path: 'login',
path: "login",
loadComponent: () =>
import('./core/auth/auth.component').then((m) => m.AuthComponent),
import("./core/auth/auth.component").then((m) => m.AuthComponent),
canActivate: [loginGuard],
},
{
path: 'callback',
path: "callback",
loadComponent: () =>
import('./core/callback/callback.component').then(
(m) => m.CallbackComponent
import("./core/callback/callback.component").then(
(m) => m.CallbackComponent,
),
},
{
path: 'departments',
path: "departments",
loadComponent: () =>
import('./core/department/department.component').then(
(m) => m.DepartmentComponent
import("./core/department/department.component").then(
(m) => m.DepartmentComponent,
),
canActivate: [authGuard],
},
{
path: ':department',
path: ":department",
loadComponent: () =>
import('./core/layout/layout.component').then((m) => m.LayoutComponent),
import("./core/layout/layout.component").then((m) => m.LayoutComponent),
children: [
{
path: 'recipes',
path: "recipes",
loadComponent: () =>
import('./features/recipes/recipes.component').then(
(m) => m.RecipesComponent
import("./features/recipes/recipes.component").then(
(m) => m.RecipesComponent,
),
canActivate: [
authGuard,
@ -121,10 +123,10 @@ const routes: Routes = [
],
},
{
path: 'recipe/:productCode',
path: "recipe/:productCode",
loadComponent: () =>
import(
'./features/recipes/recipe-details/recipe-details.component'
"./features/recipes/recipe-details/recipe-details.component"
).then((m) => m.RecipeDetailsComponent),
canActivate: [
authGuard,
@ -132,38 +134,38 @@ const routes: Routes = [
],
},
{
path: 'log',
path: "log",
loadComponent: () =>
import('./features/changelog/changelog.component').then(
(m) => m.ChangelogComponent
import("./features/changelog/changelog.component").then(
(m) => m.ChangelogComponent,
),
},
{
path: 'materials',
path: "materials",
loadComponent: () =>
import(
'./features/material-settings/material-settings.component'
"./features/material-settings/material-settings.component"
).then((m) => m.MaterialSettingsComponent),
},
{
path: 'toppings',
path: "toppings",
loadComponent: () =>
import('./features/toppings/toppings.component').then(
(t) => t.ToppingsComponent
import("./features/toppings/toppings.component").then(
(t) => t.ToppingsComponent,
),
},
],
},
{
path: '',
pathMatch: 'full',
redirectTo: 'departments',
path: "",
pathMatch: "full",
redirectTo: "departments",
},
{
path: 'unauthorized',
path: "unauthorized",
loadComponent: () =>
import('./core/auth/unauthorized.component').then(
(m) => m.UnauthorizedComponent
import("./core/auth/unauthorized.component").then(
(m) => m.UnauthorizedComponent,
),
},
// {
@ -172,8 +174,8 @@ const routes: Routes = [
// import('./core/notfound.component').then((m) => m.NotfoundComponent),
// },
{
path: '**',
redirectTo: 'departments',
path: "**",
redirectTo: "departments",
},
];

View file

@ -8,13 +8,28 @@ export enum UserPermissions {
VIEWER = 1 << 4,
EDITOR = 1 << 7,
DUBAI_PERMISSION = 1 << 8,
COUNTER_PERMISSION = 1 << 9,
SINGAPORE_PERMISSION = 1 << 10,
COCKTAIL_PERMISSION = 1 << 11,
// add new permission by shifting after 7. eg. 8,9,...
// also do add at server
SUPER_ADMIN_PERMISSION = THAI_PERMISSION | MALAY_PERMISSION | AUS_PERMISSION | ALPHA3_PERMISSION | (EDITOR | VIEWER)
SUPER_ADMIN_PERMISSION = THAI_PERMISSION |
MALAY_PERMISSION |
AUS_PERMISSION |
ALPHA3_PERMISSION |
COUNTER_PERMISSION |
SINGAPORE_PERMISSION |
DUBAI_PERMISSION |
COCKTAIL_PERMISSION |
(EDITOR | VIEWER),
}
export function getPermissions(perms: number) : UserPermissions[] {
return Object.values(UserPermissions)
.filter(permission => typeof permission === 'number' && (perms & permission) !== 0) as UserPermissions[];
export function getPermissions(perms: number): UserPermissions[] {
return Object.values(UserPermissions).filter(
(permission) =>
typeof permission === "number" && (perms & permission) !== 0,
) as UserPermissions[];
}

View file

@ -1,37 +1,42 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../services/user.service';
import {getPermissions} from "../auth/userPermissions";
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { UserService } from "../services/user.service";
import { getPermissions } from "../auth/userPermissions";
@Component({
selector: 'app-callback',
selector: "app-callback",
standalone: true,
templateUrl: './callback.component.html',
templateUrl: "./callback.component.html",
})
export class CallbackComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private userService: UserService
private userService: UserService,
) {}
ngOnInit(): void {
this.route.queryParams.subscribe((params) => {
console.log(params);
console.log(params, params["permissions"]);
if (params['email'] && params['name'] && params['picture'] && params['permissions']) {
if (
params["email"] &&
params["name"] &&
params["picture"] &&
params["permissions"]
) {
this.userService.setAuth({
email: params['email'],
name: params['name'],
picture: params['picture'],
permissions: getPermissions(params['permissions']),
email: params["email"],
name: params["name"],
picture: params["picture"],
permissions: getPermissions(params["permissions"]),
});
}
if (params['redirect_to']) {
void this.router.navigate([params['redirect_to']]);
if (params["redirect_to"]) {
void this.router.navigate([params["redirect_to"]]);
} else {
void this.router.navigate(['/']);
void this.router.navigate(["/"]);
}
});
}

View file

@ -1,11 +1,11 @@
import { Component } from '@angular/core';
import { CommonModule, NgOptimizedImage } from '@angular/common';
import { Router } from '@angular/router';
import { UserService } from '../services/user.service';
import { UserPermissions } from '../auth/userPermissions';
import { NotFoundHandler } from 'src/app/shared/helpers/notFoundHandler';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
import { Component } from "@angular/core";
import { CommonModule, NgOptimizedImage } from "@angular/common";
import { Router } from "@angular/router";
import { UserService } from "../services/user.service";
import { UserPermissions } from "../auth/userPermissions";
import { NotFoundHandler } from "src/app/shared/helpers/notFoundHandler";
import { AsyncStorage } from "src/app/shared/helpers/asyncStorage";
import { getCountryMapSwitcher } from "src/app/shared/helpers/recipe";
@Component({
standalone: true,
@ -56,33 +56,43 @@ import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe';
</div>
`,
})
export class DepartmentComponent {
acccessibleCountries:string[] = [];
acccessibleCountries: string[] = [];
// top row country
countries: { id: string; img: string }[] = [
{
id: 'tha',
img: 'assets/departments/tha_plate.png',
id: "tha",
img: "assets/departments/tha_plate.png",
},
{
id: 'mys',
img: 'assets/departments/mys_plate.png',
id: "mys",
img: "assets/departments/mys_plate.png",
},
{
id: 'aus',
img: 'assets/departments/aus_plate.png',
id: "aus",
img: "assets/departments/aus_plate.png",
},
// add new country here!
{
id: "sgp",
img: "assets/departments/sgp_plate.png",
},
{
id: "counter",
img: "assets/departments/counter01_plate.png",
},
];
// bottom row country
alphas: { id: string; img: string }[] = [
{
id: 'alpha-3',
img: 'assets/departments/alpha-3.png',
id: "alpha-3",
img: "assets/departments/alpha-3.png",
},
{
id: "cocktail",
img: "assets/departments/cocktail_tha.png",
},
];
@ -91,45 +101,66 @@ export class DepartmentComponent {
constructor(
private router: Router,
private _userService: UserService
private _userService: UserService,
) {
let perms = _userService.getCurrentUser()!.permissions;
console.log("GainAccesses",perms)
console.log("GainAccesses", perms);
for (let perm of perms) {
switch (perm) {
case UserPermissions.THAI_PERMISSION:
this.acccessibleCountries.push('tha');
this.acccessibleCountries.push("tha");
break;
case UserPermissions.MALAY_PERMISSION:
this.acccessibleCountries.push('mys');
this.acccessibleCountries.push("mys");
break;
case UserPermissions.AUS_PERMISSION:
this.acccessibleCountries.push('aus');
this.acccessibleCountries.push("aus");
break;
case UserPermissions.ALPHA3_PERMISSION:
this.acccessibleCountries.push('alpha-3');
this.acccessibleCountries.push("alpha-3");
break;
case UserPermissions.SINGAPORE_PERMISSION:
this.acccessibleCountries.push("sgp");
break;
case UserPermissions.COUNTER_PERMISSION:
this.acccessibleCountries.push("counter");
break;
case UserPermissions.DUBAI_PERMISSION:
this.acccessibleCountries.push("dubai");
break;
case UserPermissions.COCKTAIL_PERMISSION:
this.acccessibleCountries.push("cocktail");
break;
default:
break;
}
}
console.log("OK", this.acccessibleCountries);
}
onClick(id: string) {
// add handler for redirect
this.notfoundHandler.handleSwitchCountry(id, async () => {
// set country
await AsyncStorage.setItem('currentRecipeCountry', getCountryMapSwitcher(id));
// set filename, don't know which file was a target so use default
await AsyncStorage.setItem('currentRecipeFile', 'default');
}, async () => {
// set country to `tha`
await AsyncStorage.setItem('currentRecipeCountry', 'Thailand');
// set filename, don't know which file was a target so use default
await AsyncStorage.setItem('currentRecipeFile', 'default');
// safely return to recipes
});
this.notfoundHandler.handleSwitchCountry(
id,
async () => {
// set country
await AsyncStorage.setItem(
"currentRecipeCountry",
getCountryMapSwitcher(id),
);
// set filename, don't know which file was a target so use default
await AsyncStorage.setItem("currentRecipeFile", "default");
},
async () => {
// set country to `tha`
await AsyncStorage.setItem("currentRecipeCountry", "Thailand");
// set filename, don't know which file was a target so use default
await AsyncStorage.setItem("currentRecipeFile", "default");
// safely return to recipes
},
);
void this.router.navigate([`/${id}/recipes`]);
}
}

View file

@ -133,7 +133,6 @@ export class Debugger {
}
});
break;
default:
if(cmd.startsWith("fn::")){
@ -204,6 +203,23 @@ export class Debugger {
} else if(cmd.startsWith("var::")){
let varname = cmd.substring(5);
this.output.push(JSON.stringify(holdon[varname]));
} else if(cmd.startsWith("load::")){
} else {
// assume varname
if(cmd.endsWith("#window")){
let exposed: string = cmd.split(" ")[0];
console.log("try exposed to window "+exposed);
let estr = "window."+exposed+" = \""+holdon[exposed]+"\"";
console.log("estr", estr);
let eval_res = eval(estr);
console.log("eval_res", eval_res);
this.output.push(JSON.stringify(eval_res));
} else {
this.output.push(JSON.stringify(holdon[cmd]));
}
}
break;
@ -217,9 +233,9 @@ export class Debugger {
}
} else if (!line.startsWith("//") && line != ""){
if(!line.startsWith("window") && !line.startsWith("let") && !line.startsWith("var")){
line = "window."+line;
}
// if(!line.startsWith("window") && !line.startsWith("let") && !line.startsWith("var")){
// line = "window."+line;
// }
try {

View file

@ -4,7 +4,10 @@ export function departmentList() {
'tha',
'mys',
'aus',
'alpha-3'
'alpha-3',
'sgp',
'dubai',
'counter'
];
}
@ -28,7 +31,16 @@ export class NotFoundHandler {
handleSwitchCountry(country: string, callback: () => Promise<any>, error?: () => Promise<any>) {
let checkCondition = departmentList().includes(country);
if(checkCondition) {
callback();
// callback();
Promise.allSettled([
Promise.resolve(callback())
]).then((results) => {
// console.log("Resolved callback: ",results)
if(results[0].status == 'fulfilled'){
console.info("Callback executed successfully");
}
});
} else {
if(error)
error();

View file

@ -114,6 +114,9 @@ export var countryMap: Tuple<string, string>[] = [
new Tuple<string, string>('tha', 'Thailand'),
new Tuple<string, string>('mys', 'Malaysia'),
new Tuple<string, string>('aus', 'Australia'),
new Tuple<string, string>('sgp', 'Singapore'),
new Tuple<string, string>('dubai', 'UAE Dubai'),
new Tuple<string, string>('counter', 'Counter')
];
export function getCountryMapSwitcher(param: string) {

View file

@ -1,4 +1,5 @@
export const environment = {
production: false,
api: 'http://localhost:8080',
api: "http://localhost:8080",
imgApi: "http://localhost:36527",
};

View file

@ -1,4 +1,5 @@
export const environment = {
production: true,
api: 'https://recipe.taobin.io:8090/api',
api: "https://recipe.taobin.io:8090/api",
imgApi: "https://recipe.taobin.io:8090/img",
};