1
0
Fork 0
mirror of synced 2024-06-12 07:44:44 +12:00

Updated new document form

This commit is contained in:
Eldad Fux 2020-04-18 01:19:02 +03:00
parent fbf1f188a0
commit c41dc2cd1b
9 changed files with 331 additions and 191 deletions

View file

@ -9,6 +9,9 @@ use Utopia\Validator\Range;
use Utopia\Validator\WhiteList;
use Utopia\Validator\Text;
use Utopia\Validator\ArrayList;
use Utopia\Locale\Locale;
use Utopia\Audit\Audit;
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\UID;
@ -18,6 +21,8 @@ use Appwrite\Database\Validator\Collection;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Exception\Authorization as AuthorizationException;
use Appwrite\Database\Exception\Structure as StructureException;
use DeviceDetector\DeviceDetector;
use GeoIp2\Database\Reader;
include_once __DIR__ . '/../shared/api.php';
@ -164,6 +169,69 @@ $utopia->get('/v1/database/collections/:collectionId')
}
);
$utopia->get('/v1/database/collections/:collectionId/logs')
->desc('Get Collection Logs')
->label('scope', 'collections.read')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.namespace', 'database')
->label('sdk.method', 'getCollectionLogs')
->label('sdk.description', '/docs/references/database/get-collection-logs.md')
->param('collectionId', '', function () { return new UID(); }, 'Collection unique ID.')
->action(
function ($collectionId) use ($response, $register, $projectDB, $project) {
$collection = $projectDB->getDocument($collectionId);
if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
throw new Exception('Collection not found', 404);
}
$adapter = new AuditAdapter($register->get('db'));
$adapter->setNamespace('app_'.$project->getId());
$audit = new Audit($adapter);
$countries = Locale::getText('countries');
$logs = $audit->getLogsByResource('database/collection/'.$collection->getId());
$reader = new Reader(__DIR__.'/../../db/DBIP/dbip-country-lite-2020-01.mmdb');
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$dd = new DeviceDetector($log['userAgent']);
$dd->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$dd->parse();
$output[$i] = [
'event' => $log['event'],
'ip' => $log['ip'],
'time' => strtotime($log['time']),
'OS' => $dd->getOs(),
'client' => $dd->getClient(),
'device' => $dd->getDevice(),
'brand' => $dd->getBrand(),
'model' => $dd->getModel(),
'geo' => [],
];
try {
$record = $reader->country($log['ip']);
$output[$i]['geo']['isoCode'] = strtolower($record->country->isoCode);
$output[$i]['geo']['country'] = $record->country->name;
$output[$i]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
} catch (\Exception $e) {
$output[$i]['geo']['isoCode'] = '--';
$output[$i]['geo']['country'] = Locale::getText('locale.country.unknown');
}
}
$response->json($output);
}
);
$utopia->put('/v1/database/collections/:collectionId')
->desc('Update Collection')
->label('scope', 'collections.write')

View file

@ -118,8 +118,8 @@
</div>
</div>
</li>
<li data-state="/console/database/collection/settings?id={{router.params.id}}&project={{router.params.project}}">
<h2>Settings</h2>
<li data-state="/console/database/collection/update?id={{router.params.id}}&project={{router.params.project}}">
<h2>Update</h2>
<div class="row responsive margin-top-negative">
<div class="col span-8 margin-bottom">

View file

