Untitled

 avatar
unknown
plain_text
3 months ago
15 kB
6
Indexable
import { ProfileService } from './services';
import {
    Component,
    OnInit,
    inject,
    ViewChild,
    HostListener,
} from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
import { Profile } from './models/profile';
import { DxDataGridComponent } from 'devextreme-angular';
import { BehaviorSubject, switchMap, lastValueFrom } from 'rxjs';
import { cloneDeep } from 'lodash';
import { Customer, CustomerService } from '../customer';
import dxDataGrid, { Column, ContentReadyEvent } from 'devextreme/ui/data_grid';


interface ButtonDataViewModel {
    name: string;
    icon: string;
    template: string;
    type: string;
    class: string;
    event: string;
    disabled: boolean;
}

interface DetailViewModel {
    title: string;
    visible: boolean;
    profile?: Profile;
    isEditMode: boolean;
}

interface DeleteViewModel {
    visible: boolean;
    profileIds: number[];
}

@Component({
    selector: 'app-profile',
    templateUrl: './profile.component.html',
    styleUrls: ['./profile.component.scss'],
    standalone: false
})
export class ProfileComponent implements OnInit {
    public searchPlaceholder: string;

    public buttonsData: ButtonDataViewModel[];

    public profiles$: Observable<Profile[]>;

    public customers: Customer[];

    public detailDialog$: Observable<DetailViewModel>;

    public deleteDialog$: Observable<DeleteViewModel>;

    public regexDetails$: Observable<boolean>;

    public selectedProfiles$: Observable<Profile[]>;

    public profileNames: string[];

    public uncNetworkPaths: string[];

    @ViewChild('gridComponent')
    private readonly _gridComponent: DxDataGridComponent;

    private readonly _detailDialogSubject: BehaviorSubject<DetailViewModel> =
        new BehaviorSubject<DetailViewModel>(null);

    private readonly _deleteDialogSubject: BehaviorSubject<DeleteViewModel> =
        new BehaviorSubject<DeleteViewModel>(null);

    private readonly _regexDetailsSubject: BehaviorSubject<boolean> =
        new BehaviorSubject<boolean>(false);

    private readonly _refreshDataSubject = new BehaviorSubject<void>(undefined);

    private readonly _selectedProfilesSubject = new BehaviorSubject<Profile[]>(
        [],
    );

    private _profileService: ProfileService = inject(ProfileService);
    private _customerService: CustomerService = inject(CustomerService);

    @HostListener('window:resize')
    public onResize(): void {
        const gridInstance = this._gridComponent.instance as any;
        const columnChooserElementRef = document.querySelector(
            '.dx-datagrid-column-chooser',
        );

        if (gridInstance == undefined || columnChooserElementRef == undefined) {
            return;
        }

        gridInstance
            .getView('columnChooserView')
            ._popupContainer.option('position', {
                of: gridInstance.element(),
                my: 'right bottom',
                at: 'right bottom',
                offset: '-2 -2',
            });
    }

    public async ngOnInit(): Promise<void> {
        this.searchPlaceholder = this._profileService.getSearchPlaceHolder();
        this.buttonsData = this._profileService.getPriorityNavItems();
        this.detailDialog$ = this._detailDialogSubject.asObservable();
        this.deleteDialog$ = this._deleteDialogSubject.asObservable();
        this.regexDetails$ = this._regexDetailsSubject.asObservable();
        this.selectedProfiles$ = this._selectedProfilesSubject.asObservable();
        this.profiles$ = this._refreshDataSubject.pipe(
            switchMap(() => this._profileService.getAll()),
        );
        this.customers = await lastValueFrom(this._customerService.getAll());
        this.fetchProfileData();
    }

    public onCloseDetailDialog(event: boolean): void {
        this._detailDialogSubject.next(null);
        this.refreshData(event);
    }

    public onCloseDeleteDialog(event: boolean): void {
        this._deleteDialogSubject.next(null);
        this.refreshData(event);
    }

    public onCloseRegexDetails(): void {
        this._regexDetailsSubject.next(false);
    }

    public calculateCustomerCellValue = (rowData: Profile): string => {
        const customer = this.customers.find(
            (c) => c.id === rowData.customerId,
        );
        if (customer) {
            return customer.name;
        }
        return '';
    }

