microting/ngx-charts

View on GitHub
demo/bubble-chart-interactive/models.ts

Summary

Maintainability
A
0 mins
Test Coverage

export class Order {
    orderCode: string;
    orderId: number;
    customerName: string;
    orderItemCount: number;
    orderFinTotal: number;
    orderCompletionPercent: number;

    constructor(json: any) {
        this.orderCode = json.orderCode;
        this.orderId = json.orderId;
        this.customerName = json.customerName;
        this.orderItemCount = json.orderItemCount;
        this.orderFinTotal = json.orderFinTotal;
        this.orderCompletionPercent = json.orderCompletionPercent;
    }

    toChart() {
        // each order gets a different 'series' object
        // the name must be unique, or ngx-charts will lump the two into the same series
        return {
            name: `Order ${this.orderCode}`,
            series: [{
                name: `${this.customerName}`,
                x: this.orderFinTotal,
                y: this.orderItemCount,
                r: 0.95,
                //
                orderId: this.orderId,
                orderCode: this.orderCode,
            }]
        };
    }
}

export class Store {
    name: string;
    storeId: number;
    storeCode: string;
    orders: Order[];
    averageOrderFinTotal: number;
    averageOrderItemCount: number;
    averageOrderCompletionPercent: number;

    constructor(json: any) {
        this.name = json.name;
        this.storeId = json.storeId;
        this.storeCode = json.storeCode;
        this.orders = json.orders.map(o => new Order(o));
        // calc props
        this.processAggregateData();
    }

    processAggregateData() {
        let finTotal = 0;
        let itmTotal = 0;
        let completionTotal = 0;
        this.orders.forEach((o) => {
            finTotal += o.orderFinTotal;
            itmTotal += o.orderItemCount;
            completionTotal += o.orderCompletionPercent;
        });
        const orderCount = this.orders.length;
        this.averageOrderFinTotal = finTotal / orderCount;
        this.averageOrderItemCount = itmTotal / orderCount;
        this.averageOrderCompletionPercent = completionTotal / orderCount;
    }

    toChartAsStore() {
        return this.orders && this.orders.length > 0 ? this.orders.map(o => o.toChart()) : [];
    }

    toChartAsEnterprise() {
        // each store gets a different 'series' object
        // the name must be unique, or ngx-charts will lump the two into the same series
        return {
            name: `Store ${this.storeCode}`,
            series: [{
                name: this.name,
                x: this.averageOrderFinTotal,
                y: this.averageOrderItemCount,
                r: this.averageOrderCompletionPercent,
                children: this.orders.map(o => o.toChart()),
                //
                storeId: this.storeId,
                storeCode: this.storeCode,
            }]
        };
    }
}

export class Enterprise {
    name: string;
    clientId: number;
    stores: Store[];
    averageOrderFinTotal: number;
    averageOrderItemCount: number;
    averageOrderCompletionPercent: number;

    constructor(json: any) {
        this.name = json.name;
        this.clientId = json.clientId;
        this.stores = json.stores.map(s => new Store(s));
        // calc props
        this.processAggregateData();
    }

    processAggregateData() {
        let finTotal = 0;
        let itmTotal = 0;
        let completionTotal = 0;
        this.stores.forEach((s) => {
            finTotal += s.averageOrderFinTotal;
            itmTotal += s.averageOrderItemCount;
            completionTotal += s.averageOrderCompletionPercent;
        });
        const storeCount = this.stores.length;
        this.averageOrderFinTotal = finTotal / storeCount;
        this.averageOrderItemCount = itmTotal / storeCount;
        this.averageOrderCompletionPercent = completionTotal / storeCount;
    }

    toChart() {
        return this.stores.map(s => s.toChartAsEnterprise());
    }
}

export class BubbleChartInteractiveServerDataModel {

    enterprise: Enterprise;
    chartDrilldownPath: any[];

    constructor() {
        this.chartDrilldownPath = [];
    }

    // updates incoming from server
    setDataFromServer(json: any) {
        this.enterprise = new Enterprise(json.data);
    }

    // Chart data
    toChart() {
        return this.chartDrilldownPath.length > 0 ?
            this.toChartAsStore(this.chartDrilldownPath[0])
            : this.toChartAsEnterprise();
    }
    toChartAsEnterprise() {
        return this.enterprise.toChart();
    }
    toChartAsStore(storeJsonObj: any) {
        const store = this.enterprise.stores.find((s) => {
            return s.storeId === storeJsonObj.storeId;
        });
        return store && store.toChartAsStore();
    }

    // drilldown 
    getChartTitle() {
        const path = this.chartDrilldownPath;
        if (path.length > 0) {
            const current = path[0];
            return `${current.seriesName} (${current.bubbleName})`;
        }
        return 'Top Level';
    }
    getDrilldownDepth() {
        return this.chartDrilldownPath.length;
    }
    resetDrilldown() {
        this.chartDrilldownPath = [];
    }
    drilldown(event) {
        // console.log(event);
        let toExpand;
        const clickedBubble = event.bubble;
        const clickedSeries = event.series;
        if (clickedBubble) {
            toExpand = clickedBubble.children;
            if (toExpand && toExpand.length) {
                // console.log('found children', toExpand);
                this.chartDrilldownPath.push({
                    storeId: clickedBubble.storeId,
                    //
                    seriesName: clickedSeries.name,
                    bubbleName: clickedBubble.name,
                });
                return toExpand;
            }
        }
    }
}