@ -11,7 +11,7 @@
data-param-collection-id="{{router.params.collection}}"
data-param-document-id="{{router.params.id}}"
data-scope="sdk"
data-event="load,database.updateDocument"
data-event="load"
data-name="project-document"
data-success="default">
@ -38,11 +38,12 @@
data-analytics-category="console"
data-analytics-label="Update Database Document"
data-service="{{|documentAction}}"
data-name="project-document"
data-scope="sdk"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated document successfully"
data-success-param-trigger-events="database.updateDocument"
data-success-param-trigger-events="database.xupdateDocument"
data-failure="alert"
data-failure-param-alert-text="Failed to update document"
data-failure-param-alert-classname="error">
@ -50,7 +51,7 @@
<label>&nbsp;</label>
<div class="box">
<div data-ls-template="template-main" data-type="script" class="margin-bottom"></div>
<div data-ls-template="template-main" data-type="script"></div>
</div>
</form>
@ -241,8 +242,6 @@ $list = [
<script type="text/html" id="template-main">
<div data-ls-bind="{{project-document}}"></div>
<input name="documentId" type="hidden" data-ls-bind="{{project-document.$id}}" />
<input name="collectionId" type="hidden" data-ls-bind="{{project-collection.$id}}" />
@ -275,7 +274,7 @@ $list = [
</ul>
</fieldset>
<div class="toggle margin-bottom" data-ls-ui-open>
<div class="toggle margin-bottom margin-top" data-ls-ui-open>
<i class="icon-plus pull-end margin-top-tiny"></i>
<i class="icon-minus pull-end margin-top-tiny"></i>

View file

@ -34,7 +34,7 @@
"utopia-php/framework": "0.2.*",
"utopia-php/abuse": "0.2.*",
"utopia-php/audit": "0.2.*",
"utopia-php/audit": "0.3.*",
"utopia-php/cache": "0.2.*",
"utopia-php/cli": "0.4.*",
"utopia-php/config": "0.2.*",

344
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d19ba7d1c39970839f6f191664e9498d",
"content-hash": "41b9cc9221e2531109d2b2547a5b4209",
"packages": [
{
"name": "appwrite/php-clamav",
@ -239,12 +239,12 @@
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "47fe531de31fca4a1b997f87308e7d7804348f7e"
"reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e",
"reference": "47fe531de31fca4a1b997f87308e7d7804348f7e",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/95c63ab2117a72f48f5a55da9740a3273d45b7fd",
"reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd",
"shasum": ""
},
"require": {
@ -287,7 +287,7 @@
"ssl",
"tls"
],
"time": "2020-01-13T10:02:55+00:00"
"time": "2020-04-08T08:27:21+00:00"
},
{
"name": "dasprid/enum",
@ -481,27 +481,24 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "dev-master",
"version": "6.5.x-dev",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "dbc2bc3a293ed6b1ae08a3651e2bfd213d19b6a5"
"reference": "3325c9d98ad876127d6244d6e09e3cd7076d6492"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/dbc2bc3a293ed6b1ae08a3651e2bfd213d19b6a5",
"reference": "dbc2bc3a293ed6b1ae08a3651e2bfd213d19b6a5",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/3325c9d98ad876127d6244d6e09e3cd7076d6492",
"reference": "3325c9d98ad876127d6244d6e09e3cd7076d6492",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": "^7.2.5",
"psr/http-client": "^1.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.11"
},
"require-dev": {
"ext-curl": "*",
@ -509,7 +506,6 @@
"psr/log": "^1.1"
},
"suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
@ -548,7 +544,7 @@
"rest",
"web service"
],
"time": "2019-12-07T18:20:45+00:00"
"time": "2020-04-15T18:04:46+00:00"
},
{
"name": "guzzlehttp/promises",
@ -1006,55 +1002,6 @@
],
"time": "2016-01-21T22:26:37+00:00"
},
{
"name": "psr/http-client",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "fd5d37ae5a76ee3c5301a762faf66bf9519132ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/fd5d37ae5a76ee3c5301a762faf66bf9519132ef",
"reference": "fd5d37ae5a76ee3c5301a762faf66bf9519132ef",
"shasum": ""
},
"require": {
"php": "^7.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"time": "2019-09-04T06:46:09+00:00"
},
{
"name": "psr/http-message",
"version": "dev-master",
@ -1192,6 +1139,182 @@
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "37b0976c78b94856543260ce09b460a7bc852747"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
"reference": "37b0976c78b94856543260ce09b460a7bc852747",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2020-02-27T09:26:54+00:00"
},
{
"name": "utopia-php/abuse",
"version": "0.2.0",
@ -1241,16 +1364,16 @@
},
{
"name": "utopia-php/audit",
"version": "0.2.0",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "b35a68bca46bf6645a21f6491568030599f61b3c"
"reference": "ed624c324835859b68521099de13c01c6928703f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/b35a68bca46bf6645a21f6491568030599f61b3c",
"reference": "b35a68bca46bf6645a21f6491568030599f61b3c",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/ed624c324835859b68521099de13c01c6928703f",
"reference": "ed624c324835859b68521099de13c01c6928703f",
"shasum": ""
},
"require": {
@ -1284,7 +1407,7 @@
"upf",
"utopia"
],
"time": "2019-12-28T23:32:08+00:00"
"time": "2020-04-17T19:42:29+00:00"
},
{
"name": "utopia-php/cache",
@ -1622,7 +1745,7 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator",
"reference": "3b7389388f29c6e0cf53cf2233ee516fb20ad9f7"
"reference": "ccab743c1a82aa116456114a66dfefe1976e125a"
},
"require": {
"ext-curl": "*",
@ -1652,7 +1775,7 @@
}
],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"time": "2020-04-05T20:13:47+00:00"
"time": "2020-04-14T14:07:24+00:00"
},
{
"name": "doctrine/instantiator",
@ -1979,12 +2102,12 @@
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "b0843c8cbcc2dc5eda5158e583c7199a5e44c86d"
"reference": "74a67151cce1fe4aa5960636ae510ddf1faefdb3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/b0843c8cbcc2dc5eda5158e583c7199a5e44c86d",
"reference": "b0843c8cbcc2dc5eda5158e583c7199a5e44c86d",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/74a67151cce1fe4aa5960636ae510ddf1faefdb3",
"reference": "74a67151cce1fe4aa5960636ae510ddf1faefdb3",
"shasum": ""
},
"require": {
@ -2023,7 +2146,7 @@
"reflection",
"static analysis"
],
"time": "2019-12-20T12:45:35+00:00"
"time": "2020-04-10T20:41:10+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
@ -2441,16 +2564,16 @@
},
{
"name": "phpunit/phpunit",
"version": "7.5.x-dev",
"version": "7.5.20",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "6ef9ac810e494e7793013f8f5004d5d268852412"
"reference": "9467db479d1b0487c99733bb1e7944d32deded2c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6ef9ac810e494e7793013f8f5004d5d268852412",
"reference": "6ef9ac810e494e7793013f8f5004d5d268852412",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c",
"reference": "9467db479d1b0487c99733bb1e7944d32deded2c",
"shasum": ""
},
"require": {
@ -2521,7 +2644,7 @@
"testing",
"xunit"
],
"time": "2019-11-27T08:45:03+00:00"
"time": "2020-01-08T08:45:45+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@ -3147,65 +3270,6 @@
],
"time": "2020-02-27T09:26:54+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.1.3",

