Skip to content

Commit

Permalink
feat(4ps): add roles list
Browse files Browse the repository at this point in the history
  • Loading branch information
develite98 committed Jan 2, 2024
1 parent d78ce8d commit 474bc0c
Show file tree
Hide file tree
Showing 25 changed files with 920 additions and 26 deletions.
4 changes: 4 additions & 0 deletions apps/mix-database/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export const CMS_ROUTES = {
path: 'users',
fullPath: 'app/cam/users',
},
roles: {
path: 'roles',
fullPath: 'app/cam/roles',
},
},
};

Expand Down
6 changes: 6 additions & 0 deletions apps/mix-database/src/app/shares/consts/app.menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const APP_MENU: MenuItem[] = [
url: '',
iconColor: '#EC652C',
icon: 'database',
default: true,
children: [
{
icon: 'format_list_numbered',
Expand Down Expand Up @@ -63,6 +64,11 @@ export const APP_MENU: MenuItem[] = [
title: 'All Users',
url: CMS_ROUTES.portal.users.fullPath,
},
{
icon: 'description',
title: 'Roles',
url: CMS_ROUTES.portal.roles.fullPath,
},
],
},
];
Expand Down
1 change: 1 addition & 0 deletions libs/mix-lib/src/model/menu.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export type MenuItem = {
children?: MenuItem[];
align?: 'top' | 'bottom';
isDevelopment?: boolean;
default?: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ export class MainSideMenuComponent {

public selectedMenu: MenuItem | undefined = undefined;
public selectedMenus: Record<string, MenuItem | undefined> = {};
public settingMenu = {
title: 'Settings',
icon: 'settings',
align: 'bottom',
};

constructor(public route: Router) {}

ngOnInit() {
this.selectedMenu = this.menu.find((x) => x.default);
}

@tuiPure
public isMenuSelected(item: MenuItem, selectedMenu: MenuItem | undefined) {
return item.title === selectedMenu?.title;
Expand Down Expand Up @@ -102,22 +101,4 @@ export class MainSideMenuComponent {
this.showDetail = !this.showDetail;
if (!this.showDetail) this.selectedMenus = {};
}

public getShortName(name: string) {
if (name.length >= 10) {
return name
.split(' ')
.map((x) => x.charAt(0))
.join('');
}

return name;
}

// public showSetting() {
// this.dialogService.open(SettingDialogComponent, {
// width: 'fit-content',
// id: 'top-align-modal',
// });
// }
}
5 changes: 5 additions & 0 deletions libs/mix-share/src/modules/account/account.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ export const ROUTES: Route[] = [
loadComponent: () =>
import('./users/users.component').then((c) => c.UserComponent),
},
{
path: 'roles',
loadComponent: () =>
import('./roles/roles.component').then((c) => c.RolesComponent),
},
{
path: '',
redirectTo: 'users',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { MixInputComponent } from '@mixcore/ui/input';
import { MixSelectComponent } from '@mixcore/ui/select';
import { DialogRef, DialogService } from '@ngneat/dialog';
import { HotToastService } from '@ngneat/hot-toast';
import { UserStore } from '../../../stores/user.store';
import { UserStore } from '../../stores/user.store';

@Component({
selector: 'mix-create-user-dialog',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<div class="portal-menu-item flex gap-3 items-center"
[formGroup]="form">
<span class="flex items-center gap-2">
Title:
<editable (save)="save()">
<ng-template viewMode>
<span class="text-bold">{{ form.controls.title.value }}</span>
</ng-template>

<ng-template editMode>
<mix-input formControlName="title"
style="width: 150px"
editableOnEnter
editableOnEscape>
</mix-input></ng-template>
</editable>
</span>

<span class="flex items-center gap-2">
Path:
<editable (save)="save()">
<ng-template viewMode>
<span class="text-bold">{{
form.controls.path.value || 'Empty path'
}}</span>
</ng-template>

<ng-template editMode>
<mix-input [autoCompleteItems]="FULL_MENU"
formControlName="path"
style="width: 150px"
editableOnEnter
editableOnEscape>
</mix-input></ng-template>
</editable>
</span>

<span class="flex items-center gap-2">
Icon:
<editable (save)="save()">
<ng-template viewMode>
<span *ngIf="form.controls?.icon?.value"
class="material-symbols-outlined text-bold">{{ form.controls.icon.value }}</span>
<span *ngIf="!form.controls?.icon?.value">No icon found</span>
</ng-template>

<ng-template editMode>
<mix-input formControlName="icon"
style="width: 150px"
editableOnEnter
editableOnEscape>
</mix-input></ng-template>
</editable>
</span>

<span class="flex items-center gap-2">
Priority:
<editable (save)="save()">
<ng-template viewMode>
<span class="text-bold">{{ form.controls.priority.value || 0 }}</span>
</ng-template>

<ng-template editMode>
<mix-input-number type="number"
[step]="1"
formControlName="priority"
style="width: 150px"
editableOnEnter
editableOnEscape>
</mix-input-number></ng-template>
</editable>
</span>

<div class="flex gap-1 items-center ms-3">
<mix-button type="danger"
[iconBtn]="true"
(click)="deleteMenu()"
size="xs"><span class="material-symbols-outlined"> delete </span></mix-button>

<mix-button *ngIf="item.portalMenuId === null"
type="outline"
[iconBtn]="true"
(click)="showDialog(addNewMenuItem)"
size="xs"><span class="material-symbols-outlined"> add </span></mix-button>
</div>
</div>

<ng-template #addNewMenuItem
let-observer>
<div [formGroup]="addMenuForm">
<div>Update Portal Menu Item:</div>

<span class="content-label mt-3">Menu title</span>
<mix-input formControlName="title"
placeHolder="Menu title"></mix-input>
<mix-form-error formControlName="title"></mix-form-error>

<span class="content-label mt-3">Path</span>
<mix-input [autoCompleteItems]="FULL_MENU"
formControlName="path"
placeHolder="Admin path url"></mix-input>

<span class="content-label mt-3">Icon</span>
<span class="content-sub-description">We use Google Symbol as icon, please
<a href="https://fonts.google.com/icons"
tuiLink
target="_blank">visit here</a>
to get the correct icon name</span>

<mix-input class="mt-1"
formControlName="icon"
placeHolder="Icon"></mix-input>

<div class="flex justify-content-end mt-3">
<mix-button type="outline"
(click)="observer.complete()">Cancel</mix-button>

<mix-button class="ms-2"
(click)="createMenu(observer)">Create</mix-button>
</div>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.portal-menu-item {
padding: 8px;
border-radius: 4px;
border: 1px solid var(--border-color-default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { CommonModule } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
OnInit,
Output,
inject,
} from '@angular/core';
import {
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { MixDynamicData, PortalMenu } from '@mixcore/lib/model';
import { MixApiFacadeService } from '@mixcore/share/api';
import { FULL_MENU } from '@mixcore/share/auth';
import { FormHelper } from '@mixcore/share/form';
import { Utils } from '@mixcore/share/utils';
import { MixButtonComponent } from '@mixcore/ui/button';
import { MixInputComponent } from '@mixcore/ui/input';
import { MixInputNumberComponent } from '@mixcore/ui/input-number';
import { ModalService } from '@mixcore/ui/modal';
import { EditModeDirective, EditableComponent } from '@ngneat/edit-in-place';
import { HotToastService } from '@ngneat/hot-toast';
import { TuiDialogContext, TuiDialogService } from '@taiga-ui/core';
import { PolymorpheusContent } from '@tinkoff/ng-polymorpheus';
import { map, switchMap } from 'rxjs';

@Component({
selector: 'mix-portal-menu-item',
templateUrl: './portal-menu-item.component.html',
styleUrls: ['./portal-menu-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [
CommonModule,
MixInputComponent,
MixButtonComponent,
EditableComponent,
EditModeDirective,
EditModeDirective,
ReactiveFormsModule,
MixInputNumberComponent,
],
})
export class PortalMenuItemComponent implements OnInit {
FULL_MENU = inject(FULL_MENU).map((x) => x.url);
MIX_API = inject(MixApiFacadeService);
TOAST = inject(HotToastService);
dialog = inject(TuiDialogService);
DB_NAME = 'PortalMenu';
modal = inject(ModalService);

@Input() item!: PortalMenu;
@Output() portalMenuAdded = new EventEmitter<PortalMenu>();
@Output() portalMenuDeleted = new EventEmitter<PortalMenu>();

defaultFormValue: Record<string, string | null> = {};
form = new FormGroup({
title: new FormControl('', Validators.required),
path: new FormControl('', Validators.required),
icon: new FormControl('', Validators.required),
priority: new FormControl(),
});

public addMenuForm = new FormGroup({
title: new FormControl('', Validators.required),
path: new FormControl('', Validators.required),
icon: new FormControl('', Validators.required),
});

ngOnInit() {
this.form.patchValue(this.item);
this.defaultFormValue = this.form.getRawValue();
}

save() {
if (FormHelper.validateForm(this.form)) {
if (!Utils.isDifferent(this.defaultFormValue, this.form.getRawValue()))
return;

this.MIX_API.databaseApi
.saveData(this.DB_NAME, this.item.id, {
...this.item,
...(this.form.getRawValue() as unknown as MixDynamicData),
})
.pipe(
this.TOAST.observe({
loading: 'Saving...',
success: 'Successfully apply your change',
error: 'Something error, please try again',
})
)
.subscribe(() => {
this.defaultFormValue = this.form.getRawValue();
});
}
}

createMenu(dialog: any) {
if (FormHelper.validateForm(this.form)) {
this.MIX_API.databaseApi
.saveData(this.DB_NAME, -1, {
...(this.addMenuForm.getRawValue() as unknown as MixDynamicData),
portalMenuId: this.item.id,
role: this.item.role,
})
.pipe(
switchMap((item) => {
return this.MIX_API.databaseApi
.associateDb(this.DB_NAME, item.id!, this.DB_NAME, this.item.id)
.pipe(map(() => item));
}),
this.TOAST.observe({
loading: 'Creating...',
success: 'Successfully apply your change',
error: 'Something error, please try again',
})
)
.subscribe((result) => {
this.portalMenuAdded.emit(result as unknown as PortalMenu);
dialog.complete();
});
}
}

deleteMenu() {
this.modal.asKForAction('Are you sure to delete this portal menu ?', () => {
this.MIX_API.databaseApi
.deleteData(this.DB_NAME, this.item.id)
.pipe(
this.TOAST.observe({
loading: 'Deleting...',
success: 'Successfully apply your change',
error: 'Something error, please try again',
})
)
.subscribe(() => {
this.portalMenuDeleted.emit(this.item);
});
});
}

showDialog(content: PolymorpheusContent<TuiDialogContext>): void {
this.dialog.open(content, { size: 'auto' }).subscribe();
}
}
Loading

1 comment on commit 474bc0c

@vercel
Copy link

@vercel vercel bot commented on 474bc0c Jan 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.