Added new monitors
This commit is contained in:
parent
b287f47125
commit
263d5e4cc1
15 changed files with 299 additions and 142 deletions
|
@ -120,7 +120,7 @@ App::get('/v1/functions/:functionId/usage')
|
|||
->label('sdk.namespace', 'functions')
|
||||
->label('sdk.method', 'getUsage')
|
||||
->param('functionId', '', function () { return new UID(); }, 'Function unique ID.')
|
||||
->param('range', 'last30', function () { return new WhiteList(['daily', 'monthly', 'last30', 'last90']); }, 'Date range.', true)
|
||||
->param('range', '30d', function () { return new WhiteList(['24h', '7d', '30d', '90d']); }, 'Date range.', true)
|
||||
->action(function ($functionId, $range, $response, $project, $projectDB, $register) {
|
||||
/** @var Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
|
@ -135,36 +135,32 @@ App::get('/v1/functions/:functionId/usage')
|
|||
}
|
||||
|
||||
$period = [
|
||||
'daily' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('today')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
||||
'group' => '1m',
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '30m',
|
||||
],
|
||||
'monthly' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('midnight first day of this month')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('midnight last day of this month')),
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last30' => [
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last90' => [
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('today')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
// 'yearly' => [
|
||||
// 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')),
|
||||
// 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')),
|
||||
// 'group' => '4w',
|
||||
// ],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
$executions = [];
|
||||
$failures = [];
|
||||
$compute = [];
|
||||
|
||||
if ($client) {
|
||||
|
@ -183,6 +179,17 @@ App::get('/v1/functions/:functionId/usage')
|
|||
];
|
||||
}
|
||||
|
||||
// Failures
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' AND "functionStatus"=\'failed\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
foreach ($points as $point) {
|
||||
$failures[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
// Compute
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_time" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
@ -196,12 +203,19 @@ App::get('/v1/functions/:functionId/usage')
|
|||
}
|
||||
|
||||
$response->json([
|
||||
'range' => $range,
|
||||
'executions' => [
|
||||
'data' => $executions,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $executions)),
|
||||
],
|
||||
'failures' => [
|
||||
'data' => $failures,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
return $item['value'];
|
||||
}, $failures)),
|
||||
],
|
||||
'compute' => [
|
||||
'data' => $compute,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
|
@ -533,8 +547,8 @@ App::post('/v1/functions/:functionId/executions')
|
|||
->label('sdk.method', 'createExecution')
|
||||
->label('sdk.description', '/docs/references/functions/create-execution.md')
|
||||
->param('functionId', '', function () { return new UID(); }, 'Function unique ID.')
|
||||
->param('async', 1, function () { return new Range(0, 1); }, 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
|
||||
->action(function ($functionId, $async, $response, $project, $projectDB) {
|
||||
// ->param('async', 1, function () { return new Range(0, 1); }, 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
|
||||
->action(function ($functionId, /*$async,*/ $response, $project, $projectDB) {
|
||||
/** @var Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Appwrite\Database\Database $projectDB */
|
||||
|
@ -575,16 +589,14 @@ App::post('/v1/functions/:functionId/executions')
|
|||
throw new Exception('Failed saving execution to DB', 500);
|
||||
}
|
||||
|
||||
if((bool)$async) {
|
||||
// Issue a TLS certificate when domain is verified
|
||||
Resque::enqueue('v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $project->getId(),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => $execution->getId(),
|
||||
'functionTag' => $tag->getId(),
|
||||
'functionTrigger' => 'http',
|
||||
]);
|
||||
}
|
||||
// Issue a TLS certificate when domain is verified
|
||||
Resque::enqueue('v1-functions', 'FunctionsV1', [
|
||||
'projectId' => $project->getId(),
|
||||
'functionId' => $function->getId(),
|
||||
'executionId' => $execution->getId(),
|
||||
'functionTag' => $tag->getId(),
|
||||
'functionTrigger' => 'http',
|
||||
]);
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
|
|
|
@ -161,7 +161,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getUsage')
|
||||
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
|
||||
->param('range', 'last30', function () { return new WhiteList(['daily', 'monthly', 'last30', 'last90']); }, 'Date range.', true)
|
||||
->param('range', '30d', function () { return new WhiteList(['24h', '7d', '30d', '90d']); }, 'Date range.', true)
|
||||
->action(function ($projectId, $range, $response, $consoleDB, $projectDB, $register) {
|
||||
/** @var Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Database $consoleDB */
|
||||
|
@ -175,31 +175,26 @@ App::get('/v1/projects/:projectId/usage')
|
|||
}
|
||||
|
||||
$period = [
|
||||
'daily' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('today')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
||||
'group' => '1m',
|
||||
'24h' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||
'group' => '1h',
|
||||
],
|
||||
'monthly' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('midnight first day of this month')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('midnight last day of this month')),
|
||||
'7d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last30' => [
|
||||
'30d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
'last90' => [
|
||||
'90d' => [
|
||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('today')),
|
||||
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||
'group' => '1d',
|
||||
],
|
||||
// 'yearly' => [
|
||||
// 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')),
|
||||
// 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')),
|
||||
// 'group' => '4w',
|
||||
// ],
|
||||
];
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
@ -289,6 +284,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
$tasksTotal = \count($project->getAttribute('tasks', []));
|
||||
|
||||
$response->json([
|
||||
'range' => $range,
|
||||
'requests' => [
|
||||
'data' => $requests,
|
||||
'total' => \array_sum(\array_map(function ($item) {
|
||||
|
|
|
@ -36,7 +36,7 @@ const APP_EMAIL_SECURITY = 'security@localhost.test'; // Default security email
|
|||
const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
|
||||
const APP_MODE_ADMIN = 'admin';
|
||||
const APP_PAGING_LIMIT = 12;
|
||||
const APP_CACHE_BUSTER = 127;
|
||||
const APP_CACHE_BUSTER = 128;
|
||||
const APP_VERSION_STABLE = '0.6.2';
|
||||
const APP_STORAGE_UPLOADS = '/storage/uploads';
|
||||
const APP_STORAGE_FUNCTIONS = '/storage/functions';
|
||||
|
|
|
@ -50,7 +50,7 @@ $http->on('AfterReload', function($serv, $workerId) {
|
|||
});
|
||||
|
||||
$http->on('start', function (Server $http) use ($payloadSize) {
|
||||
Console::success('Server started succefully (max payload is '.$payloadSize.' bytes)');
|
||||
Console::success('Server started succefully (max payload is '.number_format($payloadSize).' bytes)');
|
||||
|
||||
Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}");
|
||||
|
||||
|
|
|
@ -241,28 +241,119 @@ $timeout = $this->getParam('timeout', 900);
|
|||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li data-state="/console/functions/function/usage?id={{router.params.id}}&project={{router.params.project}}">
|
||||
<h2>Usage</h2>
|
||||
<li data-state="/console/functions/function/monitor?id={{router.params.id}}&project={{router.params.project}}">
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||
data-service="functions.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-function-id="{{router.params.id}}"
|
||||
data-param-range="90d">
|
||||
<button class="tick">90d</button>
|
||||
</form>
|
||||
|
||||
<div class="box margin-bottom-small"
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
|
||||
data-service="functions.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-function-id="{{router.params.id}}">
|
||||
<button class="tick">30d</button>
|
||||
</form>
|
||||
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
|
||||
|
||||
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
|
||||
data-service="functions.getUsage"
|
||||
data-event="submit"
|
||||
data-name="usage"
|
||||
data-param-function-id="{{router.params.id}}"
|
||||
data-param-range="24h">
|
||||
<button class="tick">24h</button>
|
||||
</form>
|
||||
|
||||
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
|
||||
|
||||
<h2>Monitor</h2>
|
||||
|
||||
<div
|
||||
data-service="functions.getUsage"
|
||||
data-event="load"
|
||||
data-name="usage"
|
||||
data-param-function-id="{{router.params.id}}"
|
||||
data-param-range="last30">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart margin-bottom-no">
|
||||
<div class="content" data-forms-chart="Executions=usage.executions.data,CPU Time (minutes)=usage.compute.data" data-height="140"></div>
|
||||
data-param-function-id="{{router.params.id}}">
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="xchart margin-bottom-no">
|
||||
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Executions=usage.executions.data" data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>Executions</li>
|
||||
</ul>
|
||||
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="xchart margin-bottom-no">
|
||||
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="CPU Time (minutes)=usage.compute.data" data-colors="orange" data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li class="orange">CPU Time (minutes)</li>
|
||||
</ul>
|
||||
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="xchart margin-bottom-no">
|
||||
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Failures=usage.failures.data" data-colors="red" data-height="140" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li class="red">Errors</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--
|
||||
<div
|
||||
data-service="functions.getUsage"
|
||||
data-event="load"
|
||||
data-name="usage"
|
||||
data-param-function-id="{{router.params.id}}">
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart margin-bottom-no">
|
||||
<div class="content" data-forms-chart="Executions=usage.executions.data" data-height="140"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>Executions</li>
|
||||
<li>CPU Time (minutes)</li>
|
||||
</ul>
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>Executions</li>
|
||||
</ul>
|
||||
|
||||
<h3>Logs <span class="text-fade text-size-small pull-end margin-top-small" data-ls-bind="{{project-function-executions.sum}} executions found"></span></h3>
|
||||
<div class="box margin-bottom-small">
|
||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||
<div class="chart margin-bottom-no">
|
||||
<div class="content" data-forms-chart="CPU Time (minutes)=usage.compute.data" data-height="140"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="chart-notes margin-bottom-large">
|
||||
<li>CPU Time (minutes)</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
</li>
|
||||
<li data-state="/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}">
|
||||
|
||||
<div class="text-fade text-size-small pull-end margin-top" data-ls-bind="{{project-function-executions.sum}} executions found"></div>
|
||||
|
||||
<h2>Logs</h2>
|
||||
|
||||
<div
|
||||
data-service="functions.listExecutions"
|
||||
|
@ -311,14 +402,14 @@ $timeout = $this->getParam('timeout', 900);
|
|||
<span data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-ls-bind="{{execution.time|seconds2hum}}"></span>
|
||||
<span data-ls-if="{{execution.status}} === 'waiting' || {{execution.status}} === 'processing'">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<td data-title="">
|
||||
<div data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-title="">
|
||||
|
||||
<button class="desktops-only pull-end link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
||||
<button class="desktops-only pull-end link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
||||
|
||||
<button class="phones-only tablets-only link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
||||
<button class="phones-only tablets-only link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
||||
<button class="phones-only-inline tablets-only-inline link margin-end-small" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
||||
<button class="phones-only-inline tablets-only-inline link text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
||||
|
||||
<div data-ui-modal class="modal width-large box close" data-button-alias="none" data-open-event="execution-stdout-{{execution.$id}}">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
|
|
@ -30,13 +30,13 @@ $graph = $this->getParam('graph', false);
|
|||
data-event="load"
|
||||
data-name="usage"
|
||||
data-param-project-id="{{router.params.project}}"
|
||||
data-param-range="last30">
|
||||
data-param-range="30d">
|
||||
|
||||
<?php if (!$graph) : ?>
|
||||
<div class="row responsive">
|
||||
<div class="col span-9">
|
||||
<div class="chart pull-end">
|
||||
<div class="content" data-forms-chart="Requests=usage.requests.data"></div>
|
||||
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Requests=usage.requests.data" />
|
||||
</div>
|
||||
|
||||
<div class="chart-metric">
|
||||
|
|
|
@ -306,6 +306,7 @@ class FunctionsV1
|
|||
|
||||
$executionEnd = \microtime(true);
|
||||
$executionTime = ($executionEnd - $executionStart);
|
||||
$functionStatus = ($exitCode === 0) ? 'completed' : 'failed';
|
||||
|
||||
Console::info("Function executed in " . ($executionEnd - $executionStart) . " seconds with exit code {$exitCode}");
|
||||
|
||||
|
@ -313,7 +314,7 @@ class FunctionsV1
|
|||
|
||||
$execution = $projectDB->updateDocument(array_merge($execution->getArrayCopy(), [
|
||||
'tagId' => $tag->getId(),
|
||||
'status' => ($exitCode === 0) ? 'completed' : 'failed',
|
||||
'status' => $functionStatus,
|
||||
'exitCode' => $exitCode,
|
||||
'stdout' => mb_substr($stdout, -4000), // log last 4000 chars output
|
||||
'stderr' => mb_substr($stderr, -4000), // log last 4000 chars output
|
||||
|
@ -332,6 +333,7 @@ class FunctionsV1
|
|||
->setParam('projectId', $projectId)
|
||||
->setParam('functionId', $function->getId())
|
||||
->setParam('functionExecution', 1)
|
||||
->setParam('functionStatus', $functionStatus)
|
||||
->setParam('functionExecutionTime', $executionTime * 1000) // ms
|
||||
->setParam('networkRequestSize', 0)
|
||||
->setParam('networkResponseSize', 0)
|
||||
|
|
|
@ -39,6 +39,7 @@ class UsageV1
|
|||
$functionId = $this->args['functionId'];
|
||||
$functionExecution = $this->args['functionExecution'];
|
||||
$functionExecutionTime = $this->args['functionExecutionTime'];
|
||||
$functionStatus = $this->args['functionStatus'];
|
||||
|
||||
$tags = ",project={$projectId},version=".App::getEnv('_APP_VERSION', 'UNKNOWN').'';
|
||||
|
||||
|
@ -50,7 +51,8 @@ class UsageV1
|
|||
}
|
||||
|
||||
if($functionExecution >= 1) {
|
||||
$statsd->increment('executions.all'.$tags.',functionId='.$functionId);
|
||||
$statsd->increment('executions.all'.$tags.',functionId='.$functionId.',functionStatus='.$functionStatus);
|
||||
var_dump($tags.',functionId='.$functionId.',functionStatus='.$functionStatus);
|
||||
$statsd->count('executions.time'.$tags.',functionId='.$functionId, $functionExecutionTime);
|
||||
}
|
||||
|
||||
|
|
10
public/dist/scripts/app-all.js
vendored
10
public/dist/scripts/app-all.js
vendored
|
@ -2687,9 +2687,13 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
|
|||
if(target){target=document.getElementById(target);}
|
||||
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
|
||||
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");let sources=element.getAttribute('data-forms-chart');let width=element.getAttribute('data-width')||500;let height=element.getAttribute('data-height')||175;let colors=['#29b5d9','#4eb55b','#fba233',,];child.width=width;child.height=height;let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};sources=sources.split(',');for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let data=container.path(path);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=colors[i];config.data.datasets[i].backgroundColor=colors[i]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
|
||||
for(let x=0;x<data.length;x++){config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format("d F Y",data[x].date);}}
|
||||
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-chart",controller:function(element,container,date,document){let wrapper=document.createElement("div");let child=document.createElement("canvas");let sources=element.getAttribute('data-forms-chart');let width=element.getAttribute('data-width')||500;let height=element.getAttribute('data-height')||175;let colors=(element.getAttribute('data-colors')||'blue,green,orange,red').split(',');let themes={'blue':'#29b5d9','green':'#4eb55b','orange':'#fba233','red':'#dc3232',};let range={'24h':'H:i','7d':'d F Y','30d':'d F Y','90d':'d F Y'}
|
||||
element.parentNode.insertBefore(wrapper,element.nextSibling);wrapper.classList.add('content');child.width=width;child.height=height;sources=sources.split(',');wrapper.appendChild(child);let chart=null;let check=function(){let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let data=container.path(path);let value=JSON.parse(element.value);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=themes[colors[i]];config.data.datasets[i].backgroundColor=themes[colors[i]]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
|
||||
let dateFormat=(value.range&&range[value.range])?range[value.range]:'d F Y';for(let x=0;x<data.length;x++){config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format(dateFormat,data[x].date);}}
|
||||
if(chart){chart.destroy();}
|
||||
else{}
|
||||
chart=new Chart(child.getContext("2d"),config);wrapper.dataset["canvas"]=true;}
|
||||
check();element.addEventListener('change',check);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
window.getSelection().removeAllRanges();});let check=function(){if(!element.value){return;}
|
||||
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
|
||||
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}
|
||||
|
|
10
public/dist/scripts/app.js
vendored
10
public/dist/scripts/app.js
vendored
|
@ -323,9 +323,13 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
|
|||
if(target){target=document.getElementById(target);}
|
||||
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
|
||||
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");let sources=element.getAttribute('data-forms-chart');let width=element.getAttribute('data-width')||500;let height=element.getAttribute('data-height')||175;let colors=['#29b5d9','#4eb55b','#fba233',,];child.width=width;child.height=height;let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};sources=sources.split(',');for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let data=container.path(path);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=colors[i];config.data.datasets[i].backgroundColor=colors[i]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
|
||||
for(let x=0;x<data.length;x++){config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format("d F Y",data[x].date);}}
|
||||
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-chart",controller:function(element,container,date,document){let wrapper=document.createElement("div");let child=document.createElement("canvas");let sources=element.getAttribute('data-forms-chart');let width=element.getAttribute('data-width')||500;let height=element.getAttribute('data-height')||175;let colors=(element.getAttribute('data-colors')||'blue,green,orange,red').split(',');let themes={'blue':'#29b5d9','green':'#4eb55b','orange':'#fba233','red':'#dc3232',};let range={'24h':'H:i','7d':'d F Y','30d':'d F Y','90d':'d F Y'}
|
||||
element.parentNode.insertBefore(wrapper,element.nextSibling);wrapper.classList.add('content');child.width=width;child.height=height;sources=sources.split(',');wrapper.appendChild(child);let chart=null;let check=function(){let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let data=container.path(path);let value=JSON.parse(element.value);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=themes[colors[i]];config.data.datasets[i].backgroundColor=themes[colors[i]]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
|
||||
let dateFormat=(value.range&&range[value.range])?range[value.range]:'d F Y';for(let x=0;x<data.length;x++){config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format(dateFormat,data[x].date);}}
|
||||
if(chart){chart.destroy();}
|
||||
else{}
|
||||
chart=new Chart(child.getContext("2d"),config);wrapper.dataset["canvas"]=true;}
|
||||
check();element.addEventListener('change',check);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
window.getSelection().removeAllRanges();});let check=function(){if(!element.value){return;}
|
||||
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
|
||||
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}
|
||||
|
|
2
public/dist/styles/default-ltr.css
vendored
2
public/dist/styles/default-ltr.css
vendored
File diff suppressed because one or more lines are too long
2
public/dist/styles/default-rtl.css
vendored
2
public/dist/styles/default-rtl.css
vendored
File diff suppressed because one or more lines are too long
|
@ -4,87 +4,110 @@
|
|||
window.ls.container.get("view").add({
|
||||
selector: "data-forms-chart",
|
||||
controller: function(element, container, date, document) {
|
||||
let wrapper = document.createElement("div");
|
||||
let child = document.createElement("canvas");
|
||||
let sources = element.getAttribute('data-forms-chart');
|
||||
let width = element.getAttribute('data-width') || 500;
|
||||
let height = element.getAttribute('data-height') || 175;
|
||||
let colors = ['#29b5d9' /* blue */, '#4eb55b' /* green */, '#fba233', /* orange */,];
|
||||
let colors = (element.getAttribute('data-colors') || 'blue,green,orange,red').split(',');
|
||||
let themes = {'blue': '#29b5d9', 'green': '#4eb55b', 'orange': '#fba233', 'red': '#dc3232',};
|
||||
let range = {'24h': 'H:i', '7d': 'd F Y', '30d': 'd F Y', '90d': 'd F Y'}
|
||||
|
||||
element.parentNode.insertBefore(wrapper, element.nextSibling);
|
||||
|
||||
wrapper.classList.add('content');
|
||||
|
||||
child.width = width;
|
||||
child.height = height;
|
||||
|
||||
let config = {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: []
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title: {
|
||||
display: false,
|
||||
text: "Stats"
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
caretPadding: 0
|
||||
},
|
||||
hover: {
|
||||
mode: "nearest",
|
||||
intersect: true
|
||||
},
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
display: false
|
||||
}
|
||||
],
|
||||
yAxes: [
|
||||
{
|
||||
display: false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sources = sources.split(',');
|
||||
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
let label = sources[i].substring(0, sources[i].indexOf('='));
|
||||
let path = sources[i].substring(sources[i].indexOf('=') + 1);
|
||||
let data = container.path(path);
|
||||
wrapper.appendChild(child);
|
||||
|
||||
config.data.labels[i] = label;
|
||||
config.data.datasets[i] = {};
|
||||
config.data.datasets[i].label = label;
|
||||
config.data.datasets[i].borderColor = colors[i];
|
||||
config.data.datasets[i].backgroundColor = colors[i] + '36';
|
||||
config.data.datasets[i].borderWidth = 2;
|
||||
config.data.datasets[i].data = [0, 0, 0, 0, 0, 0, 0];
|
||||
config.data.datasets[i].fill = true;
|
||||
let chart = null;
|
||||
|
||||
if(!data) {
|
||||
return;
|
||||
let check = function() {
|
||||
|
||||
let config = {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: []
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title: {
|
||||
display: false,
|
||||
text: "Stats"
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
mode: "index",
|
||||
intersect: false,
|
||||
caretPadding: 0
|
||||
},
|
||||
hover: {
|
||||
mode: "nearest",
|
||||
intersect: true
|
||||
},
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
display: false
|
||||
}
|
||||
],
|
||||
yAxes: [
|
||||
{
|
||||
display: false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
let label = sources[i].substring(0, sources[i].indexOf('='));
|
||||
let path = sources[i].substring(sources[i].indexOf('=') + 1);
|
||||
let data = container.path(path);
|
||||
let value = JSON.parse(element.value);
|
||||
|
||||
config.data.labels[i] = label;
|
||||
config.data.datasets[i] = {};
|
||||
config.data.datasets[i].label = label;
|
||||
config.data.datasets[i].borderColor = themes[colors[i]];
|
||||
config.data.datasets[i].backgroundColor = themes[colors[i]] + '36';
|
||||
config.data.datasets[i].borderWidth = 2;
|
||||
config.data.datasets[i].data = [0, 0, 0, 0, 0, 0, 0];
|
||||
config.data.datasets[i].fill = true;
|
||||
|
||||
if(!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dateFormat = (value.range && range[value.range]) ? range[value.range] : 'd F Y';
|
||||
|
||||
for (let x = 0; x < data.length; x++) {
|
||||
config.data.datasets[i].data[x] = data[x].value;
|
||||
config.data.labels[x] = date.format(dateFormat, data[x].date);
|
||||
}
|
||||
}
|
||||
|
||||
for (let x = 0; x < data.length; x++) {
|
||||
config.data.datasets[i].data[x] = data[x].value;
|
||||
config.data.labels[x] = date.format("d F Y", data[x].date);
|
||||
if(chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
else {
|
||||
}
|
||||
chart = new Chart(child.getContext("2d"), config);
|
||||
|
||||
wrapper.dataset["canvas"] = true;
|
||||
|
||||
}
|
||||
|
||||
element.innerHTML = "";
|
||||
check();
|
||||
|
||||
element.appendChild(child);
|
||||
|
||||
container.set("chart", new Chart(child.getContext("2d"), config), true);
|
||||
|
||||
element.dataset["canvas"] = true;
|
||||
element.addEventListener('change', check);
|
||||
}
|
||||
});
|
||||
})(window);
|
||||
|
|
|
@ -98,6 +98,21 @@ button,
|
|||
font-size: 13px;
|
||||
}
|
||||
|
||||
&.tick {
|
||||
background: var(--config-color-fade-light);
|
||||
color: var(--config-color-dark);
|
||||
border-radius: 20px;
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-size: 12px;
|
||||
|
||||
&.selected {
|
||||
background: var(--config-color-dark);
|
||||
color: var(--config-color-fade);
|
||||
}
|
||||
}
|
||||
|
||||
&.round {
|
||||
width: 52px;
|
||||
padding: 0;
|
||||
|
|
|
@ -586,7 +586,7 @@
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&:nth-child(1) {
|
||||
&:nth-child(1), &.blue {
|
||||
color: #29b5d9;
|
||||
|
||||
&::before {
|
||||
|
@ -594,7 +594,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
&:nth-child(2), &.green {
|
||||
color: #4eb55b;
|
||||
|
||||
&::before {
|
||||
|
@ -602,13 +602,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
&:nth-child(3), &.orange {
|
||||
color: #ec9323;
|
||||
|
||||
&::before {
|
||||
background: #ec9323;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(4), &.red {
|
||||
color: #dc3232;
|
||||
|
||||
&::before {
|
||||
background: #dc3232;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue