Skip to content

Commit

Permalink
feat(): delete & ui db context
Browse files Browse the repository at this point in the history
  • Loading branch information
develite98 committed Dec 4, 2023
1 parent 2276991 commit b5f0b0a
Show file tree
Hide file tree
Showing 17 changed files with 399 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { MixSelectComponent } from '@mixcore/ui/select';
import { MixTextAreaComponent } from '@mixcore/ui/textarea';
import { DialogRef } from '@ngneat/dialog';
import { HotToastService } from '@ngneat/hot-toast';
import { debounceTime, delay, tap } from 'rxjs';
import { debounceTime, tap } from 'rxjs';

@Component({
selector: 'mix-db-context-form',
Expand Down Expand Up @@ -58,7 +58,7 @@ export class DbContextFormComponent extends BaseComponent {

public displayName$ = this.form.controls.displayName.valueChanges.pipe(
takeUntilDestroyed(),
debounceTime(300),
debounceTime(600),
tap(() => this.updateSystemName())
);

Expand All @@ -71,7 +71,7 @@ export class DbContextFormComponent extends BaseComponent {
this.form.disable();
this.mixApi.databaseContext
.save(this.form.value as MixDbContext)
.pipe(delay(5000), this.observerLoadingStateSignal())
.pipe(this.observerLoadingStateSignal())
.subscribe({
next: () => {
this.toast.success('Successfully create your db context');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,82 @@
<div class="data-table-page">
<div class="data-table-page__main-container">
<mix-sub-toolbar [description]="'LISTING'"
[title]="'All Context'">
[title]="'All Db Context'">
<div class="toolbar-separator"></div>
<mix-button (click)="addContext()"
size="s"><span class="material-symbols-outlined"> add </span>&nbsp; New
Context</mix-button>
<div class="toolbar-separator"></div>
<mix-button type="danger"
size="s">
<span class="material-symbols-outlined"> delete </span>&nbsp;
Remove(s)</mix-button>
</mix-sub-toolbar>

<div class="data-table-page__body">
@if (store.vm$ |async; as vm) {
<div class="p-3 d-flex gap-3 flex-wrap">
@for (item of vm.data; track item.id) {
<div class="context-card {{ ProviderIconMap[item.databaseProvider] }}"
tuiCard
tuiSurface>
<h4 tuiTitle>
{{ item.displayName }}
</h4>
<span tuiSubtitle>{{ item.databaseProvider }}</span>
@if (store.vm$ |async; as vm) { @if (vm.status === 'Loading') {
<div class="p-3">
<mix-skeleton-loading type="table"></mix-skeleton-loading>
</div>
} @else if (!vm.data.length) {
<div class="p-3">
<mix-empty-content (actionClick)="addContext()"></mix-empty-content>
</div>
} @else {
<div class="p-3 mb-2">
<div class="text-sub text-500 mb-1">Choose provider:</div>
<tui-filter [content]="content"
[formControl]="filterForm"
[items]="filterItems"></tui-filter>
<ng-template #content
let-item>
{{ ProviderLabel[item] }}
</ng-template>
</div>

<div class="p-3">
<div class="text-sub text-500 mb-1 d-flex gap-2 align-items-center">
<div>Available contexts:</div>
<tui-loader *ngIf="vm.status === 'SilentLoading'"
[showLoader]="true"
[size]="'s'"></tui-loader>
</div>
<div class="d-flex gap-3 flex-wrap">
@for (item of combineFilter(vm.data, filterForm.value); track item.id)
{
<div class="context-card {{ ProviderIconMap[item.databaseProvider] }}"
tuiCard
tuiSurface>
<h4 tuiTitle>
{{ item.displayName }}
</h4>
<span tuiSubtitle>{{ item.databaseProvider }}</span>

<mix-button class="context-card__action"
type="icon"
[iconBtn]="true"
[tp]="dbSelect"
[tpOffset]="[-10, 5]"
(click)="selected = item"
tpVariation="popper"
tpPlacement="bottom-start"><span class="mix-icon">more_horiz</span></mix-button>
</div>
}
</div>
}
</div>
}
} }
</div>
</div>
</div>

<ng-template #dbSelect
let-hide>
<!-- <div class="mix-menu-item">
<div class="d-flex align-items-center gap-2">
<span class="mix-icon">edit</span> <span>Edit</span>
</div>
</div> -->
<div class="mix-menu-item"
(click)="hide(); onDelete()">
<div class="d-flex align-items-center gap-2">
<span class="mix-icon">delete</span>
<span class="text-danger">Remove</span>
</div>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.context-card {
padding: 1rem;
padding: 1rem 4rem 1rem 1rem;
background: var(--tui-base-02);
height: 8rem;
min-width: 200px;
width: fit-content;
cursor: pointer;
position: relative;

&:hover:after {
transform: scale(1.1);
Expand All @@ -17,17 +18,27 @@

&.sqlserver:after {
background: url('/assets/icons/microsoft.svg') bottom right no-repeat;
background-size: 50px;
}

&.postgres:after {
background: url('/assets/icons/postgres.svg') bottom right no-repeat;
background-size: 50px;
}

&.mysql:after {
background: url('/assets/icons/mysql.svg') bottom right no-repeat;
background-size: 100px;
}

&.sqllite:after {
&.sqlite:after {
background: url('/assets/icons/sqllite.svg') bottom right no-repeat;
background-size: 50px;
}

&__action {
position: absolute;
top: 2px;
right: 2px;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { DatabaseProvider } from '@mixcore/lib/model';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import {
DatabaseProvider,
DatabaseProviderDisplay,
MixDbContext,
} from '@mixcore/lib/model';
import { MixApiFacadeService } from '@mixcore/share/api';
import {
MixStatusIndicatorComponent,
MixSubToolbarComponent,
} from '@mixcore/share/components';
import { toastObserverProcessing } from '@mixcore/share/helper';
import { RelativeTimeSpanPipe } from '@mixcore/share/pipe';
import { MixButtonComponent } from '@mixcore/ui/button';
import { MixEmptyContentComponent } from '@mixcore/ui/empty-content';
import { DynamicFilterComponent } from '@mixcore/ui/filter';
import { ModalService } from '@mixcore/ui/modal';
import { SkeletonLoadingComponent } from '@mixcore/ui/skeleton';
import { MixDataTableModule } from '@mixcore/ui/table';
import { DialogService } from '@ngneat/dialog';
import { TippyDirective } from '@ngneat/helipopper';
import { HotToastService } from '@ngneat/hot-toast';
import { tuiPure } from '@taiga-ui/cdk';
import { TuiLoaderModule } from '@taiga-ui/core';
import { TuiCardModule, TuiSurfaceModule } from '@taiga-ui/experimental';
import { TuiFilterModule } from '@taiga-ui/kit';
import { DbContextFormComponent } from '../components/db-context-form/db-context-form.component';
import { DatabaseContextStore } from '../store/db-context.store';

Expand All @@ -19,6 +34,7 @@ import { DatabaseContextStore } from '../store/db-context.store';
standalone: true,
imports: [
CommonModule,
ReactiveFormsModule,
MixSubToolbarComponent,
MixButtonComponent,
MixDataTableModule,
Expand All @@ -27,6 +43,11 @@ import { DatabaseContextStore } from '../store/db-context.store';
DynamicFilterComponent,
TuiCardModule,
TuiSurfaceModule,
TuiFilterModule,
MixEmptyContentComponent,
SkeletonLoadingComponent,
TippyDirective,
TuiLoaderModule,
],
templateUrl: './database-context.component.html',
styleUrl: './database-context.component.scss',
Expand All @@ -35,14 +56,31 @@ import { DatabaseContextStore } from '../store/db-context.store';
export class DatabaseContextComponent {
public dialog = inject(DialogService);
public store = inject(DatabaseContextStore);
public modal = inject(ModalService);
public mixApi = inject(MixApiFacadeService);
public toast = inject(HotToastService);

public ProviderIconMap: Record<DatabaseProvider, string> = {
[DatabaseProvider.SQLSERVER]: 'sqlserver',
[DatabaseProvider.MySQL]: 'mysql',
[DatabaseProvider.PostgreSQL]: 'postgres',
[DatabaseProvider.SQLLITE]: 'sqllite',
[DatabaseProvider.SQLITE]: 'sqlite',
};

public filterForm = inject(FormBuilder).control<DatabaseProvider[]>([]);
public filterItems = Object.values(DatabaseProvider);
public ProviderLabel = DatabaseProviderDisplay as any;
public selected?: MixDbContext;

@tuiPure
public combineFilter(
value: MixDbContext[],
filterValue: DatabaseProvider[] | null
): MixDbContext[] {
if (!filterValue?.length) return value;
return value.filter((v) => filterValue.includes(v.databaseProvider));
}

public addContext() {
const dialogRef = this.dialog.open(DbContextFormComponent, {
windowClass: 'top-align-modal',
Expand All @@ -52,4 +90,19 @@ export class DatabaseContextComponent {
if (isReload) this.store.reload();
});
}

public onDelete() {
if (!this.selected) return;

this.modal.asKForAction('Are you sure to delete this item?', () => {
this.mixApi.databaseContext
.deleteById(this.selected!.id)
.pipe(toastObserverProcessing(this.toast))
.subscribe({
next: () => {
this.store.reload();
},
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class DatabaseContextStore extends BaseCRUDStore<MixDbContext> {
this.mixApi.databaseContext.gets({ ...request, columns: '', pageSize: 50 });

public override vm$ = this.select((s) => s);
public override requestName = 'database-context';
public override requestName = 'databaseContext';
public override searchColumns = ['Name', 'Description'];
public override searchColumnsDict: { [key: string]: string } = {
Name: 'displayName',
Expand Down
Loading

1 comment on commit b5f0b0a

@vercel
Copy link

@vercel vercel bot commented on b5f0b0a Dec 4, 2023

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.