    public onButtonClick(e: any): void {
        if (e == undefined) {
            return;
        }
        switch (e.detail) {
            case 'ADD':
                this._detailDialogSubject.next({
                    visible: true,
                    title: 'generalWords.add',
                    profile: new Profile(),
                    isEditMode: false,
                });
                break;
            case 'EDIT':
                this._gridComponent.instance.getSelectedRowsData().then((values) => {
                    this._detailDialogSubject.next({
                        visible: true,
                        title: 'generalWords.edit',
                        profile: cloneDeep(
                            values[0],
                        ),
                        isEditMode: true,
                    });
                })
                break;
            case 'DELETE':
                this._gridComponent.instance.getSelectedRowKeys().then((values) => {
                    this._deleteDialogSubject.next({
                        visible: true,
                        profileIds:
                            values
                    });
                })
                this._gridComponent.instance.deselectAll();
                this._gridComponent.instance.clearSelection();

                break;
            case 'COLUMN-CHOOSER':
                this._gridComponent.instance.showColumnChooser();
                break;
            case 'REGEX':
                this._regexDetailsSubject.next(
                    !this._regexDetailsSubject.value,
                );
                break;
        }
    }

    public onSearch(e: any): void {
        if (e == undefined) {
            return;
        }

        this._gridComponent.instance.searchByText(e.detail.value);
        this._gridComponent.instance.clearSelection();
    }

    public onSelectionChanged(e: any): void {
        if (e == undefined) {
            return;
        }

        const selectedDataCount = e.component.getSelectedRowKeys().then((values) => {
            this.buttonsData[2].disabled = values.length !== 1;
            this.buttonsData[3].disabled = values.length !== 1;
            this.buttonsData[4].disabled = values.length === 0;

            this.buttonsData = Object.assign([{}], this.buttonsData);
            e.component.getSelectedRowsData().then((value) => { this._selectedProfilesSubject.next(value) });
            if (this._regexDetailsSubject.value && selectedDataCount !== 1) {
                this._regexDetailsSubject.next(false);
            }
        });
    }

    public onRowClick(e: any): void {
        if (e == undefined) {
            return;
        }

        this._gridComponent.instance.selectRows(e.key, e.event.ctrlKey);
    }

    public onRowDblClick(e: any): void {
        if (e == undefined) {
            return;
        }

        this._detailDialogSubject.next({
            visible: true,
            title: 'generalWords.edit',
            profile: cloneDeep(e.data),
            isEditMode: true,
        });
    }

    // Dynamically set minWidth of columns to fit header text
    public onContentReady(e: ContentReadyEvent): void {
        const grid: dxDataGrid = e.component;
        grid.getVisibleColumns().forEach((col: Column) => {
            const headerText = col.caption || col.dataField;
            const span = document.createElement('span');
            span.innerText = headerText;
            document.body.appendChild(span);
            const width = span.offsetWidth + 32;
            document.body.removeChild(span);
            grid.columnOption(col.dataField, 'minWidth', width);
        });
    }

    public onCustomLoad(): unknown {
        return JSON.parse(localStorage.getItem('profilesGrid'));
    }

    public onCustomSave(state: any): void {
        if (state == undefined) {
            return;
        }

        state.searchText = null;
        state.selectedRowKeys = [];
        localStorage.setItem('profilesGrid', JSON.stringify(state));
    }

    private fetchProfileData(): void {
        this._profileService
            .getAll()
            .subscribe((returnedProfiles: Profile[]) => {
                this.profileNames = returnedProfiles.map(
                    (profile) => profile.name,
                );
                this.uncNetworkPaths = returnedProfiles.map(
                    (profile) => profile.uncNetworkPath,
                );
            });
    }

    private refreshData(refresh: boolean): void {
        if (!refresh) {
            return;
        }
        this.fetchProfileData();
        this._refreshDataSubject.next();
    }

    @HostListener('window:beforeunload', ['$event'])
    public onBeforeUnload(event: Event): void {
        if (this._gridComponent && this._gridComponent.instance) {
            this._gridComponent.instance.deselectAll();
        }
    }
}
 

 -----------------------------------------------------------------------------------------

 <div class="profile__actions-bar">
    <buttons-app
        [buttonsData]="buttonsData"
        (buttonEventEmitter)="onButtonClick($event)"
        (searchBarEventEmitter)="onSearch($event)"
        [searchBoxItems]="[{name: searchPlaceholder, icon: 'fas fa-search'}]">
    </buttons-app>
</div>

<app-profile-detail
    *ngIf="detailDialog$ | async as detailDialog"
    [title]="detailDialog.title"
    [visible]="detailDialog.visible"
    [profile]="detailDialog.profile"
    [isEditMode]="detailDialog.isEditMode"
    [profileNames]="profileNames"
    [uncNetworkPaths]="uncNetworkPaths"
    (closeDialog)="onCloseDetailDialog($event)">
</app-profile-detail>

<app-profile-delete
    *ngIf="deleteDialog$ | async as deleteDialog"
    title="generalWords.delete"
    [visible]="deleteDialog.visible"
    [profileIds]="deleteDialog.profileIds"
    (closeDialog)="onCloseDeleteDialog($event)">
</app-profile-delete>

<ng-container *ngIf="profiles$ | async as profiles">
    <div class="profiles__container">
        <dx-data-grid
            #gridComponent
            class="profiles_grid"
            keyExpr="id"
            [dataSource]="profiles"
            [showRowLines]="true"
            [allowColumnResizing]="true"
            [allowColumnReordering]="true"
            [scrolling]="{ mode: 'virtual' }"
            [selection]="{ mode: 'multiple', deferred: true }"
            (onRowClick)="onRowClick($event)"
            (onSelectionChanged)="onSelectionChanged($event)"
            (onRowDblClick)="onRowDblClick($event)"
            (onContentReady)="onContentReady($event)">
            <dxo-header-filter [visible]="true"></dxo-header-filter>
            <dxo-filter-row [visible]="true"></dxo-filter-row>

            <dxo-sorting
                [ascendingText]="'devextreme.sortAscending' | translate"
                [descendingText]="'devextreme.sortDescending' | translate"
                [clearText]="'devextreme.clearSorting' | translate">
            </dxo-sorting>

            <dxo-toolbar [visible]="false"></dxo-toolbar>

            <dxo-scrolling mode="infinite"></dxo-scrolling>

            <dxo-selection
                mode="multiple"
                showCheckBoxesMode="always">
            </dxo-selection>
            <dxo-column-chooser
                mode="select"
                [enabled]="true"
                [title]="'devextreme.columnChooser' | translate">
                <dxo-search [enabled]="true"></dxo-search>
            </dxo-column-chooser>

            <dxo-state-storing
                type="custom"
                [enabled]="true"
                [customLoad]="onCustomLoad"
                [customSave]="onCustomSave">
            </dxo-state-storing>

            <dxi-column
                dataField="name"
                dataType="string"
                sortOrder="asc"
                [caption]="'properties.profile.name' | translate">
            </dxi-column>
            <dxi-column
                dataField="email"
                dataType="string"
                [caption]="'properties.customer.email' | translate">
            </dxi-column>
            <dxi-column
                dataField="viewerUrl"
                dataType="string"
                [caption]="'properties.customer.viewerUrl' | translate">
            </dxi-column>
            <dxi-column
                dataField="stabibaseDb"
                dataType="string"
                [caption]="'properties.customer.stabibaseDb' | translate">
            </dxi-column>
            <dxi-column
                dataField="asBuiltDb"
                dataType="string"
                [caption]="'properties.customer.asBuiltDb' | translate">
            </dxi-column>
            <dxi-column
                dataField="uncNetworkPath"
                dataType="string"
                [caption]="'properties.profile.uncNetworkPath' | translate">
            </dxi-column>
            <dxi-column
                dataField="uploadService"
                dataType="string"
                [caption]="'properties.profile.uploadService' | translate">
            </dxi-column>
            <dxi-column
                dataField="projectLeader"
                dataType="string"
                [caption]="'properties.profile.projectLeader' | translate">
            </dxi-column>
            <dxi-column
                dataField="description"
                dataType="string"
                [caption]="'properties.profile.description' | translate">
            </dxi-column>
            <dxi-column
                *ngIf="customers"
                [allowSorting]="true"
                [allowFiltering]="true"
                [calculateCellValue]="calculateCustomerCellValue"
                dataType="string"
                [caption]="'properties.profile.customerId' | translate">
            </dxi-column>
        </dx-data-grid>
        <app-regex
            [visible]="regexDetails$ | async"
            [selectedProfiles$]="selectedProfiles$"
            (closeDialog)="onCloseRegexDetails()">
        </app-regex>
    </div>
</ng-container> 
Editor is loading...
Leave a Comment