View file

@ -2585,7 +2585,7 @@ let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentRequired",function($value,rule,filter){if(!$value||$value==='false'){return'';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');console.log('isnew?');console.log(document);console.log(document.$id);if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
@ -2597,7 +2597,7 @@ window.ls.container.get("view").add({selector:"data-acl",controller:function(ele
if("/console"===router.getCurrent().path){document.body.classList.add("index");}else{document.body.classList.remove("index");}}}).add({selector:"data-forms-headers",controller:function(element){let key=document.createElement("input");let value=document.createElement("input");let wrap=document.createElement("div");let cell1=document.createElement("div");let cell2=document.createElement("div");key.type="text";key.className="margin-bottom-no";key.placeholder="Key";value.type="text";value.className="margin-bottom-no";value.placeholder="Value";wrap.className="row thin margin-bottom-small";cell1.className="col span-6";cell2.className="col span-6";element.parentNode.insertBefore(wrap,element);cell1.appendChild(key);cell2.appendChild(value);wrap.appendChild(cell1);wrap.appendChild(cell2);key.addEventListener("input",function(){syncA();});value.addEventListener("input",function(){syncA();});element.addEventListener("change",function(){syncB();});let syncA=function(){element.value=key.value.toLowerCase()+":"+value.value.toLowerCase();};let syncB=function(){let split=element.value.toLowerCase().split(":");key.value=split[0]||"";value.value=split[1]||"";key.value=key.value.trim();value.value=value.value.trim();};syncB();}}).add({selector:"data-prism",controller:function(window,document,element,alerts){Prism.highlightElement(element);let copy=document.createElement("i");copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.textContent="Click Here to Copy";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(element);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();});element.parentNode.parentNode.appendChild(copy);}}).add({selector:"data-ls-ui-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");child.width=500;child.height=175;let stats=container.get("usage");if(!stats||!stats["requests"]||!stats["requests"]["data"]){return;}
let config={type:"line",data:{labels:[],datasets:[{label:"Requests",backgroundColor:"rgba(230, 248, 253, 0.3)",borderColor:"#29b5d9",borderWidth:2,data:[0,0,0,0,0,0,0],fill:true}]},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<stats["requests"]["data"].length;i++){config.data.datasets[0].data[i]=stats["requests"]["data"][i].value;config.data.labels[i]=date.format("d F Y",stats["requests"]["data"][i].date);}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){window.location=url||"/";};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
@ -2610,24 +2610,25 @@ let attrKey=prefix+key.charAt(0).toUpperCase()+key.slice(1);if(element.dataset[a
if(data[key]){result=data[key];}
if(!result){result="";}
return result;};let resolve=function(target,prefix="param",data={}){if(!target){return function(){};}
let args=getParams(target);return target.apply(target,args.map(function(value){let result=getValue(value,prefix,data);return result;}));};let exec=function(event){action=expression.parse(action);success=expression.parse(success);failure=expression.parse(failure);success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];element.$lsSkip=true;element.classList.add("load-service-start");if(!document.body.contains(element)){element=undefined;return false;}
let args=getParams(target);return target.apply(target,args.map(function(value){let result=getValue(value,prefix,data);return result;}));};let exec=function(event){let parsedSuccess=expression.parse(success);let parsedFailure=expression.parse(failure);let parsedAction=expression.parse(action);parsedSuccess=parsedSuccess&&parsedSuccess!=""?parsedSuccess.split(",").map(element=>element.trim()):[];parsedFailure=parsedFailure&&parsedFailure!=""?parsedFailure.split(",").map(element=>element.trim()):[];element.$lsSkip=true;element.classList.add("load-service-start");if(!document.body.contains(element)){element=undefined;return false;}
if(event){event.preventDefault();}
if(running){return false;}
running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm)!==true){element.classList.add("load-service-end");return false;}}
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
let method=container.path(scope+"."+action);if(!method){throw new Error('Method "'+scope+"."+action+'" not found');}
let method=container.path(scope+"."+parsedAction);if(!method){throw new Error('Method "'+scope+"."+parsedAction+'" not found');}
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);for(let i=0;i<success.length;i++){container.resolve(resolve(callbacks[success[i]],"successParam"+
success[i].charAt(0).toUpperCase()+
success[i].slice(1),{}));}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");if(service){container.set(service.replace(".","-"),data,true,true);}
container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);for(let i=0;i<parsedSuccess.length;i++){container.resolve(resolve(callbacks[parsedSuccess[i]],"successParam"+
parsedSuccess[i].charAt(0).toUpperCase()+
parsedSuccess[i].slice(1),{}));}
container.set("serviceData",null,true,true);container.set("serviceForm",null,true,true);element.$lsSkip=false;view.render(element);},function(exception){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
failure[i].charAt(0).toUpperCase()+
failure[i].slice(1),{}));}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<parsedFailure.length;i++){container.resolve(resolve(callbacks[parsedFailure[i]],"failureParam"+
parsedFailure[i].charAt(0).toUpperCase()+
parsedFailure[i].slice(1),{}));}
element.$lsSkip=false;view.render(element);});};let events=event.trim().split(",");for(let y=0;y<events.length;y++){if(""===events[y]){continue;}
switch(events[y].trim()){case"load":exec();break;case"none":break;case"click":case"change":case"keypress":case"keydown":case"keyup":case"input":case"submit":element.addEventListener(events[y],exec);break;default:document.addEventListener(events[y],exec);}}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-analytics-event",controller:function(element){var action=element.getAttribute("data-analytics-event")||"click";element.addEventListener(action,function(){var category=element.getAttribute("data-analytics-category")||"undefined";var label=element.getAttribute("data-analytics-label")||"undefined";if(!ga){console.error("Google Analytics ga object is not available");}
ga("send",{hitType:"event",eventCategory:category,eventAction:action,eventLabel:label});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-analytics-pageview",controller:function(window,router,env){if(!ga){console.error("Google Analytics ga object is not available");}

