mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
46 changed files with 1057 additions and 404 deletions
@ -0,0 +1,14 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header"> |
|||
API Calls |
|||
|
|||
<div class="float-right"> |
|||
<a class="force" (click)="downloadLog()"> |
|||
<small>Download Log</small> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="card-body"> |
|||
<chart type="bar" [data]="chartData" [options]="chartOptions"></chart> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,60 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, CallsUsageDto, fadeAnimation, UsagesService } from '@app/shared'; |
|||
import { ChartHelpers, ChartOptions } from './shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-api-calls-card', |
|||
styleUrls: ['./api-calls-card.component.scss'], |
|||
templateUrl: './api-calls-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ApiCallsCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: CallsUsageDto; |
|||
|
|||
public chartOptions = ChartOptions.Stacked; |
|||
public chartData: any; |
|||
|
|||
constructor( |
|||
private readonly usagesService: UsagesService |
|||
) { |
|||
} |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
const labels = ChartHelpers.createLabelsFromSet(this.usage.details); |
|||
|
|||
this.chartData = { |
|||
labels, |
|||
datasets: Object.keys(this.usage.details).map((k, i) => ( |
|||
{ |
|||
label: ChartHelpers.label(k), |
|||
backgroundColor: ChartHelpers.getBackgroundColor(i), |
|||
borderColor: ChartHelpers.getBorderColor(i), |
|||
borderWidth: 1, |
|||
data: this.usage.details[k].map(x => x.averageElapsedMs) |
|||
})) |
|||
}; |
|||
} |
|||
} |
|||
|
|||
public downloadLog() { |
|||
this.usagesService.getLog(this.app.name) |
|||
.subscribe(url => { |
|||
window.open(url, '_blank'); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
<div class="card card"> |
|||
<div class="card-header">API Calls</div> |
|||
<div class="card-body"> |
|||
<div class="aggregation" *ngIf="callsTotal >= 0"> |
|||
<div class="aggregation-label">This month</div> |
|||
<div class="aggregation-value">{{callsTotal | sqxKNumber}}</div> |
|||
<div class="aggregation-label" *ngIf="callsAllowed > 0">Monthly limit: {{callsAllowed | sqxKNumber}}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,36 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, CallsUsageDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-api-calls-summary-card', |
|||
styleUrls: ['./api-calls-summary-card.component.scss'], |
|||
templateUrl: './api-calls-summary-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ApiCallsSummaryCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: CallsUsageDto; |
|||
|
|||
public callsTotal = 0; |
|||
public callsAllowed = 0; |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
this.callsTotal = this.usage.totalCalls; |
|||
this.callsAllowed = this.usage.allowedCalls; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
<div class="card card-href"> |
|||
<div class="card-body"> |
|||
<div class="card-image"> |
|||
<img src="./images/dashboard-api.svg" /> |
|||
</div> |
|||
|
|||
<h4 class="card-title"> |
|||
<a href="/api/content/{{app.name}}/docs" sqxExternalLink>Content API</a> |
|||
</h4> |
|||
|
|||
<div class="card-text"> |
|||
OpenAPI 3.0 compatible documentation for your app content. |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,23 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; |
|||
import { AppDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-api-card', |
|||
styleUrls: ['./api-card.component.scss'], |
|||
templateUrl: './api-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ApiCardComponent { |
|||
@Input() |
|||
public app: AppDto; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header"> |
|||
API Performance (ms): {{chartSummary}}ms avg |
|||
|
|||
<div class="float-right"> |
|||
<div class="form-check"> |
|||
<input class="form-check-input" type="checkbox" id="stacked" |
|||
[ngModel]="isStacked" |
|||
(ngModelChange)="isStackedChange.emit($event)" /> |
|||
|
|||
<label class="form-check-label" for="stacked"> |
|||
Stacked |
|||
</label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="card-body"> |
|||
<chart type="bar" [data]="chartData" [options]="chartOptions"></chart> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,61 @@ |
|||
|
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; |
|||
import { AppDto, CallsUsageDto, fadeAnimation } from '@app/shared'; |
|||
import { ChartHelpers, ChartOptions } from './shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-api-performance-card', |
|||
styleUrls: ['./api-performance-card.component.scss'], |
|||
templateUrl: './api-performance-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ApiPerformanceCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: CallsUsageDto; |
|||
|
|||
@Input() |
|||
public isStacked = false; |
|||
|
|||
@Output() |
|||
public isStackedChange = new EventEmitter<boolean>(); |
|||
|
|||
public get chartOptions() { |
|||
return this.isStacked ? ChartOptions.Stacked : ChartOptions.Default; |
|||
} |
|||
|
|||
public chartData: any; |
|||
public chartSummary = 0; |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
const labels = ChartHelpers.createLabelsFromSet(this.usage.details); |
|||
|
|||
this.chartData = { |
|||
labels, |
|||
datasets: Object.keys(this.usage.details).map((k, i) => ( |
|||
{ |
|||
label: ChartHelpers.label(k), |
|||
backgroundColor: ChartHelpers.getBackgroundColor(i), |
|||
borderColor: ChartHelpers.getBorderColor(i), |
|||
borderWidth: 1, |
|||
data: this.usage.details[k].map(x => x.totalCalls) |
|||
})) |
|||
}; |
|||
|
|||
this.chartSummary = this.usage.averageElapsedMs; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header"> |
|||
Traffic (MB): {{chartSummary | sqxFileSize}} total |
|||
|
|||
<div class="float-right"> |
|||
<div class="form-check"> |
|||
<input class="form-check-input" type="checkbox" id="stacked" |
|||
[ngModel]="isStacked" |
|||
(ngModelChange)="isStackedChange.emit($event)" /> |
|||
|
|||
<label class="form-check-label" for="stacked"> |
|||
Stacked |
|||
</label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="card-body"> |
|||
<chart type="bar" [data]="chartData" [options]="chartOptions"></chart> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,61 @@ |
|||
|
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; |
|||
import { AppDto, CallsUsageDto, fadeAnimation } from '@app/shared'; |
|||
import { ChartHelpers, ChartOptions } from './shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-api-traffic-card', |
|||
styleUrls: ['./api-traffic-card.component.scss'], |
|||
templateUrl: './api-traffic-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class ApiTrafficCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: CallsUsageDto; |
|||
|
|||
@Input() |
|||
public isStacked = false; |
|||
|
|||
@Output() |
|||
public isStackedChange = new EventEmitter<boolean>(); |
|||
|
|||
public get chartOptions() { |
|||
return this.isStacked ? ChartOptions.Stacked : ChartOptions.Default; |
|||
} |
|||
|
|||
public chartData: any; |
|||
public chartSummary = 0; |
|||
|
|||
public ngOnChanges(changes: SimpleChanges) { |
|||
if (this.usage && changes['usage']) { |
|||
const labels = ChartHelpers.createLabelsFromSet(this.usage.details); |
|||
|
|||
this.chartData = { |
|||
labels, |
|||
datasets: Object.keys(this.usage.details).map((k, i) => ( |
|||
{ |
|||
label: ChartHelpers.label(k), |
|||
backgroundColor: ChartHelpers.getBackgroundColor(i), |
|||
borderColor: ChartHelpers.getBorderColor(i), |
|||
borderWidth: 1, |
|||
data: this.usage.details[k].map(x => Math.round(100 * (x.totalBytes / (1024 * 1024))) / 100) |
|||
})) |
|||
}; |
|||
|
|||
this.chartSummary = this.usage.totalBytes; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header">Assets Uploads</div> |
|||
<div class="card-body"> |
|||
<chart type="line" [data]="chartData" [options]="chartOptions"></chart> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, fadeAnimation, StorageUsagePerDateDto } from '@app/shared'; |
|||
import { ChartHelpers, ChartOptions } from './shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-asset-uploads-count-card', |
|||
styleUrls: ['./asset-uploads-count-card.component.scss'], |
|||
templateUrl: './asset-uploads-count-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class AssetUploadsCountCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: ReadonlyArray<StorageUsagePerDateDto>; |
|||
|
|||
public chartData: any; |
|||
public chartOptions = ChartOptions.Default; |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
const labels = ChartHelpers.createLabels(this.usage); |
|||
|
|||
this.chartData = { |
|||
labels, |
|||
datasets: [ |
|||
{ |
|||
label: 'All', |
|||
lineTension: 0, |
|||
fill: false, |
|||
backgroundColor: ChartHelpers.getBackgroundColor(), |
|||
borderColor: ChartHelpers.getBorderColor(), |
|||
borderWidth: 1, |
|||
data: this.usage.map(x => x.totalCount) |
|||
} |
|||
] |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header">Assets Uploads</div> |
|||
<div class="card-body"> |
|||
<chart type="line" [data]="chartData" [options]="chartOptions"></chart> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, fadeAnimation, StorageUsagePerDateDto } from '@app/shared'; |
|||
import { ChartHelpers, ChartOptions } from './shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-asset-uploads-size-card', |
|||
styleUrls: ['./asset-uploads-size-card.component.scss'], |
|||
templateUrl: './asset-uploads-size-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class AssetUploadsSizeCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: ReadonlyArray<StorageUsagePerDateDto>; |
|||
|
|||
public chartData: any; |
|||
public chartOptions = ChartOptions.Default; |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
const labels = ChartHelpers.createLabels(this.usage); |
|||
|
|||
this.chartData = { |
|||
labels, |
|||
datasets: [ |
|||
{ |
|||
label: 'All', |
|||
lineTension: 0, |
|||
fill: false, |
|||
backgroundColor: ChartHelpers.getBackgroundColor(), |
|||
borderColor: ChartHelpers.getBorderColor(), |
|||
borderWidth: 1, |
|||
data: this.usage.map(x => Math.round(100 * (x.totalSize / (1024 * 1024))) / 100) |
|||
} |
|||
] |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
<div class="card card"> |
|||
<div class="card-header">Assets Size (MB)</div> |
|||
<div class="card-body"> |
|||
<div class="aggregation" *ngIf="storageCurrent >= 0"> |
|||
<div class="aggregation-label">Total Size</div> |
|||
<div class="aggregation-value">{{storageCurrent | sqxFileSize}}</div> |
|||
<div class="aggregation-label" *ngIf="storageAllowed > 0">Total limit: {{storageAllowed | sqxFileSize}}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,36 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, CurrentStorageDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-asset-uploads-size-summary-card', |
|||
styleUrls: ['./asset-uploads-size-summary-card.component.scss'], |
|||
templateUrl: './asset-uploads-size-summary-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class AssetUploadsSizeSummaryCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
@Input() |
|||
public usage: CurrentStorageDto; |
|||
|
|||
public storageCurrent = 0; |
|||
public storageAllowed = 0; |
|||
|
|||
public ngOnChanges() { |
|||
if (this.usage) { |
|||
this.storageCurrent = this.usage.size; |
|||
this.storageAllowed = this.usage.maxAllowed; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
<div class="card card-href"> |
|||
<div class="card-body"> |
|||
<div class="card-image"> |
|||
<img src="./images/dashboard-github.svg" /> |
|||
</div> |
|||
|
|||
<h4 class="card-title"> |
|||
<a href="https://github.com/squidex/squidex" sqxExternalLink>Github</a> |
|||
</h4> |
|||
|
|||
<div class="card-text"> |
|||
Get the source code from Github and report bugs or ask for support. |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,23 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; |
|||
import { AppDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-github-card', |
|||
styleUrls: ['./github-card.component.scss'], |
|||
templateUrl: './github-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class GithubCardComponent { |
|||
@Input() |
|||
public app: AppDto; |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<div class="card card-lg"> |
|||
<div class="card-header">History</div> |
|||
<div class="card-body card-history card-body-scroll"> |
|||
<sqx-history-list [events]="history | async"></sqx-history-list> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,35 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; |
|||
import { AppDto, fadeAnimation, HistoryEventDto, HistoryService } from '@app/shared'; |
|||
import { Observable } from 'rxjs'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-history-card', |
|||
styleUrls: ['./history-card.component.scss'], |
|||
templateUrl: './history-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class HistoryCardComponent implements OnChanges { |
|||
@Input() |
|||
public app: AppDto; |
|||
|
|||
public history: Observable<ReadonlyArray<HistoryEventDto>>; |
|||
|
|||
constructor( |
|||
private readonly historyService: HistoryService |
|||
) { |
|||
} |
|||
|
|||
public ngOnChanges() { |
|||
this.history = this.historyService.getHistory(this.app.name, ''); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<div class="card card-href"> |
|||
<div class="card-body"> |
|||
<div class="card-image"> |
|||
<img src="./images/dashboard-schema.svg" /> |
|||
</div> |
|||
|
|||
<ng-container *ngIf="app.canReadSchemas; else noPermission"> |
|||
<h4 class="card-title"> |
|||
<a [routerLink]="['schemas', { showDialog: true }]">New Schema</a> |
|||
</h4> |
|||
|
|||
<div class="card-text"> |
|||
A schema defines the structure of your content element. |
|||
</div> |
|||
</ng-container> |
|||
|
|||
<ng-template #noPermission> |
|||
<h4 class="card-title"> |
|||
<a [routerLink]="['schemas']">Schemas</a> |
|||
</h4> |
|||
|
|||
<div class="card-text"> |
|||
Get an insight to the data model of this app. |
|||
</div> |
|||
</ng-template> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,23 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; |
|||
import { AppDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-schema-card', |
|||
styleUrls: ['./schema-card.component.scss'], |
|||
templateUrl: './schema-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class SchemaCardComponent { |
|||
@Input() |
|||
public app: AppDto; |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { DateTime } from '@app/shared'; |
|||
|
|||
const ColorSchema: ReadonlyArray<string> = [ |
|||
' 51, 137, 213', |
|||
'211, 50, 50', |
|||
'131, 211, 50', |
|||
' 50, 211, 131', |
|||
' 50, 211, 211', |
|||
' 50, 131, 211', |
|||
' 50, 50, 211', |
|||
' 50, 211, 50', |
|||
'131, 50, 211', |
|||
'211, 50, 211', |
|||
'211, 50, 131' |
|||
]; |
|||
|
|||
export module ChartHelpers { |
|||
export function label(category: string) { |
|||
return category === '*' ? 'anonymous' : category; |
|||
} |
|||
|
|||
export function createLabels(dtos: ReadonlyArray<{ date: DateTime }>): ReadonlyArray<string> { |
|||
return dtos.map(d => d.date.toStringFormat('M-dd')); |
|||
} |
|||
|
|||
export function createLabelsFromSet(dtos: { [category: string]: ReadonlyArray<{ date: DateTime }> }): ReadonlyArray<string> { |
|||
return createLabels(dtos[Object.keys(dtos)[0]]); |
|||
} |
|||
|
|||
export function getBackgroundColor(i = 0) { |
|||
return `rgba(${ColorSchema[i]}, 0.6)`; |
|||
} |
|||
|
|||
export function getBorderColor(i = 0) { |
|||
return `rgba(${ColorSchema[i]}, 1)`; |
|||
} |
|||
} |
|||
|
|||
export module ChartOptions { |
|||
export const Default = { |
|||
responsive: true, |
|||
scales: { |
|||
xAxes: [{ |
|||
display: true, |
|||
stacked: false |
|||
}], |
|||
yAxes: [{ |
|||
ticks: { |
|||
beginAtZero: true |
|||
}, |
|||
stacked: false |
|||
}] |
|||
}, |
|||
maintainAspectRatio: false |
|||
}; |
|||
|
|||
export const Stacked = { |
|||
responsive: true, |
|||
scales: { |
|||
xAxes: [{ |
|||
display: true, |
|||
stacked: true |
|||
}], |
|||
yAxes: [{ |
|||
ticks: { |
|||
beginAtZero: true |
|||
}, |
|||
stacked: true |
|||
}] |
|||
}, |
|||
maintainAspectRatio: false |
|||
}; |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
<div class="card card-href"> |
|||
<div class="card-body"> |
|||
<div class="card-image"> |
|||
<img src="./images/dashboard-feedback.svg" /> |
|||
</div> |
|||
|
|||
<h4 class="card-title"> |
|||
<a href="https://support.squidex.io" sqxExternalLink>Feedback & Support</a> |
|||
</h4> |
|||
|
|||
<div class="card-text"> |
|||
Provide feedback and request features to help us to improve Squidex. |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,23 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; |
|||
import { AppDto, fadeAnimation } from '@app/shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-support-card', |
|||
styleUrls: ['./support-card.component.scss'], |
|||
templateUrl: './support-card.component.html', |
|||
animations: [ |
|||
fadeAnimation |
|||
], |
|||
changeDetection: ChangeDetectionStrategy.OnPush |
|||
}) |
|||
export class SupportCardComponent { |
|||
@Input() |
|||
public app: AppDto; |
|||
} |
|||
Loading…
Reference in new issue