import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactoryResolver, Input, ViewChild, ViewContainerRef, NgModule } from '@angular/core';
import { DashboardWidgetService, LocalStorageService, DataService, SortOrder, CoreModule, SharedModule, ADMIN_UI_VERSION, getAppConfig, Permission } from '@ishop/admin-ui/core';
import { assertNever } from '@ishop/common/lib/shared-utils';
import { map, tap, distinctUntilChanged, shareReplay, switchMap } from 'rxjs/operators';
import { __awaiter } from 'tslib';
import { RouterModule } from '@angular/router';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import dayjs from 'dayjs';
import { BehaviorSubject } from 'rxjs';

class DashboardComponent {
    constructor(dashboardWidgetService, localStorageService, changedDetectorRef, dataService) {
        this.dashboardWidgetService = dashboardWidgetService;
        this.localStorageService = localStorageService;
        this.changedDetectorRef = changedDetectorRef;
        this.dataService = dataService;
        this.deletionMarker = '__delete__';
    }
    ngOnInit() {
        this.availableWidgetIds$ = this.dataService.client.userStatus().stream$.pipe(map(({ userStatus }) => userStatus.permissions), map(permissions => this.dashboardWidgetService.getAvailableIds(permissions)), tap(ids => (this.widgetLayout = this.initLayout(ids))));
    }
    getClassForWidth(width) {
        switch (width) {
            case 3:
                return `clr-col-12 clr-col-sm-6 clr-col-lg-3`;
            case 4:
                return `clr-col-12 clr-col-sm-6 clr-col-lg-4`;
            case 6:
                return `clr-col-12 clr-col-lg-6`;
            case 8:
                return `clr-col-12 clr-col-lg-8`;
            case 12:
                return `clr-col-12`;
            default:
                assertNever(width);
        }
    }
    getSupportedWidths(config) {
        return config.supportedWidths || [3, 4, 6, 8, 12];
    }
    setWidgetWidth(widget, width) {
        widget.width = width;
        this.recalculateLayout();
    }
    trackRow(index, row) {
        const id = row.map(item => `${item.id}:${item.width}`).join('|');
        return id;
    }
    trackRowItem(index, item) {
        return item.config;
    }
    addWidget(id) {
        var _a;
        const config = this.dashboardWidgetService.getWidgetById(id);
        if (config) {
            const width = this.getSupportedWidths(config)[0];
            const widget = {
                id,
                config,
                width,
            };
            let targetRow;
            if (this.widgetLayout && this.widgetLayout.length) {
                targetRow = this.widgetLayout[this.widgetLayout.length - 1];
            }
            else {
                targetRow = [];
                (_a = this.widgetLayout) === null || _a === void 0 ? void 0 : _a.push(targetRow);
            }
            targetRow.push(widget);
            this.recalculateLayout();
        }
    }
    removeWidget(widget) {
        widget.id = this.deletionMarker;
        this.recalculateLayout();
    }
    drop(event) {
        const { currentIndex, previousIndex, previousContainer, container } = event;
        if (previousIndex === currentIndex && previousContainer.data.index === container.data.index) {
            // Nothing changed
            return;
        }
        if (this.widgetLayout) {
            const previousLayoutRow = this.widgetLayout[previousContainer.data.index];
            const newLayoutRow = this.widgetLayout[container.data.index];
            previousLayoutRow.splice(previousIndex, 1);
            newLayoutRow.splice(currentIndex, 0, event.item.data);
            this.recalculateLayout();
        }
    }
    initLayout(availableIds) {
        const savedLayoutDef = this.localStorageService.get('dashboardWidgetLayout');
        let layoutDef;
        if (savedLayoutDef) {
            // validate all the IDs from the saved layout are still available
            layoutDef = savedLayoutDef.filter(item => availableIds.includes(item.id));
        }
        return this.dashboardWidgetService.getWidgetLayout(layoutDef);
    }
    recalculateLayout() {
        if (this.widgetLayout) {
            const flattened = this.widgetLayout
                .reduce((flat, row) => [...flat, ...row], [])
                .filter(item => item.id !== this.deletionMarker);
            const newLayoutDef = flattened.map(item => ({
                id: item.id,
                width: item.width,
            }));
            this.widgetLayout = this.dashboardWidgetService.getWidgetLayout(newLayoutDef);
            this.localStorageService.set('dashboardWidgetLayout', newLayoutDef);
            setTimeout(() => this.changedDetectorRef.markForCheck());
        }
    }
}
DashboardComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-dashboard',
                template: "<div class=\"widget-header\">\r\n    <vdr-dropdown>\r\n        <button class=\"btn btn-secondary btn-sm\" vdrDropdownTrigger>\r\n            <clr-icon shape=\"plus\"></clr-icon>\r\n            {{ 'dashboard.add-widget' | translate }}\r\n        </button>\r\n        <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n            <button\r\n                class=\"button\"\r\n                vdrDropdownItem\r\n                *ngFor=\"let id of availableWidgetIds$ | async\"\r\n                (click)=\"addWidget(id)\"\r\n            >\r\n                {{ id }}\r\n            </button>\r\n        </vdr-dropdown-menu>\r\n    </vdr-dropdown>\r\n</div>\r\n<div cdkDropListGroup>\r\n    <div\r\n        class=\"clr-row dashboard-row\"\r\n        *ngFor=\"let row of widgetLayout; index as rowIndex; trackBy: trackRow\"\r\n        cdkDropList\r\n        (cdkDropListDropped)=\"drop($event)\"\r\n        cdkDropListOrientation=\"horizontal\"\r\n        [cdkDropListData]=\"{ index: rowIndex }\"\r\n    >\r\n        <div\r\n            *ngFor=\"let widget of row; trackBy: trackRowItem\"\r\n            class=\"dashboard-item\"\r\n            [ngClass]=\"getClassForWidth(widget.width)\"\r\n            cdkDrag\r\n            [cdkDragData]=\"widget\"\r\n        >\r\n            <vdr-dashboard-widget\r\n                *vdrIfPermissions=\"widget.config.requiresPermissions || null\"\r\n                [widgetConfig]=\"widget.config\"\r\n            >\r\n                <div class=\"flex\">\r\n                    <div class=\"drag-handle\" cdkDragHandle>\r\n                        <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n                    </div>\r\n                    <vdr-dropdown>\r\n                        <button class=\"icon-button\" vdrDropdownTrigger>\r\n                            <clr-icon shape=\"ellipsis-vertical\"></clr-icon>\r\n                        </button>\r\n                        <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n                            <h4 class=\"dropdown-header\">{{ 'dashboard.widget-resize' | translate }}</h4>\r\n                            <button\r\n                                class=\"button\"\r\n                                vdrDropdownItem\r\n                                [disabled]=\"width === widget.width\"\r\n                                *ngFor=\"let width of getSupportedWidths(widget.config)\"\r\n                                (click)=\"setWidgetWidth(widget, width)\"\r\n                            >\r\n                                {{ 'dashboard.widget-width' | translate: { width: width } }}\r\n                            </button>\r\n                            <div class=\"dropdown-divider\" role=\"separator\"></div>\r\n                            <button class=\"button\" vdrDropdownItem (click)=\"removeWidget(widget)\">\r\n                                <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n                                {{ 'dashboard.remove-widget' | translate }}\r\n                            </button>\r\n                        </vdr-dropdown-menu>\r\n                    </vdr-dropdown>\r\n                </div>\r\n            </vdr-dashboard-widget>\r\n        </div>\r\n    </div>\r\n</div>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [".widget-header{display:flex;justify-content:flex-end}.placeholder{color:var(--color-grey-300);text-align:center}.placeholder .version{font-size:3em;margin:24px;line-height:1em}.placeholder ::ng-deep .clr-i-outline{fill:var(--color-grey-200)}vdr-dashboard-widget{margin-bottom:24px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.dashboard-row{padding:0;border-width:1;margin-bottom:6px;transition:padding .2s,margin .2s}.dashboard-row.cdk-drop-list-dragging,.dashboard-row.cdk-drop-list-receiving{border:1px dashed var(--color-component-border-200);padding:6px}.dashboard-row.cdk-drop-list-dragging .dashboard-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}"]
            },] }
];
DashboardComponent.ctorParameters = () => [
    { type: DashboardWidgetService },
    { type: LocalStorageService },
    { type: ChangeDetectorRef },
    { type: DataService }
];

class DashboardWidgetComponent {
    constructor(componentFactoryResolver) {
        this.componentFactoryResolver = componentFactoryResolver;
    }
    ngAfterViewInit() {
        this.loadWidget();
    }
    loadWidget() {
        return __awaiter(this, void 0, void 0, function* () {
            const loadComponentResult = this.widgetConfig.loadComponent();
            const componentType = loadComponentResult instanceof Promise ? yield loadComponentResult : loadComponentResult;
            this.componentRef = this.portal.createComponent(this.componentFactoryResolver.resolveComponentFactory(componentType));
            this.componentRef.changeDetectorRef.markForCheck();
        });
    }
    ngOnDestroy() {
        if (this.componentRef) {
            this.componentRef.destroy();
        }
    }
}
DashboardWidgetComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-dashboard-widget',
                template: "<div class=\"card\">\r\n    <div class=\"card-header\">\r\n        <div class=\"title\">\r\n            <ng-container *ngIf=\"widgetConfig.title as title\">{{ title | translate }}</ng-container>\r\n        </div>\r\n        <div class=\"controls\">\r\n            <ng-content></ng-content>\r\n        </div>\r\n    </div>\r\n    <div class=\"card-block\">\r\n        <ng-template #portal></ng-template>\r\n    </div>\r\n</div>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [":host{display:block}.card{margin-top:0;min-height:200px}.card-header{display:flex;justify-content:space-between}"]
            },] }
];
DashboardWidgetComponent.ctorParameters = () => [
    { type: ComponentFactoryResolver }
];
DashboardWidgetComponent.propDecorators = {
    widgetConfig: [{ type: Input }],
    portal: [{ type: ViewChild, args: ['portal', { read: ViewContainerRef },] }]
};

const dashboardRoutes = [
    {
        path: '',
        component: DashboardComponent,
        pathMatch: 'full',
    },
];

class LatestOrdersWidgetComponent {
    constructor(dataService) {
        this.dataService = dataService;
    }
    ngOnInit() {
        this.latestOrders$ = this.dataService.order
            .getOrders({
            take: 10,
            filter: {
                active: { eq: false },
            },
            sort: {
                orderPlacedAt: SortOrder.DESC,
            },
        })
            .refetchOnChannelChange()
            .mapStream(data => data.orders.items);
    }
}
LatestOrdersWidgetComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-latest-orders-widget',
                template: "<vdr-data-table [items]=\"latestOrders$ | async\">\r\n    <ng-template let-order=\"item\">\r\n        <td class=\"left align-middle\">\r\n            {{ order.code }}\r\n            <vdr-order-state-label [state]=\"order.state\"></vdr-order-state-label>\r\n        </td>\r\n        <td class=\"left align-middle\">\r\n            <vdr-customer-label [customer]=\"order.customer\"></vdr-customer-label>\r\n        </td>\r\n        <td class=\"left align-middle\">{{ order.total | localeCurrency: order.currencyCode }}</td>\r\n        <td class=\"left align-middle\">{{ order.orderPlacedAt | timeAgo }}</td>\r\n        <td class=\"right align-middle\">\r\n            <vdr-table-row-action\r\n                iconShape=\"shopping-cart\"\r\n                [label]=\"'common.open' | translate\"\r\n                [linkTo]=\"['/orders/', order.id]\"\r\n            ></vdr-table-row-action>\r\n        </td>\r\n    </ng-template>\r\n</vdr-data-table>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: ["vdr-data-table ::ng-deep table{margin-top:0}"]
            },] }
];
LatestOrdersWidgetComponent.ctorParameters = () => [
    { type: DataService }
];
class LatestOrdersWidgetModule {
}
LatestOrdersWidgetModule.decorators = [
    { type: NgModule, args: [{
                imports: [CoreModule, SharedModule],
                declarations: [LatestOrdersWidgetComponent],
            },] }
];

class OrderSummaryWidgetComponent {
    constructor(dataService) {
        this.dataService = dataService;
        this.today = new Date();
        this.yesterday = new Date(new Date().setDate(this.today.getDate() - 1));
        this.selection$ = new BehaviorSubject({
            timeframe: 'day',
            date: this.today,
        });
    }
    ngOnInit() {
        this.dateRange$ = this.selection$.pipe(distinctUntilChanged(), map(selection => {
            return {
                start: dayjs(selection.date).startOf(selection.timeframe).toDate(),
                end: dayjs(selection.date).endOf(selection.timeframe).toDate(),
            };
        }), shareReplay(1));
        const orderSummary$ = this.dateRange$.pipe(switchMap(({ start, end }) => {
            return this.dataService.order
                .getOrderSummary(start, end)
                .refetchOnChannelChange()
                .mapStream(data => data.orders);
        }), shareReplay(1));
        this.totalOrderCount$ = orderSummary$.pipe(map(res => res.totalItems));
        this.totalOrderValue$ = orderSummary$.pipe(map(res => res.items.reduce((total, order) => total + order.total, 0) / 100));
        this.currencyCode$ = this.dataService.settings
            .getActiveChannel()
            .refetchOnChannelChange()
            .mapStream(data => data.activeChannel.currencyCode || undefined);
    }
}
OrderSummaryWidgetComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-order-summary-widget',
                template: "<div class=\"stats\">\r\n    <div class=\"stat\">\r\n        <div class=\"stat-figure\">{{ totalOrderCount$ | async }}</div>\r\n        <div class=\"stat-label\">{{ 'dashboard.total-orders' | translate }}</div>\r\n    </div>\r\n    <div class=\"stat\">\r\n        <div class=\"stat-figure\">\r\n            {{ totalOrderValue$ | async | currency: (currencyCode$ | async) || undefined }}\r\n        </div>\r\n        <div class=\"stat-label\">{{ 'dashboard.total-order-value' | translate }}</div>\r\n    </div>\r\n</div>\r\n<div class=\"footer\">\r\n    <div class=\"btn-group btn-outline-primary btn-sm\" *ngIf=\"selection$ | async as selection\">\r\n        <button class=\"btn\" [class.btn-primary]=\"selection.date === today\" (click)=\"selection$.next({timeframe: 'day', date: today})\">\r\n            {{ 'dashboard.today' | translate }}\r\n        </button>\r\n        <button class=\"btn\" [class.btn-primary]=\"selection.date === yesterday\" (click)=\"selection$.next({timeframe: 'day', date: yesterday})\">\r\n            {{ 'dashboard.yesterday' | translate }}\r\n        </button>\r\n        <button class=\"btn\" [class.btn-primary]=\"selection.timeframe === 'week'\" (click)=\"selection$.next({timeframe: 'week'})\">\r\n            {{ 'dashboard.thisWeek' | translate }}\r\n        </button>\r\n        <button class=\"btn\" [class.btn-primary]=\"selection.timeframe === 'month'\" (click)=\"selection$.next({timeframe: 'month'})\">\r\n            {{ 'dashboard.thisMonth' | translate }}\r\n        </button>\r\n    </div>\r\n\r\n    <div class=\"date-range p5\" *ngIf=\"dateRange$ | async as range\">\r\n        {{ range.start | localeDate }} - {{ range.end | localeDate }}\r\n    </div>\r\n</div>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [".stats{display:flex;justify-content:space-evenly}.stat{text-align:center}.stat-figure{font-size:2rem;line-height:3rem}.stat-label{text-transform:uppercase}.date-range{margin-top:0}.footer{margin-top:24px;display:flex;flex-direction:column;justify-content:space-between}@media screen and (min-width:768px){.footer{flex-direction:row}}"]
            },] }
];
OrderSummaryWidgetComponent.ctorParameters = () => [
    { type: DataService }
];
class OrderSummaryWidgetModule {
}
OrderSummaryWidgetModule.decorators = [
    { type: NgModule, args: [{
                imports: [CoreModule],
                declarations: [OrderSummaryWidgetComponent],
            },] }
];

class TestWidgetComponent {
}
TestWidgetComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-test-widget',
                template: "<p>This is a test widget!</p>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [""]
            },] }
];
class TestWidgetModule {
}
TestWidgetModule.decorators = [
    { type: NgModule, args: [{
                declarations: [TestWidgetComponent],
            },] }
];