View file

@ -301,7 +301,7 @@ let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentLabel",function($value,rule,filter){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentRequired",function($value,rule,filter){if(!$value||$value==='false'){return'';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'required';}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');console.log('isnew?');console.log(document);console.log(document.$id);if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
@ -313,7 +313,7 @@ window.ls.container.get("view").add({selector:"data-acl",controller:function(ele
if("/console"===router.getCurrent().path){document.body.classList.add("index");}else{document.body.classList.remove("index");}}}).add({selector:"data-forms-headers",controller:function(element){let key=document.createElement("input");let value=document.createElement("input");let wrap=document.createElement("div");let cell1=document.createElement("div");let cell2=document.createElement("div");key.type="text";key.className="margin-bottom-no";key.placeholder="Key";value.type="text";value.className="margin-bottom-no";value.placeholder="Value";wrap.className="row thin margin-bottom-small";cell1.className="col span-6";cell2.className="col span-6";element.parentNode.insertBefore(wrap,element);cell1.appendChild(key);cell2.appendChild(value);wrap.appendChild(cell1);wrap.appendChild(cell2);key.addEventListener("input",function(){syncA();});value.addEventListener("input",function(){syncA();});element.addEventListener("change",function(){syncB();});let syncA=function(){element.value=key.value.toLowerCase()+":"+value.value.toLowerCase();};let syncB=function(){let split=element.value.toLowerCase().split(":");key.value=split[0]||"";value.value=split[1]||"";key.value=key.value.trim();value.value=value.value.trim();};syncB();}}).add({selector:"data-prism",controller:function(window,document,element,alerts){Prism.highlightElement(element);let copy=document.createElement("i");copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.textContent="Click Here to Copy";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(element);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();});element.parentNode.parentNode.appendChild(copy);}}).add({selector:"data-ls-ui-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");child.width=500;child.height=175;let stats=container.get("usage");if(!stats||!stats["requests"]||!stats["requests"]["data"]){return;}
let config={type:"line",data:{labels:[],datasets:[{label:"Requests",backgroundColor:"rgba(230, 248, 253, 0.3)",borderColor:"#29b5d9",borderWidth:2,data:[0,0,0,0,0,0,0],fill:true}]},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<stats["requests"]["data"].length;i++){config.data.datasets[0].data[i]=stats["requests"]["data"][i].value;config.data.labels[i]=date.format("d F Y",stats["requests"]["data"][i].date);}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){window.location=url||"/";};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
@ -326,24 +326,25 @@ let attrKey=prefix+key.charAt(0).toUpperCase()+key.slice(1);if(element.dataset[a
if(data[key]){result=data[key];}
if(!result){result="";}
return result;};let resolve=function(target,prefix="param",data={}){if(!target){return function(){};}
let args=getParams(target);return target.apply(target,args.map(function(value){let result=getValue(value,prefix,data);return result;}));};let exec=function(event){action=expression.parse(action);success=expression.parse(success);failure=expression.parse(failure);success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];element.$lsSkip=true;element.classList.add("load-service-start");if(!document.body.contains(element)){element=undefined;return false;}
let args=getParams(target);return target.apply(target,args.map(function(value){let result=getValue(value,prefix,data);return result;}));};let exec=function(event){let parsedSuccess=expression.parse(success);let parsedFailure=expression.parse(failure);let parsedAction=expression.parse(action);parsedSuccess=parsedSuccess&&parsedSuccess!=""?parsedSuccess.split(",").map(element=>element.trim()):[];parsedFailure=parsedFailure&&parsedFailure!=""?parsedFailure.split(",").map(element=>element.trim()):[];element.$lsSkip=true;element.classList.add("load-service-start");if(!document.body.contains(element)){element=undefined;return false;}
if(event){event.preventDefault();}
if(running){return false;}
running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm)!==true){element.classList.add("load-service-end");return false;}}
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
let method=container.path(scope+"."+action);if(!method){throw new Error('Method "'+scope+"."+action+'" not found');}
let method=container.path(scope+"."+parsedAction);if(!method){throw new Error('Method "'+scope+"."+parsedAction+'" not found');}
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);for(let i=0;i<success.length;i++){container.resolve(resolve(callbacks[success[i]],"successParam"+
success[i].charAt(0).toUpperCase()+
success[i].slice(1),{}));}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");if(service){container.set(service.replace(".","-"),data,true,true);}
container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);for(let i=0;i<parsedSuccess.length;i++){container.resolve(resolve(callbacks[parsedSuccess[i]],"successParam"+
parsedSuccess[i].charAt(0).toUpperCase()+
parsedSuccess[i].slice(1),{}));}
container.set("serviceData",null,true,true);container.set("serviceForm",null,true,true);element.$lsSkip=false;view.render(element);},function(exception){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
failure[i].charAt(0).toUpperCase()+
failure[i].slice(1),{}));}
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<parsedFailure.length;i++){container.resolve(resolve(callbacks[parsedFailure[i]],"failureParam"+
parsedFailure[i].charAt(0).toUpperCase()+
parsedFailure[i].slice(1),{}));}
element.$lsSkip=false;view.render(element);});};let events=event.trim().split(",");for(let y=0;y<events.length;y++){if(""===events[y]){continue;}
switch(events[y].trim()){case"load":exec();break;case"none":break;case"click":case"change":case"keypress":case"keydown":case"keyup":case"input":case"submit":element.addEventListener(events[y],exec);break;default:document.addEventListener(events[y],exec);}}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-analytics-event",controller:function(element){var action=element.getAttribute("data-analytics-event")||"click";element.addEventListener(action,function(){var category=element.getAttribute("data-analytics-category")||"undefined";var label=element.getAttribute("data-analytics-label")||"undefined";if(!ga){console.error("Google Analytics ga object is not available");}
ga("send",{hitType:"event",eventCategory:category,eventAction:action,eventLabel:label});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-analytics-pageview",controller:function(window,router,env){if(!ga){console.error("Google Analytics ga object is not available");}

View file

@ -398,6 +398,10 @@ window.ls.filter
let collection = container.get('project-collection');
let document = container.get('project-document');
console.log('isnew?');
console.log(document);
console.log(document.$id);
if(collection && document && !document.$id) {
return 'database.createDocument';
}

View file

@ -5,7 +5,7 @@
selector: "data-service",
controller: function(element, view, container, form, alerts, expression, window) {
let action = element.dataset["service"];
let service = element.dataset["name"] || action;
let service = element.dataset["name"] || null;
let event = expression.parse(element.dataset["event"]); // load, click, change, submit
let confirm = element.dataset["confirm"] || ""; // Free text
let loading = element.dataset["loading"] || ""; // Free text
@ -258,17 +258,17 @@
let exec = function(event) {
action = expression.parse(action);
success = expression.parse(success);
failure = expression.parse(failure);
success =
success && success != ""
? success.split(",").map(element => element.trim())
let parsedSuccess = expression.parse(success);
let parsedFailure = expression.parse(failure);
let parsedAction = expression.parse(action);
parsedSuccess =
parsedSuccess && parsedSuccess != ""
? parsedSuccess.split(",").map(element => element.trim())
: [];
failure =
failure && failure != ""
? failure.split(",").map(element => element.trim())
parsedFailure =
parsedFailure && parsedFailure != ""
? parsedFailure.split(",").map(element => element.trim())
: [];
element.$lsSkip = true;
@ -302,10 +302,10 @@
loaderId = alerts.add({ text: loading, class: "" }, 0);
}
let method = container.path(scope + "." + action);
let method = container.path(scope + "." + parsedAction);
if (!method) {
throw new Error('Method "' + scope + "." + action + '" not found');
throw new Error('Method "' + scope + "." + parsedAction + '" not found');
}
let formData = "FORM" === element.tagName ? form.toJson(element) : {};
@ -337,18 +337,21 @@
element.style.backgroud = 'transparent';
element.classList.add("load-service-end");
container.set(service.replace(".", "-"), data, true, true);
if(service) {
container.set(service.replace(".", "-"), data, true, true);
}
container.set("serviceData", data, true, true);
container.set("serviceForm", formData, true, true);
for (let i = 0; i < success.length; i++) {
for (let i = 0; i < parsedSuccess.length; i++) {
// Trigger success callbacks
container.resolve(
resolve(
callbacks[success[i]],
callbacks[parsedSuccess[i]],
"successParam" +
success[i].charAt(0).toUpperCase() +
success[i].slice(1),
parsedSuccess[i].charAt(0).toUpperCase() +
parsedSuccess[i].slice(1),
{}
)
);
@ -375,14 +378,14 @@
element.style.backgroud = 'transparent';
element.classList.add("load-service-end");
for (let i = 0; i < failure.length; i++) {
for (let i = 0; i < parsedFailure.length; i++) {
// Trigger failure callbacks
container.resolve(
resolve(
callbacks[failure[i]],
callbacks[parsedFailure[i]],
"failureParam" +
failure[i].charAt(0).toUpperCase() +
failure[i].slice(1),
parsedFailure[i].charAt(0).toUpperCase() +
parsedFailure[i].slice(1),
{}
)
);