Compare commits

8 changed files with 523 additions and 145 deletions
@@ -0,0 +1,4 @@
export interface XSizeModel {
width?: number;
height?: number;
}
@@ -9,7 +9,7 @@
[class.fullscreen]="getValue(isFullscreen) | async" [class.fullscreen]="getValue(isFullscreen) | async"
> >
<!-- Card Header --> <!-- Card Header -->
<mat-card-header class="x-header" *ngIf="getValue(showHeader) | async"> <mat-card-header #cardHeader class="x-header" *ngIf="getValue(showHeader) | async">
<!-- Avatar Image --> <!-- Avatar Image -->
<section <section
*ngIf="notEmptyValue(avatarUrl) | async" *ngIf="notEmptyValue(avatarUrl) | async"
@@ -57,6 +57,7 @@
<!-- Card Image --> <!-- Card Image -->
<img <img
mat-card-image mat-card-image
#cardImage
class="x-image" class="x-image"
[src]="getValue(imageUrl) | async" [src]="getValue(imageUrl) | async"
*ngIf="notEmptyValue(imageUrl) | async" *ngIf="notEmptyValue(imageUrl) | async"
@@ -64,18 +65,18 @@
/> />
<!-- Card Content --> <!-- Card Content -->
<mat-card-content class="x-content" *ngIf="getValue(showContent) | async"> <mat-card-content #cardContent class="x-content" *ngIf="getValue(showContent) | async">
<ng-content></ng-content> <ng-content></ng-content>
</mat-card-content> </mat-card-content>
<!-- Card Actions --> <!-- Card Actions -->
<mat-card-actions class="x-actions" *ngIf="getValue(showActions) | async"> <mat-card-actions #cardActions class="x-actions" *ngIf="getValue(showActions) | async">
<ng-content select="[actions]"></ng-content> <ng-content select="[actions]"></ng-content>
</mat-card-actions> </mat-card-actions>
<!-- Card Footer --> <!-- Card Footer -->
<mat-card-footer <mat-card-footer
#footer #cardFooter
class="x-footer" class="x-footer"
*ngIf="getValue(showFooter) | async" *ngIf="getValue(showFooter) | async"
> >
@@ -19,7 +19,6 @@
&:fullscreen { &:fullscreen {
border-radius: 0; border-radius: 0;
background-color: var(--full-screen-bg, #ffffff);
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
@@ -54,7 +53,7 @@
height: var(--height, inherit); height: var(--height, inherit);
} }
.x-card.page-card { .x-card.page-card:not(.fullscreen) {
@include push-auto(); @include push-auto();
@include applyWidthHeight(); @include applyWidthHeight();
@include m-tb($d-l); @include m-tb($d-l);
@@ -5,8 +5,18 @@ import {
} from './x-card.typings'; } from './x-card.typings';
import { Subject, Subscription } from 'rxjs'; import { Subject, Subscription } from 'rxjs';
import { concatMap, map } from 'rxjs/operators'; import { concatMap, map } from 'rxjs/operators';
import { nameof, isNullOrEmptyString } from 'x-framework-core'; import { XSizeModel } from '../classes/x-size.model.';
import { Component, ChangeDetectionStrategy } from '@angular/core'; import {
nameof,
isNullOrEmptyString,
isNullOrUndefined,
} from 'x-framework-core';
import {
Component,
ChangeDetectionStrategy,
ElementRef,
ViewChild,
} from '@angular/core';
@Component({ @Component({
// tslint:disable-next-line:component-selector // tslint:disable-next-line:component-selector
@@ -22,22 +32,107 @@ export class XCardComponent extends XCardContainerComponent {
private ACTION_PROVIDER_SUBSCRIPTION: Subscription; private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
// //
// Full Screen ... //#region Card Elements ....
private IS_FULLSCREEN: boolean = false; private CARD_IMAGE: ElementRef<HTMLElement> = undefined;
public set isFullscreen(v: boolean) { private CARD_HEADER: ElementRef<HTMLElement> = undefined;
// private CARD_FOOTER: ElementRef<HTMLElement> = undefined;
const isChanged = v != this.IS_FULLSCREEN; private CARD_CONTENT: ElementRef<HTMLElement> = undefined;
private CARD_ACTIONS: ElementRef<HTMLElement> = undefined;
// @ViewChild('cardImage', { static: false })
this.IS_FULLSCREEN = v; set cardImage(v: ElementRef<HTMLElement>) {
this.CARD_IMAGE = v;
} }
public get isFullscreen() {
return this.IS_FULLSCREEN; @ViewChild('cardHeader', { static: false })
set cardHeader(v: ElementRef<HTMLElement>) {
this.CARD_HEADER = v;
}
@ViewChild('cardFooter', { static: false })
set cardFooter(v: ElementRef<HTMLElement>) {
this.CARD_FOOTER = v;
}
@ViewChild('cardContent', { static: false })
set cardContent(v: ElementRef<HTMLElement>) {
this.CARD_CONTENT = v;
}
@ViewChild('cardActions', { static: false })
set cardActions(v: ElementRef<HTMLElement>) {
this.CARD_ACTIONS = v;
}
get cardImage() {
return this.CARD_IMAGE;
}
get cardHeader() {
return this.CARD_HEADER;
}
get cardFooter() {
return this.CARD_FOOTER;
}
get cardContent() {
return this.CARD_CONTENT;
}
get cardActions() {
return this.CARD_ACTIONS;
} }
//#endregion //#endregion
//
//#region Full Screen ...
//
private IS_FULLSCREEN: boolean = false;
set isFullscreen(v: boolean) {
//
const isChanged = v != this.IS_FULLSCREEN;
if (isChanged) {
//
this.actionProvider.next({
action: XCardAction.FullScreenToggled,
payload: v,
});
}
//
this.IS_FULLSCREEN = v;
}
get isFullscreen() {
return this.IS_FULLSCREEN;
}
//#endregion
//#endregion
// //
//#region LifeCycles ... //#region LifeCycles ...
onInit() {
super.onInit();
//
// Listen for fullscreen change events (handles ESC key and browser UI)
document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);
document.addEventListener(
'webkitfullscreenchange',
this.fullscreenChangeHandler,
);
document.addEventListener(
'mozfullscreenchange',
this.fullscreenChangeHandler,
);
document.addEventListener(
'MSFullscreenChange',
this.fullscreenChangeHandler,
);
}
onChange(changeKeys: string[]) { onChange(changeKeys: string[]) {
super.onChange(changeKeys); super.onChange(changeKeys);
@@ -58,6 +153,24 @@ export class XCardComponent extends XCardContainerComponent {
// //
this.unregisterActionProvider(); this.unregisterActionProvider();
//
document.removeEventListener(
'fullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'webkitfullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'mozfullscreenchange',
this.fullscreenChangeHandler,
);
document.removeEventListener(
'MSFullscreenChange',
this.fullscreenChangeHandler,
);
} }
registerViewHandlers() { registerViewHandlers() {
@@ -149,6 +262,124 @@ export class XCardComponent extends XCardContainerComponent {
await this.enterFullscreen(); await this.enterFullscreen();
} }
} }
//
//#region Size Calculating ...
public calculateImageSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (
isNullOrUndefined(this.CARD_IMAGE) ||
isNullOrUndefined(this.CARD_IMAGE.nativeElement)
) {
return result;
}
//
result = {
width: this.CARD_IMAGE.nativeElement.offsetWidth,
height: this.CARD_IMAGE.nativeElement.offsetHeight,
};
//
return result;
}
public calculateHeaderSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (
isNullOrUndefined(this.CARD_HEADER) ||
isNullOrUndefined(this.CARD_HEADER.nativeElement)
) {
return result;
}
//
result = {
width: this.CARD_HEADER.nativeElement.offsetWidth,
height: this.CARD_HEADER.nativeElement.offsetHeight,
};
//
return result;
}
public calculateFooterSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (
isNullOrUndefined(this.CARD_FOOTER) ||
isNullOrUndefined(this.CARD_FOOTER.nativeElement)
) {
return result;
}
//
result = {
width: this.CARD_FOOTER.nativeElement.offsetWidth,
height: this.CARD_FOOTER.nativeElement.offsetHeight,
};
//
return result;
}
public calculateContentSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (
isNullOrUndefined(this.CARD_CONTENT) ||
isNullOrUndefined(this.CARD_CONTENT.nativeElement)
) {
return result;
}
//
result = {
width: this.CARD_CONTENT.nativeElement.offsetWidth,
height: this.CARD_CONTENT.nativeElement.offsetHeight,
};
//
return result;
}
public calculateActionsSize() {
//
let result: XSizeModel = undefined;
//
// Validate ...
if (
isNullOrUndefined(this.CARD_ACTIONS) ||
isNullOrUndefined(this.CARD_ACTIONS.nativeElement)
) {
return result;
}
//
result = {
width: this.CARD_ACTIONS.nativeElement.offsetWidth,
height: this.CARD_ACTIONS.nativeElement.offsetHeight,
};
//
return result;
}
//#endregion
//#endregion //#endregion
// //
@@ -211,6 +442,22 @@ export class XCardComponent extends XCardContainerComponent {
} }
//#endregion //#endregion
//
//#region Fullscreen ...
private fullscreenChangeHandler = () => {
//
const isFullscreen = !!(
document.fullscreenElement ||
(document as any).webkitFullscreenElement ||
(document as any).mozFullScreenElement ||
(document as any).msFullscreenElement
);
//
this.isFullscreen = isFullscreen;
this.detectChanges();
};
private canUseFullscreen(): boolean { private canUseFullscreen(): boolean {
return !!( return !!(
document.fullscreenEnabled || document.fullscreenEnabled ||
@@ -220,4 +467,5 @@ export class XCardComponent extends XCardContainerComponent {
); );
} }
//#endregion //#endregion
//#endregion
} }
@@ -33,16 +33,19 @@ import { X_FRAMEWORK_COMPONENTS_CONFIG } from '../tokens/x-injectable-tokens';
import { XFrameworkComponentsConfig } from '../config/x-framework-components.config'; import { XFrameworkComponentsConfig } from '../config/x-framework-components.config';
export enum XCardAction { export enum XCardAction {
//
Refresh = 'refresh', Refresh = 'refresh',
//
ExitFullScreen = 'exit_full_screen', ExitFullScreen = 'exit_full_screen',
EnterFullScreen = 'enter_full_screen', EnterFullScreen = 'enter_full_screen',
ToggleFullScreen = 'toggle_full_screen', ToggleFullScreen = 'toggle_full_screen',
//
FullScreenToggled = 'full_screen_toggled',
} }
export type XCardActionIdentifier = XCardAction | string; export type XCardActionIdentifier = XCardAction | string;
export interface XCardActionModel export interface XCardActionModel extends XBaseActionModel<XCardActionIdentifier> {}
extends XBaseActionModel<XCardActionIdentifier> {}
// //
//#region Container ... //#region Container ...
@@ -190,7 +193,7 @@ export abstract class XCardContainerComponent
public ruler: ViewportRuler, public ruler: ViewportRuler,
public zone: NgZone, public zone: NgZone,
public changeDetector: ChangeDetectorRef, public changeDetector: ChangeDetectorRef,
protected propertyProvider: XCardContainer protected propertyProvider: XCardContainer,
) { ) {
super( super(
config, config,
@@ -199,7 +202,7 @@ export abstract class XCardContainerComponent
renderer, renderer,
ruler, ruler,
zone, zone,
changeDetector changeDetector,
); );
} }
//#endregion //#endregion
@@ -207,37 +210,37 @@ export abstract class XCardContainerComponent
// //
//#region Abstract ... //#region Abstract ...
public extractProps( public extractProps(
container?: IXCardContainer container?: IXCardContainer,
): Observable<IXCardContainer> { ): Observable<IXCardContainer> {
return forkJoin({ return forkJoin({
// //
cssClass: this.getArrayValue( cssClass: this.getArrayValue(
container ? container.cssClass : this.cssClass container ? container.cssClass : this.cssClass,
), ),
// //
color: this.getValue(container ? container.color : this.color), color: this.getValue(container ? container.color : this.color),
foregroundColor: this.getValue( foregroundColor: this.getValue(
container ? container.foregroundColor : this.foregroundColor container ? container.foregroundColor : this.foregroundColor,
), ),
// //
showHeader: this.getValue( showHeader: this.getValue(
container ? container.showHeader : this.showHeader container ? container.showHeader : this.showHeader,
), ),
title: this.getValue(container ? container.title : this.title), title: this.getValue(container ? container.title : this.title),
subTitle: this.getValue(container ? container.subTitle : this.subTitle), subTitle: this.getValue(container ? container.subTitle : this.subTitle),
avatarUrl: this.getValue( avatarUrl: this.getValue(
container ? container.avatarUrl : this.avatarUrl container ? container.avatarUrl : this.avatarUrl,
), ),
avatarTemplate: this.getValue( avatarTemplate: this.getValue(
container ? container.avatarTemplate : this.avatarTemplate container ? container.avatarTemplate : this.avatarTemplate,
), ),
// //
imageUrl: this.getValue(container ? container.imageUrl : this.imageUrl), imageUrl: this.getValue(container ? container.imageUrl : this.imageUrl),
imageDescription: this.getValue( imageDescription: this.getValue(
container ? container.imageDescription : this.imageDescription container ? container.imageDescription : this.imageDescription,
), ),
// //
@@ -245,13 +248,13 @@ export abstract class XCardContainerComponent
// //
showContent: this.getValue( showContent: this.getValue(
container ? container.showContent : this.showContent container ? container.showContent : this.showContent,
), ),
showActions: this.getValue( showActions: this.getValue(
container ? container.showActions : this.showActions container ? container.showActions : this.showActions,
), ),
showFooter: this.getValue( showFooter: this.getValue(
container ? container.showFooter : this.showFooter container ? container.showFooter : this.showFooter,
), ),
}).pipe( }).pipe(
map((data) => { map((data) => {
@@ -264,7 +267,7 @@ export abstract class XCardContainerComponent
? container.actionProvider ? container.actionProvider
: this.actionProvider, : this.actionProvider,
}; };
}) }),
); );
} }
//#endregion //#endregion
@@ -288,8 +291,7 @@ type TXComponentCardContainer = {
}; };
export interface IXComponentCardContainer export interface IXComponentCardContainer
extends TXComponentCardContainer, extends TXComponentCardContainer, IXBaseComponentContainer {
IXBaseComponentContainer {
isInPage: XStandardType<boolean>; isInPage: XStandardType<boolean>;
wrapWithCard: XStandardType<boolean>; wrapWithCard: XStandardType<boolean>;
} }
@@ -403,7 +405,7 @@ export abstract class XComponentCardContainerComponent
public ruler: ViewportRuler, public ruler: ViewportRuler,
public zone: NgZone, public zone: NgZone,
public changeDetector: ChangeDetectorRef, public changeDetector: ChangeDetectorRef,
protected propertyProvider: XComponentCardContainer protected propertyProvider: XComponentCardContainer,
) { ) {
super( super(
config, config,
@@ -412,7 +414,7 @@ export abstract class XComponentCardContainerComponent
renderer, renderer,
ruler, ruler,
zone, zone,
changeDetector changeDetector,
); );
} }
//#endregion //#endregion
@@ -420,34 +422,34 @@ export abstract class XComponentCardContainerComponent
// //
//#region Abstract ... //#region Abstract ...
public extractProps( public extractProps(
container?: IXComponentCardContainer container?: IXComponentCardContainer,
): Observable<IXComponentCardContainer> { ): Observable<IXComponentCardContainer> {
return forkJoin({ return forkJoin({
// //
isInPage: this.getValue(container ? container.isInPage : this.isInPage), isInPage: this.getValue(container ? container.isInPage : this.isInPage),
wrapWithCard: this.getValue( wrapWithCard: this.getValue(
container ? container.wrapWithCard : this.wrapWithCard container ? container.wrapWithCard : this.wrapWithCard,
), ),
cardCssClass: this.getValue( cardCssClass: this.getValue(
container ? container.cardCssClass : this.cardCssClass container ? container.cardCssClass : this.cardCssClass,
), ),
cardColor: this.getValue( cardColor: this.getValue(
container ? container.cardColor : this.cardColor container ? container.cardColor : this.cardColor,
), ),
cardForegroundColor: this.getValue( cardForegroundColor: this.getValue(
container ? container.cardForegroundColor : this.cardForegroundColor container ? container.cardForegroundColor : this.cardForegroundColor,
), ),
cardTitle: this.getValue( cardTitle: this.getValue(
container ? container.cardTitle : this.cardTitle container ? container.cardTitle : this.cardTitle,
), ),
cardSubTitle: this.getValue( cardSubTitle: this.getValue(
container ? container.cardSubTitle : this.cardSubTitle container ? container.cardSubTitle : this.cardSubTitle,
), ),
cardShowFooter: this.getValue( cardShowFooter: this.getValue(
container ? container.cardShowFooter : this.cardShowFooter container ? container.cardShowFooter : this.cardShowFooter,
), ),
cardShowActions: this.getValue( cardShowActions: this.getValue(
container ? container.cardShowActions : this.cardShowActions container ? container.cardShowActions : this.cardShowActions,
), ),
}).pipe( }).pipe(
map((data) => { map((data) => {
@@ -460,7 +462,7 @@ export abstract class XComponentCardContainerComponent
? container.cardActionProvider ? container.cardActionProvider
: this.cardActionProvider, : this.cardActionProvider,
}; };
}) }),
); );
} }
//#endregion //#endregion
@@ -1,8 +1,10 @@
<!-- Component Template --> <!-- Component Template -->
<ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef"> <ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef">
<x-card <x-card
#chartCard
class="x-card" class="x-card"
[showActions]="true" [showActions]="true"
[actionProvider]="cardActionProvider"
[color]="getValue(cardColor) | async" [color]="getValue(cardColor) | async"
[ngClass]="getValue(cssClass) | async" [ngClass]="getValue(cssClass) | async"
[isInPage]="getValue(isInPage) | async" [isInPage]="getValue(isInPage) | async"
@@ -41,6 +43,7 @@
> >
<!-- Toolbar --> <!-- Toolbar -->
<x-action-bar <x-action-bar
#chartActionBar
[color]="actionBarColor" [color]="actionBarColor"
[cssClass]="actionBarCssClass" [cssClass]="actionBarCssClass"
[actionProvider]="actionBarActionProvider" [actionProvider]="actionBarActionProvider"
@@ -2,7 +2,6 @@ import {
Component, Component,
ViewChild, ViewChild,
ElementRef, ElementRef,
HostListener,
ChangeDetectionStrategy, ChangeDetectionStrategy,
} from '@angular/core'; } from '@angular/core';
import { import {
@@ -29,9 +28,10 @@ import {
XChartDrilldownEvent, XChartDrilldownEvent,
XChartContainerComponent, XChartContainerComponent,
XChartStoryboardBeatInfo, XChartStoryboardBeatInfo,
XChartColorFormatterOpts,
} from './x-chart.typings'; } from './x-chart.typings';
import { Subscription } from 'rxjs';
import ApexCharts from 'apexcharts'; import ApexCharts from 'apexcharts';
import { Subject, Subscription } from 'rxjs';
import { import {
XActionBarItem, XActionBarItem,
XActionBarItemSlot, XActionBarItemSlot,
@@ -39,6 +39,8 @@ import {
} from '../x-action-bar/x-action-bar.typings'; } from '../x-action-bar/x-action-bar.typings';
import { XIconNames } from '../x-icon/x-icon.typings'; import { XIconNames } from '../x-icon/x-icon.typings';
import { XCardAction } from '../x-card/x-card.typings'; import { XCardAction } from '../x-card/x-card.typings';
import { XCardComponent } from '../x-card/x-card.component';
import { XActionBarComponent } from '../x-action-bar/x-action-bar.component';
@Component({ @Component({
selector: 'x-chart', selector: 'x-chart',
@@ -50,39 +52,70 @@ export class XChartComponent extends XChartContainerComponent {
// //
//#region Props ... //#region Props ...
// //
private CHART_CONTAINER: ElementRef | undefined; //#region Chart Container ...
//
private CHART_CONTAINER: ElementRef = undefined;
@ViewChild('chartContainer', { static: false }) @ViewChild('chartContainer', { static: false })
set chartContainer(el: ElementRef | undefined) { set chartContainer(v: ElementRef) {
// //
if (isNullOrUndefined(el)) { if (isNullOrUndefined(v)) {
// //
this.destroyComponent(); this.destroyComponent();
return; return;
} }
// //
this.CHART_CONTAINER = el; this.CHART_CONTAINER = v;
this.initializeComponent(); this.initializeComponent();
} }
get chartContainer() { get chartContainer() {
return this.CHART_CONTAINER; return this.CHART_CONTAINER;
} }
//#endregion
// //
@HostListener('resize', ['$event']) //#region Chart ActionBar ...
onResize(event: any) { //
private CHART_ACTIONBAR: XActionBarComponent = undefined;
@ViewChild('chartActionBar', { static: false })
set chartActionBar(v: XActionBarComponent) {
this.CHART_ACTIONBAR = v;
}
get chartActionBar() {
return this.CHART_ACTIONBAR;
}
//#endregion
//
//#region Chart Card ...
//
private CHART_CARD: XCardComponent = undefined;
@ViewChild('chartCard', { static: false })
set chartCard(v: XCardComponent) {
// //
if (isNullOrUndefined(this.chartInstance)) { if (!isNullOrUndefined(v)) {
return; this.registerCardActionProvider();
} else {
this.unregisterCardActionProvider();
} }
// //
// TODO: Complete this ... this.CHART_CARD = v;
// this.chartInstance.updateOptions();
} }
get chartCard() {
return this.CHART_CARD;
}
//#endregion
//
private ORIGINAL_HEIGHT: string = undefined;
// //
private CHART_OPTIONS: XChartOptions = null; private CHART_OPTIONS: XChartOptions = null;
@@ -91,6 +124,7 @@ export class XChartComponent extends XChartContainerComponent {
// //
private ACTION_PROVIDER_SUBSCRIPTION: Subscription; private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
private CARD_ACTION_PROVIDER_SUBSCRIPTION: Subscription;
// //
readonly IconNames = Object.assign({}, XIconNames); readonly IconNames = Object.assign({}, XIconNames);
@@ -340,6 +374,7 @@ export class XChartComponent extends XChartContainerComponent {
// //
this.destroyComponent(); this.destroyComponent();
this.unregisterActionProvider(); this.unregisterActionProvider();
this.unregisterCardActionProvider();
} }
//#endregion //#endregion
@@ -672,47 +707,8 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
// Handle Fullscreen Toggle using Card ...
this.cardActionProvider.next({ action: XCardAction.ToggleFullScreen }); this.cardActionProvider.next({ action: XCardAction.ToggleFullScreen });
//
return;
//
const chartWrapper = this.chartContainer.nativeElement;
const doc = document as any;
//
// Check if the chart wrapper is currently in fullscreen mode
const isFullscreen =
doc.fullscreenElement === chartWrapper ||
doc.msFullscreenElement === chartWrapper ||
doc.mozFullScreenElement === chartWrapper ||
doc.webkitFullscreenElement === chartWrapper;
if (!isFullscreen) {
//
// Enter Fullscreen
if (chartWrapper.requestFullscreen) {
await chartWrapper.requestFullscreen();
} else if (chartWrapper.webkitRequestFullscreen) {
await chartWrapper.webkitRequestFullscreen();
} else if (chartWrapper.mozRequestFullScreen) {
await chartWrapper.mozRequestFullScreen();
} else if (chartWrapper.msRequestFullscreen) {
await chartWrapper.msRequestFullscreen();
}
} else {
//
// Exit Fullscreen
if (doc.exitFullscreen) {
await doc.exitFullscreen();
} else if (doc.webkitExitFullscreen) {
await doc.webkitExitFullscreen();
} else if (doc.mozCancelFullScreen) {
await doc.mozCancelFullScreen();
} else if (doc.msExitFullscreen) {
await doc.msExitFullscreen();
}
}
} }
//#endregion //#endregion
@@ -729,8 +725,14 @@ export class XChartComponent extends XChartContainerComponent {
const type = await this.getValueAsync(this.type); const type = await this.getValueAsync(this.type);
const chartId = await this.getValueAsync(this.uuid); const chartId = await this.getValueAsync(this.uuid);
const series = await this.getValueAsync(this.series); const series = await this.getValueAsync(this.series);
//
const cOptions = await this.getValueAsync(this.options); const cOptions = await this.getValueAsync(this.options);
//
const colors: Array<string | ((opts: XChartColorFormatterOpts) => string)> =
[getXColorValue(XColorWithBrightness.PrimaryShade)];
// //
const title = await this.getResourceValueAsync(this.title); const title = await this.getResourceValueAsync(this.title);
const titleAlignProp = await this.getValueAsync(this.titleAlign); const titleAlignProp = await this.getValueAsync(this.titleAlign);
@@ -764,6 +766,9 @@ export class XChartComponent extends XChartContainerComponent {
// //
const primaryColorValue = getXColorValue(XColorWithBrightness.Primary); const primaryColorValue = getXColorValue(XColorWithBrightness.Primary);
//
console.log('cOptions: ', cOptions);
// //
// Normalize Directional Properties .... // Normalize Directional Properties ....
if (this.managerService.uiDirection == 'ltr') { if (this.managerService.uiDirection == 'ltr') {
@@ -803,27 +808,27 @@ export class XChartComponent extends XChartContainerComponent {
// //
this.CHART_OPTIONS = { this.CHART_OPTIONS = {
...cOptions, ...cOptions,
series: series || cOptions.series, series: series,
title: { title: {
...cOptions.title, ...cOptions?.title,
text: title, text: title,
align: titleAlign, align: titleAlign,
style: { style: {
...cOptions.title?.style, ...cOptions?.title?.style,
color: titleColorValue, color: titleColorValue,
}, },
}, },
subtitle: { subtitle: {
...cOptions.subtitle, ...cOptions?.subtitle,
text: subTitle, text: subTitle,
align: subTitleAlign, align: subTitleAlign,
style: { style: {
...cOptions.subtitle?.style, ...cOptions?.subtitle?.style,
color: subTitleColorValue, color: subTitleColorValue,
}, },
}, },
chart: { chart: {
...cOptions.chart, ...cOptions?.chart,
id: chartId, id: chartId,
type: type as any, type: type as any,
foreColor: foregroundColorValue, foreColor: foregroundColorValue,
@@ -833,7 +838,7 @@ export class XChartComponent extends XChartContainerComponent {
autoSelected: 'pan', autoSelected: 'pan',
}, },
events: { events: {
...cOptions.chart?.events, ...cOptions?.chart?.events,
// //
//#region Attach Events ... //#region Attach Events ...
// //
@@ -844,7 +849,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.animationEnd?.(chart, options); cOptions?.chart?.events?.animationEnd?.(chart, options);
}, },
// //
@@ -855,7 +860,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.beforeMount?.(chart, options); cOptions?.chart?.events?.beforeMount?.(chart, options);
}, },
// //
@@ -866,7 +871,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.mounted?.(chart, options); cOptions?.chart?.events?.mounted?.(chart, options);
}, },
// //
@@ -877,7 +882,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.updated?.(chart, options); cOptions?.chart?.events?.updated?.(chart, options);
}, },
// //
@@ -892,7 +897,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.mouseMove?.(e, chart, options); cOptions?.chart?.events?.mouseMove?.(e, chart, options);
}, },
// //
@@ -907,7 +912,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.mouseLeave?.(e, chart, options); cOptions?.chart?.events?.mouseLeave?.(e, chart, options);
}, },
// //
@@ -922,7 +927,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.click?.(e, chart, options); cOptions?.chart?.events?.click?.(e, chart, options);
}, },
// //
@@ -937,7 +942,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.xAxisLabelClick?.(e, chart, options); cOptions?.chart?.events?.xAxisLabelClick?.(e, chart, options);
}, },
// //
@@ -955,7 +960,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.legendClick?.(chart, seriesIndex, options); cOptions?.chart?.events?.legendClick?.(chart, seriesIndex, options);
}, },
// //
@@ -970,7 +975,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.markerClick?.(e, chart, options); cOptions?.chart?.events?.markerClick?.(e, chart, options);
}, },
// //
@@ -987,7 +992,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.selection?.(chart, options); cOptions?.chart?.events?.selection?.(chart, options);
}, },
// //
@@ -1002,7 +1007,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.dataPointSelection?.(e, chart, options); cOptions?.chart?.events?.dataPointSelection?.(e, chart, options);
}, },
// //
@@ -1017,7 +1022,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.dataPointMouseEnter?.(e, chart, options); cOptions?.chart?.events?.dataPointMouseEnter?.(e, chart, options);
}, },
// //
@@ -1032,7 +1037,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.dataPointMouseLeave?.(e, chart, options); cOptions?.chart?.events?.dataPointMouseLeave?.(e, chart, options);
}, },
// //
@@ -1046,7 +1051,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.beforeZoom?.(chart, options); cOptions?.chart?.events?.beforeZoom?.(chart, options);
}, },
// //
@@ -1057,7 +1062,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.beforeResetZoom?.(chart, options); cOptions?.chart?.events?.beforeResetZoom?.(chart, options);
}, },
// //
@@ -1074,7 +1079,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.zoomed?.(chart, options); cOptions?.chart?.events?.zoomed?.(chart, options);
}, },
// //
@@ -1088,7 +1093,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.scrolled?.(chart, options); cOptions?.chart?.events?.scrolled?.(chart, options);
}, },
// //
@@ -1105,7 +1110,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.brushScrolled?.(chart, options); cOptions?.chart?.events?.brushScrolled?.(chart, options);
}, },
// //
@@ -1122,7 +1127,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.crossFilter?.(chart, options); cOptions?.chart?.events?.crossFilter?.(chart, options);
}, },
// //
@@ -1142,7 +1147,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.filterChange?.(chart, options); cOptions?.chart?.events?.filterChange?.(chart, options);
}, },
// //
@@ -1164,7 +1169,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.annotationDragged?.(chart, options); cOptions?.chart?.events?.annotationDragged?.(chart, options);
}, },
// //
@@ -1183,7 +1188,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.annotationEdited?.(chart, options); cOptions?.chart?.events?.annotationEdited?.(chart, options);
}, },
// //
@@ -1203,7 +1208,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.annotationCreated?.(chart, options); cOptions?.chart?.events?.annotationCreated?.(chart, options);
}, },
// //
@@ -1223,7 +1228,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.annotationStyled?.(chart, options); cOptions?.chart?.events?.annotationStyled?.(chart, options);
}, },
// //
@@ -1241,7 +1246,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.annotationDeleted?.(chart, options); cOptions?.chart?.events?.annotationDeleted?.(chart, options);
}, },
// //
@@ -1262,7 +1267,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.measured?.(chart, options); cOptions?.chart?.events?.measured?.(chart, options);
}, },
// //
@@ -1276,7 +1281,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.beatChange?.(chart, options); cOptions?.chart?.events?.beatChange?.(chart, options);
}, },
// //
@@ -1291,7 +1296,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.keyDown?.(e, chart, options); cOptions?.chart?.events?.keyDown?.(e, chart, options);
}, },
// //
@@ -1306,7 +1311,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.keyUp?.(e, chart, options); cOptions?.chart?.events?.keyUp?.(e, chart, options);
}, },
// //
@@ -1321,7 +1326,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.drillDownStart?.(info, chart, options); cOptions?.chart?.events?.drillDownStart?.(info, chart, options);
}, },
// //
@@ -1336,7 +1341,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.drillDownEnd?.(info, chart, options); cOptions?.chart?.events?.drillDownEnd?.(info, chart, options);
}, },
// //
@@ -1351,7 +1356,7 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.drillUp?.(info, chart, options); cOptions?.chart?.events?.drillUp?.(info, chart, options);
}, },
// //
@@ -1366,22 +1371,22 @@ export class XChartComponent extends XChartContainerComponent {
} }
// //
cOptions.chart?.events?.drillDownError?.(info, chart, options); cOptions?.chart?.events?.drillDownError?.(info, chart, options);
}, },
//#endregion //#endregion
}, },
}, },
theme: { theme: {
...cOptions.theme, ...cOptions?.theme,
palette: cOptions.theme?.palette || 'palette1', palette: cOptions?.theme?.palette || 'palette1',
}, },
colors: cOptions.colors || [primaryColorValue], colors: colors,
grid: { grid: {
...cOptions.grid, ...cOptions?.grid,
borderColor: gridColorValue, borderColor: gridColorValue,
}, },
dataLabels: { dataLabels: {
...cOptions.dataLabels, ...cOptions?.dataLabels,
}, },
}; };
@@ -1391,9 +1396,18 @@ export class XChartComponent extends XChartContainerComponent {
this.CHART_OPTIONS, this.CHART_OPTIONS,
); );
//
// Storing Original Height ...
if (isNullOrEmptyString(this.ORIGINAL_HEIGHT)) {
this.ORIGINAL_HEIGHT = this.CHART_OPTIONS.chart?.height?.toString();
}
// //
await this.prepareActionBar(); await this.prepareActionBar();
//
console.log('CHART_OPTIONS: ', this.CHART_OPTIONS);
// //
await this.chartInstance.render(); await this.chartInstance.render();
} }
@@ -2075,6 +2089,60 @@ export class XChartComponent extends XChartContainerComponent {
this.chartInstance = null; this.chartInstance = null;
} }
private async handleFullscreenMode(isFullscreen: boolean) {
//
if (
isNullOrUndefined(this.chartCard) ||
isNullOrUndefined(this.chartInstance)
) {
return;
}
//
let height = this.ORIGINAL_HEIGHT;
if (isFullscreen) {
//
const cardImageElement = document.querySelector('.x-card .x-image');
const cardHeaderElement = document.querySelector('.x-card .x-header');
const cardFooterElement = document.querySelector('.x-card .x-footer');
const cardContentElement = document.querySelector('.x-card .x-content');
const cardActionsElement = document.querySelector('.x-card .x-actions');
const actionBarHeight =
(this.chartActionBar?.element?.nativeElement as HTMLElement)
?.offsetHeight || 0;
//
const offset = 24;
height = `${
window.innerHeight -
offset -
(actionBarHeight +
(cardImageElement?.clientHeight || 0) +
(cardHeaderElement?.clientHeight || 0) +
(cardActionsElement?.clientHeight || 0) +
(cardFooterElement?.clientHeight || 0))
}px`;
}
//
this.CHART_OPTIONS = {
...this.CHART_OPTIONS,
chart: {
height: height,
},
};
//
this.chartInstance.updateOptions(
this.CHART_OPTIONS,
false,
true,
false,
false,
);
this.managerService.dispatchResizeEvent();
}
private registerActionProvider() { private registerActionProvider() {
// //
this.unregisterActionProvider(); this.unregisterActionProvider();
@@ -2145,5 +2213,43 @@ export class XChartComponent extends XChartContainerComponent {
this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe(); this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
this.ACTION_PROVIDER_SUBSCRIPTION = null; this.ACTION_PROVIDER_SUBSCRIPTION = null;
} }
private registerCardActionProvider() {
//
if (!isNullOrUndefined(this.CARD_ACTION_PROVIDER_SUBSCRIPTION)) {
this.unregisterCardActionProvider();
}
//
this.CARD_ACTION_PROVIDER_SUBSCRIPTION = this.cardActionProvider
.asObservable()
.subscribe(async (model) => {
//
if (isNullOrUndefined(model) || isNullOrEmptyString(model.action)) {
return;
}
//
// Handle Full Screen Toggled ...
if (model.action == XCardAction.FullScreenToggled) {
//
const isFullscreen = isNullOrUndefined(model.payload)
? false
: (model.payload as boolean) || false;
await this.handleFullscreenMode(isFullscreen);
}
});
}
private unregisterCardActionProvider() {
//
if (isNullOrUndefined(this.CARD_ACTION_PROVIDER_SUBSCRIPTION)) {
return;
}
//
this.CARD_ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
this.CARD_ACTION_PROVIDER_SUBSCRIPTION = null;
}
//#endregion //#endregion
} }
@@ -17,6 +17,7 @@ import {
XColorIdentifier, XColorIdentifier,
XResourceIdentifier, XResourceIdentifier,
XColorWithBrightness, XColorWithBrightness,
getXColorValue,
} from 'x-framework-core'; } from 'x-framework-core';
import { import {
XCardActionModel, XCardActionModel,
@@ -3323,6 +3324,9 @@ export interface IXChartContainer extends TXChartContainer {
series: XStandardType<XChartSeriesType>; series: XStandardType<XChartSeriesType>;
type: XStandardType<XChartTypeIdentifier>; type: XStandardType<XChartTypeIdentifier>;
//
colors: Array<string | ((opts: XChartColorFormatterOpts) => string)>;
// //
title: XStandardType<XResourceIdentifier>; title: XStandardType<XResourceIdentifier>;
titleAlign: XStandardType<XChartTextAlignIdentifier>; titleAlign: XStandardType<XChartTextAlignIdentifier>;
@@ -3473,6 +3477,11 @@ export class XChartContainer
readonly series: XStandardType<XChartSeriesType>; readonly series: XStandardType<XChartSeriesType>;
readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line; readonly type: XStandardType<XChartTypeIdentifier> = XChartType.Line;
//
readonly colors: Array<
string | ((opts: XChartColorFormatterOpts) => string)
> = [getXColorValue(XColorWithBrightness.PrimaryShade)];
// //
readonly title: XStandardType<XResourceIdentifier>; readonly title: XStandardType<XResourceIdentifier>;
readonly titleAlign: XStandardType<XChartTextAlignIdentifier> = readonly titleAlign: XStandardType<XChartTextAlignIdentifier> =
@@ -3698,6 +3707,9 @@ export abstract class XChartContainerComponent
@Input() @Input()
zoomStep: XStandardType<number> = this.propertyProvider.zoomStep; zoomStep: XStandardType<number> = this.propertyProvider.zoomStep;
@Input()
colors: Array<string | ((opts: XChartColorFormatterOpts) => string)> = this.propertyProvider.colors;
@Input() @Input()
defaultActionBarItemColor: XStandardType<XColorIdentifier> = defaultActionBarItemColor: XStandardType<XColorIdentifier> =
this.propertyProvider.defaultActionBarItemColor; this.propertyProvider.defaultActionBarItemColor;
@@ -4030,10 +4042,13 @@ export abstract class XChartContainerComponent
// //
type: this.getValue(container ? container.type : this.type), type: this.getValue(container ? container.type : this.type),
options: this.getValue(container ? container.options : this.options),
series: this.getValue(container ? container.series : this.series), series: this.getValue(container ? container.series : this.series),
options: this.getValue(container ? container.options : this.options),
zoomStep: this.getValue(container ? container.zoomStep : this.zoomStep), zoomStep: this.getValue(container ? container.zoomStep : this.zoomStep),
//
colors: this.getValue(container ? container.colors : this.colors),
// //
title: this.getValue(container ? container.title : this.title), title: this.getValue(container ? container.title : this.title),
titleAlign: this.getValue( titleAlign: this.getValue(