class WelcomeWidgetComponent {
    constructor(dataService) {
        this.dataService = dataService;
        this.version = ADMIN_UI_VERSION;
        this.brand = getAppConfig().brand;
        this.hideVendureBranding = getAppConfig().hideVendureBranding;
        this.hideVersion = getAppConfig().hideVersion;
    }
    ngOnInit() {
        this.administrator$ = this.dataService.administrator
            .getActiveAdministrator()
            .mapStream(data => data.activeAdministrator || null);
    }
}
WelcomeWidgetComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-welcome-widget',
                template: "<div *ngIf=\"administrator$ | async as administrator\">\r\n    <h4 class=\"h4\">\r\n        Welcome, {{ administrator.firstName }} {{ administrator.lastName }}<br />\r\n        <small class=\"p5\">Last login: {{ administrator.user.lastLogin | timeAgo }}</small>\r\n    </h4>\r\n\r\n    <p class=\"p5\" *ngIf=\"!hideVendureBranding || !hideVersion\">\r\n        {{ hideVendureBranding ? '' : 'Vendure' }} {{ hideVersion ? '' : ('Admin UI v' + version) }}\r\n    </p>\r\n</div>\r\n<div class=\"placeholder\">\r\n    <clr-icon shape=\"line-chart\" size=\"128\"></clr-icon>\r\n</div>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [":host{display:flex;justify-content:space-between}.placeholder{color:var(--color-grey-200)}"]
            },] }
];
WelcomeWidgetComponent.ctorParameters = () => [
    { type: DataService }
];
class WelcomeWidgetModule {
}
WelcomeWidgetModule.decorators = [
    { type: NgModule, args: [{
                imports: [CoreModule],
                declarations: [WelcomeWidgetComponent],
            },] }
];

const DEFAULT_DASHBOARD_WIDGET_LAYOUT = [
    { id: 'welcome', width: 12 },
    { id: 'orderSummary', width: 6 },
    { id: 'latestOrders', width: 6 },
];
const ɵ0 = () => WelcomeWidgetComponent, ɵ1 = () => OrderSummaryWidgetComponent, ɵ2 = () => LatestOrdersWidgetComponent, ɵ3 = () => TestWidgetComponent;
const DEFAULT_WIDGETS = {
    welcome: {
        loadComponent: ɵ0,
    },
    orderSummary: {
        title: marker('dashboard.orders-summary'),
        loadComponent: ɵ1,
        requiresPermissions: [Permission.ReadOrder],
    },
    latestOrders: {
        title: marker('dashboard.latest-orders'),
        loadComponent: ɵ2,
        supportedWidths: [6, 8, 12],
        requiresPermissions: [Permission.ReadOrder],
    },
    testWidget: {
        title: 'Test Widget',
        loadComponent: ɵ3,
    },
};

class DashboardModule {
    constructor(dashboardWidgetService) {
        Object.entries(DEFAULT_WIDGETS).map(([id, config]) => dashboardWidgetService.registerWidget(id, config));
        if (dashboardWidgetService.getDefaultLayout().length === 0) {
            dashboardWidgetService.setDefaultLayout(DEFAULT_DASHBOARD_WIDGET_LAYOUT);
        }
    }
}
DashboardModule.decorators = [
    { type: NgModule, args: [{
                imports: [SharedModule, RouterModule.forChild(dashboardRoutes)],
                declarations: [DashboardComponent, DashboardWidgetComponent],
            },] }
];
DashboardModule.ctorParameters = () => [
    { type: DashboardWidgetService }
];

// This file was generated by the build-public-api.ts script

/**
 * Generated bundle index. Do not edit.
 */

export { DEFAULT_DASHBOARD_WIDGET_LAYOUT, DEFAULT_WIDGETS, DashboardComponent, DashboardModule, DashboardWidgetComponent, LatestOrdersWidgetComponent, LatestOrdersWidgetModule, OrderSummaryWidgetComponent, OrderSummaryWidgetModule, TestWidgetComponent, TestWidgetModule, WelcomeWidgetComponent, WelcomeWidgetModule, dashboardRoutes, ɵ0, ɵ1, ɵ2, ɵ3 };
//# sourceMappingURL=ishop-admin-ui-dashboard.js.map
