Merge branch 'master' of github.com:appwrite/appwrite into 0.9.x
|
@ -8,6 +8,7 @@
|
||||||
- Renamed *Devices* to *Sessions*
|
- Renamed *Devices* to *Sessions*
|
||||||
- Add Provider Icon to each Session
|
- Add Provider Icon to each Session
|
||||||
- Add Anonymous Account Placeholder
|
- Add Anonymous Account Placeholder
|
||||||
|
- Upgraded telegraf docker image version to v1.1.0
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
|
|
||||||
|
@ -56,6 +57,8 @@
|
||||||
- Fixed incorrect audit worker event names (#1143)
|
- Fixed incorrect audit worker event names (#1143)
|
||||||
- Increased limit of memberships fetched in `createTeamMembership` to 2000 (#1143)
|
- Increased limit of memberships fetched in `createTeamMembership` to 2000 (#1143)
|
||||||
- Fixed exception thrown when SSL certificate is already stored in the database (#1151)
|
- Fixed exception thrown when SSL certificate is already stored in the database (#1151)
|
||||||
|
- Fixed user delete button in the Appwrite console (#1216)
|
||||||
|
- Fixed missing placeholder for user name when empty (#1220)
|
||||||
|
|
||||||
## Breaking Changes (Read before upgrading!)
|
## Breaking Changes (Read before upgrading!)
|
||||||
|
|
||||||
|
|
|
@ -1268,7 +1268,7 @@ App::post('/v1/projects/:projectId/platforms')
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_PLATFORM)
|
->label('sdk.response.model', Response::MODEL_PLATFORM)
|
||||||
->param('projectId', null, new UID(), 'Project unique ID.')
|
->param('projectId', null, new UID(), 'Project unique ID.')
|
||||||
->param('type', null, new WhiteList(['web', 'flutter-ios', 'flutter-android', 'ios', 'android', 'unity'], true), 'Platform type.')
|
->param('type', null, new WhiteList(['web', 'flutter-ios', 'flutter-android', 'flutter-linux', 'flutter-macos', 'flutter-windows', 'ios', 'android', 'unity'], true), 'Platform type.')
|
||||||
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
|
->param('name', null, new Text(128), 'Platform name. Max length: 128 chars.')
|
||||||
->param('key', '', new Text(256), 'Package name for android or bundle ID for iOS. Max length: 256 chars.', true)
|
->param('key', '', new Text(256), 'Package name for android or bundle ID for iOS. Max length: 256 chars.', true)
|
||||||
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
|
->param('store', '', new Text(256), 'App store or Google Play store ID. Max length: 256 chars.', true)
|
||||||
|
|
|
@ -783,7 +783,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
||||||
|
|
||||||
if ($membership->getAttribute('confirm')) { // Count only confirmed members
|
if ($membership->getAttribute('confirm')) { // Count only confirmed members
|
||||||
$team = $projectDB->updateDocument(\array_merge($team->getArrayCopy(), [
|
$team = $projectDB->updateDocument(\array_merge($team->getArrayCopy(), [
|
||||||
'sum' => $team->getAttribute('sum', 0) - 1,
|
'sum' => \max($team->getAttribute('sum', 0) - 1, 0), // Ensure that sum >= 0
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,31 @@ App::delete('/v1/mock/tests/bar')
|
||||||
->action(function ($x, $y, $z) {
|
->action(function ($x, $y, $z) {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
App::get('/v1/mock/tests/general/download')
|
||||||
|
->desc('Download File')
|
||||||
|
->groups(['mock'])
|
||||||
|
->label('scope', 'public')
|
||||||
|
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
|
||||||
|
->label('sdk.namespace', 'general')
|
||||||
|
->label('sdk.method', 'download')
|
||||||
|
->label('sdk.methodType', 'location')
|
||||||
|
->label('sdk.description', 'Mock a file download request.')
|
||||||
|
->label('sdk.response.type', '*/*')
|
||||||
|
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||||
|
->label('sdk.mock', true)
|
||||||
|
->inject('response')
|
||||||
|
->action(function ($response) {
|
||||||
|
/** @var Utopia\Swoole\Request $request */
|
||||||
|
|
||||||
|
$response
|
||||||
|
->setContentType('text/plain')
|
||||||
|
->addHeader('Content-Disposition', 'attachment; filename="test.txt"')
|
||||||
|
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
|
||||||
|
->addHeader('X-Peak', \memory_get_peak_usage())
|
||||||
|
->send("Download test passed.")
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
App::post('/v1/mock/tests/general/upload')
|
App::post('/v1/mock/tests/general/upload')
|
||||||
->desc('Upload File')
|
->desc('Upload File')
|
||||||
->groups(['mock'])
|
->groups(['mock'])
|
||||||
|
|
|
@ -184,11 +184,23 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||||
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Platform Logo" class="avatar" loading="lazy" width="60" height="60" />
|
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Platform Logo" class="avatar" loading="lazy" width="60" height="60" />
|
||||||
|
|
||||||
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
|
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
|
||||||
<img src="" data-ls-attrs="src=/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
|
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
|
||||||
<img src="" data-ls-attrs="src=/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-ls-if="{{platform.type}} === 'flutter-linux'" class="corner">
|
||||||
|
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Linux Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-ls-if="{{platform.type}} === 'flutter-macos'" class="corner">
|
||||||
|
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="MacOS Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-ls-if="{{platform.type}} === 'flutter-windows'" class="corner">
|
||||||
|
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Windows Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-one-liner" data-ls-bind="{{platform.name}}"></span>
|
<span class="text-one-liner" data-ls-bind="{{platform.name}}"></span>
|
||||||
|
@ -317,7 +329,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||||
</form>
|
</form>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-ui-modal class="modal box close" data-button-alias=".flutter-new">
|
<div data-ui-modal class="modal box close width-large" data-button-alias=".flutter-new">
|
||||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||||
|
|
||||||
<h1 class="margin-bottom-xl">Register your Flutter App</h1>
|
<h1 class="margin-bottom-xl">Register your Flutter App</h1>
|
||||||
|
@ -387,6 +399,105 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<button type="submit">Register</button> <button data-ui-modal-close="" type="button" class="reverse">Back</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2 style="display: none"> Linux </h2>
|
||||||
|
|
||||||
|
<form
|
||||||
|
data-analytics
|
||||||
|
data-analytics-activity
|
||||||
|
data-analytics-event="submit"
|
||||||
|
data-analytics-category="console"
|
||||||
|
data-analytics-label="Create Project Platform (Flutter / Linux)"
|
||||||
|
data-service="projects.createPlatform"
|
||||||
|
data-scope="console"
|
||||||
|
data-event="submit"
|
||||||
|
data-success="alert,trigger,reset"
|
||||||
|
data-success-param-alert-text="Registered new platform successfully"
|
||||||
|
data-success-param-trigger-events="projects.createPlatform"
|
||||||
|
data-failure="alert"
|
||||||
|
data-failure-param-alert-text="Failed to register platform"
|
||||||
|
data-failure-param-alert-classname="error">
|
||||||
|
|
||||||
|
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||||
|
<input type="hidden" name="type" data-ls-bind="flutter-linux" />
|
||||||
|
|
||||||
|
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="name" required autocomplete="off" placeholder="My Linux App" maxlength="128" />
|
||||||
|
|
||||||
|
<label for="key">Package Name <span class="tooltip large" data-tooltip="Your application name"><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="key" required autocomplete="off" placeholder="appname" />
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<button type="submit">Register</button> <button data-ui-modal-close="" type="button" class="reverse">Back</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2 style="display: none"> MacOS </h2>
|
||||||
|
|
||||||
|
<form
|
||||||
|
data-analytics
|
||||||
|
data-analytics-activity
|
||||||
|
data-analytics-event="submit"
|
||||||
|
data-analytics-category="console"
|
||||||
|
data-analytics-label="Create Project Platform (Flutter / Mac OS)"
|
||||||
|
data-service="projects.createPlatform"
|
||||||
|
data-scope="console"
|
||||||
|
data-event="submit"
|
||||||
|
data-success="alert,trigger,reset"
|
||||||
|
data-success-param-alert-text="Registered new platform successfully"
|
||||||
|
data-success-param-trigger-events="projects.createPlatform"
|
||||||
|
data-failure="alert"
|
||||||
|
data-failure-param-alert-text="Failed to register platform"
|
||||||
|
data-failure-param-alert-classname="error">
|
||||||
|
|
||||||
|
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||||
|
<input type="hidden" name="type" data-ls-bind="flutter-macos" />
|
||||||
|
|
||||||
|
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="name" required autocomplete="off" placeholder="My Mac OS App" maxlength="128" />
|
||||||
|
|
||||||
|
<label for="key">Bundle ID <span class="tooltip large" data-tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="key" required autocomplete="off" placeholder="com.company.appname" />
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<button type="submit">Register</button> <button data-ui-modal-close="" type="button" class="reverse">Back</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2 style="display: none"> Windows </h2>
|
||||||
|
|
||||||
|
<form
|
||||||
|
data-analytics
|
||||||
|
data-analytics-activity
|
||||||
|
data-analytics-event="submit"
|
||||||
|
data-analytics-category="console"
|
||||||
|
data-analytics-label="Create Project Platform (Flutter / Windows)"
|
||||||
|
data-service="projects.createPlatform"
|
||||||
|
data-scope="console"
|
||||||
|
data-event="submit"
|
||||||
|
data-success="alert,trigger,reset"
|
||||||
|
data-success-param-alert-text="Registered new platform successfully"
|
||||||
|
data-success-param-trigger-events="projects.createPlatform"
|
||||||
|
data-failure="alert"
|
||||||
|
data-failure-param-alert-text="Failed to register platform"
|
||||||
|
data-failure-param-alert-classname="error">
|
||||||
|
|
||||||
|
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
|
||||||
|
<input type="hidden" name="type" data-ls-bind="flutter-windows" />
|
||||||
|
|
||||||
|
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="name" required autocomplete="off" placeholder="My Windows App" maxlength="128" />
|
||||||
|
|
||||||
|
<label for="key">Package Name <span class="tooltip large" data-tooltip="Your application name"><i class="icon-question"></i></span></label>
|
||||||
|
<input type="text" class="full-width" name="key" required autocomplete="off" placeholder="appname" />
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<button type="submit">Register</button> <button data-ui-modal-close="" type="button" class="reverse">Back</button>
|
<button type="submit">Register</button> <button data-ui-modal-close="" type="button" class="reverse">Back</button>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -77,8 +77,8 @@ $auth = $this->getParam('auth', []);
|
||||||
<td data-title="Name: ">
|
<td data-title="Name: ">
|
||||||
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
|
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
|
||||||
<span data-ls-bind="{{user.name}}"></span>
|
<span data-ls-bind="{{user.name}}"></span>
|
||||||
<span data-ls-if="{{user.name|escape}} === ''">-----</span>
|
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} !== ''">Unknown</span>
|
||||||
<span data-ls-if="{{user.email}} === ''">Anonymous User</span>
|
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === ''">Anonymous User</span>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="Email: ">
|
<td data-title="Email: ">
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span data-ls-bind="{{team.name}}"> </span>
|
<span data-ls-bind="{{team.name}}"> </span>
|
||||||
<span data-ls-if="{{team.name}} === ''">Unknown</span>
|
<span data-ls-if="{{team.name|escape}} === ''">Unknown</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span data-ls-bind="{{user.name}}"> </span>
|
<span data-ls-bind="{{user.name}}"> </span>
|
||||||
<span data-ls-if="{{user.name}} === '' && {{user.email}} !== ''">Unknown</span>
|
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} !== ''">Unknown</span>
|
||||||
<span data-ls-if="{{user.name}} === '' && {{user.email}} === ''">Anonymous User</span>
|
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === ''">Anonymous User</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
|
|
||||||
<h3 class="text-danger">Danger Zone</h3>
|
<h3 class="text-danger">Danger Zone</h3>
|
||||||
|
|
||||||
<div class="box danger">
|
<div class="box danger margin-bottom">
|
||||||
<p>This is the area where you can delete this user.</p>
|
<p>This is the area where you can delete this user.</p>
|
||||||
|
|
||||||
<p>By deleting this user you will lose all data associated with this user.</p>
|
<p>By deleting this user you will lose all data associated with this user.</p>
|
||||||
|
@ -218,7 +218,7 @@
|
||||||
<button class="danger">Logout</button>
|
<button class="danger">Logout</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="pull-start margin-end avatar-container">
|
<div class="pull-start margin-end avatar-container">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=60&height=60&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar" loading="lazy" width="60" height="60" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar" loading="lazy" width="60" height="60" />
|
||||||
|
|
||||||
<div data-ls-if="{{session.provider}} !== 'email'" class="corner">
|
<div data-ls-if="{{session.provider}} !== 'email'" class="corner">
|
||||||
<img data-ls-attrs="src=/images/users/{{session.provider}}.png?buster=<?php echo APP_CACHE_BUSTER; ?>,title={{session.provider}},alt={{session.provider}}" class="avatar xs" loading="lazy" width="30" height="30" />
|
<img data-ls-attrs="src=/images/users/{{session.provider}}.png?buster=<?php echo APP_CACHE_BUSTER; ?>,title={{session.provider}},alt={{session.provider}}" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
|
@ -228,7 +228,7 @@
|
||||||
<span data-ls-bind="{{session.clientName}}"></span> <span data-ls-bind="{{session.clientVersion}}"></span> on <span data-ls-bind="{{session.deviceModel}}"></span> <span data-ls-bind="{{session.osName}}"></span> <span data-ls-bind="{{session.osVersion}}"></span>
|
<span data-ls-bind="{{session.clientName}}"></span> <span data-ls-bind="{{session.clientVersion}}"></span> on <span data-ls-bind="{{session.deviceModel}}"></span> <span data-ls-bind="{{session.osName}}"></span> <span data-ls-bind="{{session.osVersion}}"></span>
|
||||||
|
|
||||||
<div class="margin-top-small">
|
<div class="margin-top-small">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=120&height=120&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
||||||
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.countryName}}"></small>
|
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.countryName}}"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -265,11 +265,11 @@
|
||||||
data-param-user-id="{{router.params.id}}"
|
data-param-user-id="{{router.params.id}}"
|
||||||
data-event="load,logs-load">
|
data-event="load,logs-load">
|
||||||
|
|
||||||
<div data-ls-if="{{logs.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
|
<div data-ls-if="{{logs.logs.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
|
||||||
No logs available.
|
No logs available.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box" data-ls-if="{{logs.length}} !== 0" style="display: none">
|
<div class="box" data-ls-if="{{logs.logs.length}} !== 0" style="display: none">
|
||||||
<table class="vertical small">
|
<table class="vertical small">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -372,7 +372,7 @@ services:
|
||||||
- appwrite-influxdb:/var/lib/influxdb:rw
|
- appwrite-influxdb:/var/lib/influxdb:rw
|
||||||
|
|
||||||
telegraf:
|
telegraf:
|
||||||
image: appwrite/telegraf:1.0.0
|
image: appwrite/telegraf:1.1.0
|
||||||
container_name: appwrite-telegraf
|
container_name: appwrite-telegraf
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -32,7 +32,7 @@ class DeletesV1
|
||||||
|
|
||||||
public function perform()
|
public function perform()
|
||||||
{
|
{
|
||||||
$projectId = $this->args['projectId'];
|
$projectId = isset($this->args['projectId']) ? $this->args['projectId'] : '';
|
||||||
$type = $this->args['type'];
|
$type = $this->args['type'];
|
||||||
|
|
||||||
switch (strval($type)) {
|
switch (strval($type)) {
|
||||||
|
@ -127,11 +127,22 @@ class DeletesV1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete Memberships
|
// Delete Memberships and decrement team membership counts
|
||||||
$this->deleteByGroup([
|
$this->deleteByGroup([
|
||||||
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
|
||||||
'userId='.$document->getId(),
|
'userId='.$document->getId(),
|
||||||
], $this->getProjectDB($projectId));
|
], $this->getProjectDB($projectId), function(Document $document) use ($projectId) {
|
||||||
|
|
||||||
|
if ($document->getAttribute('confirm')) { // Count only confirmed members
|
||||||
|
$teamId = $document->getAttribute('teamId');
|
||||||
|
$team = $this->getProjectDB($projectId)->getDocument($teamId);
|
||||||
|
if(!$team->isEmpty()) {
|
||||||
|
$team = $this->getProjectDB($projectId)->updateDocument(\array_merge($team->getArrayCopy(), [
|
||||||
|
'sum' => \max($team->getAttribute('sum', 0) - 1, 0), // Ensure that sum >= 0
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deleteExecutionLogs($timestamp)
|
protected function deleteExecutionLogs($timestamp)
|
||||||
|
|
175
public/dist/scripts/app-all.js
vendored
|
@ -1960,145 +1960,128 @@ function join(string1,string2){var separator=separatingNewlines(string1,string2)
|
||||||
function canConvert(input){return(input!=null&&(typeof input==='string'||(input.nodeType&&(input.nodeType===1||input.nodeType===9||input.nodeType===11))))}
|
function canConvert(input){return(input!=null&&(typeof input==='string'||(input.nodeType&&(input.nodeType===1||input.nodeType===9||input.nodeType===11))))}
|
||||||
return TurndownService;}());
|
return TurndownService;}());
|
||||||
|
|
||||||
window.ls=window.ls||{};window.ls.container=function(){let stock={};let listeners={};let namespaces={};let set=function(name,object,singleton,watch=true){if(typeof name!=='string'){throw new Error('var name must be of type string');}
|
window.ls=window.ls||{};window.ls.container=(function(){let stock={};let listeners={};let namespaces={};let set=function(name,object,singleton,watch=true){if(typeof name!=="string"){throw new Error("var name must be of type string");}
|
||||||
if(typeof singleton!=='boolean'){throw new Error('var singleton "'+singleton+'" of service "'+name+'" must be of type boolean');}
|
if(typeof singleton!=="boolean"){throw new Error('var singleton "'+
|
||||||
|
singleton+'" of service "'+
|
||||||
|
name+'" must be of type boolean');}
|
||||||
stock[name]={name:name,object:object,singleton:singleton,instance:null,watch:watch,};if(!watch){return this;}
|
stock[name]={name:name,object:object,singleton:singleton,instance:null,watch:watch,};if(!watch){return this;}
|
||||||
let binds=listeners[name]||{};for(let key in binds){if(binds.hasOwnProperty(key)){document.dispatchEvent(new CustomEvent(key));}}
|
let binds=listeners[name]||{};for(let key in binds){if(binds.hasOwnProperty(key)){document.dispatchEvent(new CustomEvent(key));}}
|
||||||
return this;};let get=function(name){let service=(undefined!==stock[name])?stock[name]:null;if(null==service){return null;}
|
return this;};let get=function(name){let service=undefined!==stock[name]?stock[name]:null;if(null==service){return null;}
|
||||||
if(service.instance){return service.instance;}
|
if(service.instance){return service.instance;}
|
||||||
let instance=(typeof service.object==='function')?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=='window'&&name!=='document'&&name!=='element'&&typeof instance==='object'&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;}
|
let instance=typeof service.object==="function"?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=="window"&&name!=="document"&&name!=="element"&&typeof instance==="object"&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;}
|
||||||
if(key==="__watch"){return this.watch;}
|
if(key==="__watch"){return this.watch;}
|
||||||
if(key==="__proxy"){return true;}
|
if(key==="__proxy"){return true;}
|
||||||
if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)}
|
if(typeof target[key]==="object"&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+"."+key;return new Proxy(target[key],handler);}else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return(this.name=value);}
|
||||||
else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;}
|
if(key==="__watch"){return(this.watch=value);}
|
||||||
if(key==="__watch"){return this.watch=value;}
|
target[key]=value;let path=receiver.__name+"."+key;document.dispatchEvent(new CustomEvent(path+".changed"));if(skip){return true;}
|
||||||
target[key]=value;let path=receiver.__name+'.'+key;document.dispatchEvent(new CustomEvent(path+'.changed'));if(skip){return true;}
|
skip=true;container.set("$prop",key,true);container.set("$value",value,true);container.resolve(this.watch);container.set("$key",null,true);container.set("$value",null,true);skip=false;return true;},};instance=new Proxy(instance,handler);}
|
||||||
skip=true;container.set('$prop',key,true);container.set('$value',value,true);container.resolve(this.watch);container.set('$key',null,true);container.set('$value',null,true);skip=false;return true;},};instance=new Proxy(instance,handler);}
|
|
||||||
if(service.singleton){service.instance=instance;}
|
if(service.singleton){service.instance=instance;}
|
||||||
return instance;};let resolve=function(target){if(!target){return()=>{};}
|
return instance;};let resolve=function(target){if(!target){return()=>{};}
|
||||||
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;function getParams(func){let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,'');functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==='('){functionAsString=functionAsString.slice(1,-1);}
|
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;function getParams(func){let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,"");functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==="("){functionAsString=functionAsString.slice(1,-1);}
|
||||||
while(match=REGEX_PARAMETERS_VALUES.exec(functionAsString)){params.push(match[1]);}
|
while((match=REGEX_PARAMETERS_VALUES.exec(functionAsString))){params.push(match[1]);}
|
||||||
return params;}
|
return params;}
|
||||||
let args=getParams(target);return target.apply(target,args.map(function(value){return self.get(value.trim());}));};let path=function(path,value,type){type=(type)?type:'assign';path=container.scope(path).split('.');let name=path.shift();let object=container.get(name);let result=null;while(path.length>1){if(!object){return null;}
|
let args=getParams(target);return target.apply(target,args.map(function(value){return self.get(value.trim());}));};let path=function(path,value,type){type=type?type:"assign";path=container.scope(path).split(".");let name=path.shift();let object=container.get(name);let result=null;while(path.length>1){if(!object){return null;}
|
||||||
object=object[path.shift()];}
|
object=object[path.shift()];}
|
||||||
let shift=path.shift();if(value!==null&&value!==undefined&&object&&shift&&(object[shift]!==undefined||object[shift]!==null)){switch(type){case'append':if(!Array.isArray(object[shift])){object[shift]=[];}
|
let shift=path.shift();if(value!==null&&value!==undefined&&object&&shift&&(object[shift]!==undefined||object[shift]!==null)){switch(type){case"append":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].push(value);break;case'prepend':if(!Array.isArray(object[shift])){object[shift]=[];}
|
object[shift].push(value);break;case"prepend":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].unshift(value);break;case'splice':if(!Array.isArray(object[shift])){object[shift]=[];}
|
object[shift].unshift(value);break;case"splice":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].splice(value,1);break;default:object[shift]=value;}
|
object[shift].splice(value,1);break;default:object[shift]=value;}
|
||||||
return true;}
|
return true;}
|
||||||
if(!object){return null;}
|
if(!object){return null;}
|
||||||
if(!shift){result=object;}
|
if(!shift){result=object;}else{return object[shift];}
|
||||||
else{return object[shift];}
|
return result;};let bind=function(element,path,callback){let event=container.scope(path)+".changed";let service=event.split(".").slice(0,1).pop();let debug=element.getAttribute("data-debug")||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;}
|
||||||
return result;};let bind=function(element,path,callback){let event=container.scope(path)+'.changed';let service=event.split('.').slice(0,1).pop();let debug=element.getAttribute('data-debug')||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;}
|
let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;};})(Object.assign({},namespaces));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;};let removeNamespace=function(key){delete namespaces[key];return this;};let scope=function(path){for(let[key,value]of Object.entries(namespaces)){path=path.indexOf(".")>-1?path.replace(key+".",value+"."):path.replace(key,value);}
|
||||||
let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;}}(Object.assign({},namespaces)));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;}
|
return path;};let container={set:set,get:get,resolve:resolve,path:path,bind:bind,scope:scope,addNamespace:addNamespace,removeNamespace:removeNamespace,stock:stock,listeners:listeners,namespaces:namespaces,};set("container",container,true,false);return container;})();window.ls.container.set("http",function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){param=encodeURIComponent(param);let a=document.createElement("a");param+=value?"="+encodeURIComponent(value):"";a.href=url;a.search+=(a.search?"&":"")+param;return a.href;};let request=function(method,url,headers,payload,progress){let i;if(-1===["GET","POST","PUT","DELETE","TRACE","HEAD","OPTIONS","CONNECT","PATCH",].indexOf(method)){throw new Error("var method must contain a valid HTTP method name");}
|
||||||
let removeNamespace=function(key){delete namespaces[key];return this;}
|
if(typeof url!=="string"){throw new Error("var url must be of type string");}
|
||||||
let scope=function(path){for(let[key,value]of Object.entries(namespaces)){path=(path.indexOf('.')>-1)?path.replace(key+'.',value+'.'):path.replace(key,value);}
|
if(typeof headers!=="object"){throw new Error("var headers must be of type object");}
|
||||||
return path;}
|
if(typeof url!=="string"){throw new Error("var url must be of type string");}
|
||||||
let container={set:set,get:get,resolve:resolve,path:path,bind:bind,scope:scope,addNamespace:addNamespace,removeNamespace:removeNamespace,stock:stock,listeners:listeners,namespaces:namespaces,};set('container',container,true,false);return container;}();window.ls.container.set('http',function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){param=encodeURIComponent(param);let a=document.createElement('a');param+=(value?"="+encodeURIComponent(value):"");a.href=url;a.search+=(a.search?"&":"")+param;return a.href;};let request=function(method,url,headers,payload,progress){let i;if(-1===['GET','POST','PUT','DELETE','TRACE','HEAD','OPTIONS','CONNECT','PATCH'].indexOf(method)){throw new Error('var method must contain a valid HTTP method name');}
|
|
||||||
if(typeof url!=='string'){throw new Error('var url must be of type string');}
|
|
||||||
if(typeof headers!=='object'){throw new Error('var headers must be of type object');}
|
|
||||||
if(typeof url!=='string'){throw new Error('var url must be of type string');}
|
|
||||||
for(i=0;i<globalParams.length;i++){url=addParam(url,globalParams[i].key,globalParams[i].value);}
|
for(i=0;i<globalParams.length;i++){url=addParam(url,globalParams[i].key,globalParams[i].value);}
|
||||||
return new Promise(function(resolve,reject){let xmlhttp=new XMLHttpRequest();xmlhttp.open(method,url,true);for(i=0;i<globalHeaders.length;i++){xmlhttp.setRequestHeader(globalHeaders[i].key,globalHeaders[i].value);}
|
return new Promise(function(resolve,reject){let xmlhttp=new XMLHttpRequest();xmlhttp.open(method,url,true);for(i=0;i<globalHeaders.length;i++){xmlhttp.setRequestHeader(globalHeaders[i].key,globalHeaders[i].value);}
|
||||||
for(let key in headers){if(headers.hasOwnProperty(key)){xmlhttp.setRequestHeader(key,headers[key]);}}
|
for(let key in headers){if(headers.hasOwnProperty(key)){xmlhttp.setRequestHeader(key,headers[key]);}}
|
||||||
xmlhttp.onload=function(){if(4===xmlhttp.readyState&&200===xmlhttp.status){resolve(xmlhttp.response);}
|
xmlhttp.onload=function(){if(4===xmlhttp.readyState&&200===xmlhttp.status){resolve(xmlhttp.response);}else{document.dispatchEvent(new CustomEvent("http-"+method.toLowerCase()+"-"+xmlhttp.status));reject(new Error(xmlhttp.statusText));}};if(progress){xmlhttp.addEventListener("progress",progress);xmlhttp.upload.addEventListener("progress",progress,false);}
|
||||||
else{document.dispatchEvent(new CustomEvent('http-'+method.toLowerCase()+'-'+xmlhttp.status));reject(new Error(xmlhttp.statusText));}};if(progress){xmlhttp.addEventListener('progress',progress);xmlhttp.upload.addEventListener('progress',progress,false);}
|
xmlhttp.onerror=function(){reject(new Error("Network Error"));};xmlhttp.send(payload);});};return{get:function(url){return request("GET",url,{},"");},post:function(url,headers,payload){return request("POST",url,headers,payload);},put:function(url,headers,payload){return request("PUT",url,headers,payload);},patch:function(url,headers,payload){return request("PATCH",url,headers,payload);},delete:function(url){return request("DELETE",url,{},"");},addGlobalParam:function(key,value){globalParams.push({key:key,value:value});},addGlobalHeader:function(key,value){globalHeaders.push({key:key,value:value});},};},true,false);window.ls.container.set("cookie",function(document){function get(name){let value="; "+document.cookie,parts=value.split("; "+name+"=");if(parts.length===2){return parts.pop().split(";").shift();}
|
||||||
xmlhttp.onerror=function(){reject(new Error("Network Error"));};xmlhttp.send(payload);})};return{'get':function(url){return request('GET',url,{},'')},'post':function(url,headers,payload){return request('POST',url,headers,payload)},'put':function(url,headers,payload){return request('PUT',url,headers,payload)},'patch':function(url,headers,payload){return request('PATCH',url,headers,payload)},'delete':function(url){return request('DELETE',url,{},'')},'addGlobalParam':function(key,value){globalParams.push({key:key,value:value});},'addGlobalHeader':function(key,value){globalHeaders.push({key:key,value:value});}}},true,false);window.ls.container.set('cookie',function(document){function get(name){let value="; "+document.cookie,parts=value.split("; "+name+"=");if(parts.length===2){return parts.pop().split(";").shift();}
|
|
||||||
return null;}
|
return null;}
|
||||||
function set(name,value,days){let date=new Date();date.setTime(date.getTime()+(days*24*60*60*1000));let expires=(0<days)?'expires='+date.toUTCString():'expires=0';document.cookie=name+"="+value+";"+expires+";path=/";return this;}
|
function set(name,value,days){let date=new Date();date.setTime(date.getTime()+days*24*60*60*1000);let expires=0<days?"expires="+date.toUTCString():"expires=0";document.cookie=name+"="+value+";"+expires+";path=/";return this;}
|
||||||
return{'get':get,'set':set}},true,false);window.ls.container.set('view',function(http,container){let stock={};let execute=function(view,node,container){container.set('element',node,true,false);container.resolve(view.controller);if(true!==view.repeat){node.removeAttribute(view.selector);}};let parse=function(node,skip,callback){if(node.tagName==='SCRIPT'){return;}
|
return{get:get,set:set};},true,false);window.ls.container.set("view",function(http,container){let stock={};let execute=function(view,node,container){container.set("element",node,true,false);container.resolve(view.controller);if(true!==view.repeat){node.removeAttribute(view.selector);}};let parse=function(node,skip,callback){if(node.tagName==="SCRIPT"){return;}
|
||||||
if(node.attributes&&skip!==true){let attrs=[];let attrsLen=node.attributes.length;for(let x=0;x<attrsLen;x++){attrs.push(node.attributes[x].nodeName);}
|
if(node.attributes&&skip!==true){let attrs=[];let attrsLen=node.attributes.length;for(let x=0;x<attrsLen;x++){attrs.push(node.attributes[x].nodeName);}
|
||||||
if(1!==node.nodeType){return;}
|
if(1!==node.nodeType){return;}
|
||||||
if(attrs&&attrsLen){for(let x=0;x<attrsLen;x++){if(node.$lsSkip===true){break;}
|
if(attrs&&attrsLen){for(let x=0;x<attrsLen;x++){if(node.$lsSkip===true){break;}
|
||||||
let pointer=(!/Edge/.test(navigator.userAgent))?x:(attrsLen-1)-x;let length=attrsLen;let attr=attrs[pointer];if(!stock[attr]){continue;}
|
let pointer=!/Edge/.test(navigator.userAgent)?x:attrsLen-1-x;let length=attrsLen;let attr=attrs[pointer];if(!stock[attr]){continue;}
|
||||||
let comp=stock[attr];if(typeof comp.template==="function"){comp.template=container.resolve(comp.template);}
|
let comp=stock[attr];if(typeof comp.template==="function"){comp.template=container.resolve(comp.template);}
|
||||||
if(!comp.template){(function(comp,node,container){execute(comp,node,container);})(comp,node,container);if(length!==attrsLen){x--;}
|
if(!comp.template){(function(comp,node,container){execute(comp,node,container);})(comp,node,container);if(length!==attrsLen){x--;}
|
||||||
if(callback){callback();}
|
if(callback){callback();}
|
||||||
continue;}
|
continue;}
|
||||||
node.classList.remove('load-end');node.classList.add('load-start');node.$lsSkip=true;http.get(comp.template).then(function(node,comp){return function(data){node.$lsSkip=false;node.innerHTML=data;node.classList.remove('load-start');node.classList.add('load-end');(function(comp,node,container){execute(comp,node,container);})(comp,node,container);parse(node,true);if(callback){callback();}}}(node,comp),function(error){throw new Error('Failed to load comp template: '+error.message);});}}}
|
node.classList.remove("load-end");node.classList.add("load-start");node.$lsSkip=true;http.get(comp.template).then((function(node,comp){return function(data){node.$lsSkip=false;node.innerHTML=data;node.classList.remove("load-start");node.classList.add("load-end");(function(comp,node,container){execute(comp,node,container);})(comp,node,container);parse(node,true);if(callback){callback();}};})(node,comp),function(error){throw new Error("Failed to load comp template: "+error.message);});}}}
|
||||||
if(true===node.$lsSkip){return;}
|
if(true===node.$lsSkip){return;}
|
||||||
let list=(node)?node.childNodes:[];if(node.$lsSkip===true){list=[];}
|
let list=node?node.childNodes:[];if(node.$lsSkip===true){list=[];}
|
||||||
for(let i=0;i<list.length;i++){let child=list[i];parse(child);}};return{stock:stock,add:function(object){if(typeof object!=='object'){throw new Error('object must be of type object');}
|
for(let i=0;i<list.length;i++){let child=list[i];parse(child);}};return{stock:stock,add:function(object){if(typeof object!=="object"){throw new Error("object must be of type object");}
|
||||||
let defaults={'selector':'','controller':function(){},'template':'','repeat':false,'protected':false};for(let prop in defaults){if(!defaults.hasOwnProperty(prop)){continue;}
|
let defaults={selector:"",controller:function(){},template:"",repeat:false,protected:false,};for(let prop in defaults){if(!defaults.hasOwnProperty(prop)){continue;}
|
||||||
if(prop in object){continue;}
|
if(prop in object){continue;}
|
||||||
object[prop]=defaults[prop];}
|
object[prop]=defaults[prop];}
|
||||||
if(!object.selector){throw new Error('View component is missing a selector attribute');}
|
if(!object.selector){throw new Error("View component is missing a selector attribute");}
|
||||||
stock[object.selector]=object;return this;},render:function(element,callback){parse(element,false,callback);element.dispatchEvent(new window.Event('rendered',{bubbles:false}));}}},true,false);window.ls.container.set('router',function(window){let getJsonFromUrl=function(URL){let query;if(URL){let pos=location.search.indexOf('?');if(pos===-1)return[];query=location.search.substr(pos+1);}else{query=location.search.substr(1);}
|
stock[object.selector]=object;return this;},render:function(element,callback){parse(element,false,callback);element.dispatchEvent(new window.Event("rendered",{bubbles:false}));},};},true,false);window.ls.container.set("router",function(window){let getJsonFromUrl=function(URL){let query;if(URL){let pos=location.search.indexOf("?");if(pos===-1)return[];query=location.search.substr(pos+1);}else{query=location.search.substr(1);}
|
||||||
let result={};query.split('&').forEach(function(part){if(!part){return;}
|
let result={};query.split("&").forEach(function(part){if(!part){return;}
|
||||||
part=part.split('+').join(' ');let eq=part.indexOf('=');let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;}
|
part=part.split("+").join(" ");let eq=part.indexOf("=");let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):"";let from=key.indexOf("[");if(from===-1){result[decodeURIComponent(key)]=val;}else{let to=key.indexOf("]");let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];}
|
||||||
else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];}
|
if(!index){result[key].push(val);}else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];}
|
||||||
if(!index){result[key].push(val);}
|
return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=="string"){throw new Error("path must be of type string");}
|
||||||
else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];}
|
if(typeof view!=="object"){throw new Error("view must be of type object");}
|
||||||
return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=='string'){throw new Error('path must be of type string');}
|
states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split("/").length-a.path.split("/").length;if(n!==0){return n;}
|
||||||
if(typeof view!=='object'){throw new Error('view must be of type object');}
|
return b.path.length-a.path.length;});for(let i=0;i<states.length;i++){let value=states[i];value.path=value.path.substring(0,1)!=="/"?location.pathname+value.path:value.path;let match=new RegExp("^"+value.path.replace(/:[^\s/]+/g,"([\\w-]+)")+"$");let found=url.match(match);if(found){previous=current;current=value;return value;}}
|
||||||
states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split('/').length-a.path.split('/').length;if(n!==0){return n;}
|
return null;};let change=function(URL,replace){if(!replace){window.history.pushState({},"",URL);}else{window.history.replaceState({},"",URL);}
|
||||||
return b.path.length-a.path.length;});for(let i=0;i<states.length;i++){let value=states[i];value.path=(value.path.substring(0,1)!=='/')?location.pathname+value.path:value.path;let match=new RegExp("^"+value.path.replace(/:[^\s/]+/g,'([\\w-]+)')+"$");let found=url.match(match);if(found){previous=current;current=value;return value;}}
|
window.dispatchEvent(new PopStateEvent("popstate",{}));return this;};let reload=function(){return change(window.location.href);};return{setParam:setParam,getParam:getParam,getParams:getParams,getURL:getURL,add:add,change:change,reload:reload,match:match,getCurrent:getCurrent,setCurrent:setCurrent,getPrevious:getPrevious,setPrevious:setPrevious,params:params,hash:hash,reset:function(){this.params=getJsonFromUrl(window.location.search);this.hash=window.location.hash;},};},true,true);window.ls.container.set("expression",function(container,filter){let paths=[];return{regex:/(\{{.*?\}})/gi,parse:function(string,def,cast=false){def=def||"";paths=[];return string.replace(this.regex,(match)=>{let reference=match.substring(2,match.length-2).replace("['",".").replace("']","").trim();reference=reference.split("|");let path=container.scope(reference[0]||"");let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);}
|
||||||
return null};let change=function(URL,replace){if(!replace){window.history.pushState({},'',URL);}
|
|
||||||
else{window.history.replaceState({},'',URL);}
|
|
||||||
window.dispatchEvent(new PopStateEvent('popstate',{}));return this;};let reload=function(){return change(window.location.href);};return{setParam:setParam,getParam:getParam,getParams:getParams,getURL:getURL,add:add,change:change,reload:reload,match:match,getCurrent:getCurrent,setCurrent:setCurrent,getPrevious:getPrevious,setPrevious:setPrevious,params:params,hash:hash,reset:function(){this.params=getJsonFromUrl(window.location.search);this.hash=window.location.hash;}};},true,true);window.ls.container.set('expression',function(container,filter){let paths=[];return{regex:/(\{{.*?\}})/gi,parse:function(string,def,cast=false){def=def||'';paths=[];return string.replace(this.regex,match=>{let reference=match.substring(2,match.length-2).replace('[\'','.').replace('\']','').trim();reference=reference.split('|');let path=container.scope((reference[0]||''));let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);}
|
|
||||||
if(reference.length>=2){for(let i=1;i<reference.length;i++){result=filter.apply(reference[i],result);}}
|
if(reference.length>=2){for(let i=1;i<reference.length;i++){result=filter.apply(reference[i],result);}}
|
||||||
if(null===result||undefined===result){result=def;}
|
if(null===result||undefined===result){result=def;}else if(typeof result==="object"){result=JSON.stringify(result,null,4);}else if((typeof result==="object"||typeof result==="string")&&cast){result="'"+result+"'";}
|
||||||
else if(typeof result==='object'){result=JSON.stringify(result,null,4);}
|
return result;}).replace(/\\{/g,"{").replace(/\\}/g,"}");},getPaths:()=>paths,};},true,false);window.ls.container.set("filter",function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set("$value",value,true,false);return container.resolve(filters[name]);};add("uppercase",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
else if(((typeof result==='object')||(typeof result==='string'))&&cast){result='\''+result+'\'';}
|
return $value.toUpperCase();});add("lowercase",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
return result;}).replace(/\\{/g,"{").replace(/\\}/g,"}");},getPaths:()=>paths,}},true,false);window.ls.container.set('filter',function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set('$value',value,true,false);return container.resolve(filters[name]);};add('uppercase',($value)=>{if(typeof $value!=='string'){return $value;}
|
return $value.toLowerCase();});return{add:add,apply:apply};},true,false);window.ls.container.get("filter").add("escape",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
return $value.toUpperCase();});add('lowercase',($value)=>{if(typeof $value!=='string'){return $value;}
|
return $value.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\"/g,""").replace(/\'/g,"'").replace(/\//g,"/");});window.ls=window.ls||{};window.ls.container.set("window",window,true,false).set("document",window.document,true,false).set("element",window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return(error)=>{console.error("ls-error",error.message,error.stack,error.toString());};};window.ls.router=window.ls.container.get("router");window.ls.view=window.ls.container.get("view");window.ls.filter=window.ls.container.get("filter");window.ls.container.get("view").add({selector:"data-ls-router",controller:function(element,window,document,view,router){let firstFromServer=element.getAttribute("data-first-from-server")==="true";let scope={selector:"data-ls-scope",template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute("data-ls-scope-count")||0);element.setAttribute("data-ls-scope-count",count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);}
|
||||||
return $value.toLowerCase();});return{add:add,apply:apply}},true,false);window.ls.container.get('filter').add('escape',value=>{if(typeof value!=='string'){return value;}
|
|
||||||
return value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}
|
|
||||||
catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);}
|
|
||||||
router.reset();if(null===route){return;}
|
router.reset();if(null===route){return;}
|
||||||
scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));}
|
scope.template=undefined!==route.view.template?route.view.template:null;scope.controller=undefined!==route.view.controller?route.view.controller:function(){};document.dispatchEvent(new CustomEvent("state-change"));if(firstFromServer&&null===router.getPrevious()){scope.template="";document.dispatchEvent(new CustomEvent("state-changed"));}else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent("state-changed"));});}else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent("state-changed"));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
||||||
else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}
|
while((el=el.parentNode)){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}}
|
||||||
else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
return null;};element.removeAttribute("data-ls-router");element.setAttribute("data-ls-scope","");element.setAttribute("data-ls-scope-count",1);view.add(scope);document.addEventListener("click",function(event){let target=findParent("a",event.target);if(!target){return false;}
|
||||||
while(el=el.parentNode){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}}
|
|
||||||
return null;};element.removeAttribute('data-ls-router');element.setAttribute('data-ls-scope','');element.setAttribute('data-ls-scope-count',1);view.add(scope);document.addEventListener('click',function(event){let target=findParent('a',event.target);if(!target){return false;}
|
|
||||||
if(!target.href){return false;}
|
if(!target.href){return false;}
|
||||||
if((event.metaKey)){return false;}
|
if(event.metaKey){return false;}
|
||||||
if((target.hasAttribute('target'))&&('_blank'===target.getAttribute('target'))){return false;}
|
if(target.hasAttribute("target")&&"_blank"===target.getAttribute("target")){return false;}
|
||||||
if(target.hostname!==window.location.hostname){return false;}
|
if(target.hostname!==window.location.hostname){return false;}
|
||||||
let route=router.match(target);if(null===route){return false;}
|
let route=router.match(target);if(null===route){return false;}
|
||||||
event.preventDefault();if(window.location===target.href){return false;}
|
event.preventDefault();if(window.location===target.href){return false;}
|
||||||
route.view.state=(undefined===route.view.state)?true:route.view.state;if(true===route.view.state){if(router.getPrevious()&&router.getPrevious().view&&(router.getPrevious().view.scope!==route.view.scope)){window.location.href=target.href;return false;}
|
route.view.state=undefined===route.view.state?true:route.view.state;if(true===route.view.state){if(router.getPrevious()&&router.getPrevious().view&&router.getPrevious().view.scope!==route.view.scope){window.location.href=target.href;return false;}
|
||||||
window.history.pushState({},'Unknown',target.href);}
|
window.history.pushState({},"Unknown",target.href);}
|
||||||
init(route);return true;});window.addEventListener('popstate',function(){init(router.match(window.location));});window.addEventListener('hashchange',function(){init(router.match(window.location));});init(router.match(window.location));}});window.ls.container.get('view').add({selector:'data-ls-attrs',controller:function(element,expression,container){let attrs=element.getAttribute('data-ls-attrs').trim().split(',');let paths=[];let debug=element.getAttribute('data-debug')||false;let check=()=>{container.set('element',element,true,false);if(debug){console.info('debug-ls-attrs attributes:',attrs);}
|
init(route);return true;});window.addEventListener("popstate",function(){init(router.match(window.location));});window.addEventListener("hashchange",function(){init(router.match(window.location));});init(router.match(window.location));},});window.ls.container.get("view").add({selector:"data-ls-attrs",controller:function(element,expression,container){let attrs=element.getAttribute("data-ls-attrs").trim().split(",");let paths=[];let debug=element.getAttribute("data-debug")||false;let check=()=>{container.set("element",element,true,false);if(debug){console.info("debug-ls-attrs attributes:",attrs);}
|
||||||
for(let i=0;i<attrs.length;i++){let attr=attrs[i];let key=expression.parse((attr.substring(0,attr.indexOf('='))||attr));paths=paths.concat(expression.getPaths());let value='';if(attr.indexOf('=')>-1){value=expression.parse(attr.substring(attr.indexOf('=')+1))||'';paths=paths.concat(expression.getPaths());}
|
for(let i=0;i<attrs.length;i++){let attr=attrs[i];let key=expression.parse(attr.substring(0,attr.indexOf("="))||attr);paths=paths.concat(expression.getPaths());let value="";if(attr.indexOf("=")>-1){value=expression.parse(attr.substring(attr.indexOf("=")+1))||"";paths=paths.concat(expression.getPaths());}
|
||||||
if(!key){return null;}
|
if(!key){return null;}
|
||||||
element.setAttribute(key,value);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-bind',controller:function(element,expression,container){let debug=element.getAttribute('data-debug')||false;let echo=function(value,bind=true){if(element.tagName==='INPUT'||element.tagName==='SELECT'||element.tagName==='BUTTON'||element.tagName==='TEXTAREA'){let type=element.getAttribute('type');if('radio'===type){if(value.toString()===element.value){element.setAttribute('checked','checked');}
|
element.setAttribute(key,value);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-bind",controller:function(element,expression,container){let debug=element.getAttribute("data-debug")||false;let echo=function(value,bind=true){if(element.tagName==="INPUT"||element.tagName==="SELECT"||element.tagName==="BUTTON"||element.tagName==="TEXTAREA"){let type=element.getAttribute("type");if("radio"===type){if(value.toString()===element.value){element.setAttribute("checked","checked");}else{element.removeAttribute("checked");}
|
||||||
else{element.removeAttribute('checked');}
|
if(bind){element.addEventListener("change",()=>{for(let i=0;i<paths.length;i++){if(element.checked){value=element.value;}
|
||||||
if(bind){element.addEventListener('change',()=>{for(let i=0;i<paths.length;i++){if(element.checked){value=element.value;}
|
|
||||||
container.path(paths[i],value);}});}
|
container.path(paths[i],value);}});}
|
||||||
return;}
|
return;}
|
||||||
if('checkbox'===type){if(typeof value==='boolean'||value==='true'||value==='false'){if(value===true||value==='true'){element.setAttribute('checked','checked');element.checked=true;}
|
if("checkbox"===type){if(typeof value==="boolean"||value==="true"||value==="false"){if(value===true||value==="true"){element.setAttribute("checked","checked");element.checked=true;}else{element.removeAttribute("checked");element.checked=false;}}else{try{value=JSON.parse(value);element.checked=Array.isArray(value)&&value.indexOf(element.value)>-1;value=element.value;}catch{return null;}}
|
||||||
else{element.removeAttribute('checked');element.checked=false;}}
|
if(bind){element.addEventListener("change",()=>{for(let i=0;i<paths.length;i++){let value=container.path(paths[i]);let index=value.indexOf(element.value);if(element.checked&&index<0){value.push(element.value);}
|
||||||
else{try{value=JSON.parse(value);element.checked=(Array.isArray(value)&&(value.indexOf(element.value)>-1));value=element.value;}
|
|
||||||
catch{return null;}}
|
|
||||||
if(bind){element.addEventListener('change',()=>{for(let i=0;i<paths.length;i++){let value=container.path(paths[i]);let index=value.indexOf(element.value);if(element.checked&&index<0){value.push(element.value);}
|
|
||||||
if(!element.checked&&index>-1){value.splice(index,1);}
|
if(!element.checked&&index>-1){value.splice(index,1);}
|
||||||
container.path(paths[i],value);}});}
|
container.path(paths[i],value);}});}
|
||||||
return;}
|
return;}
|
||||||
if(element.value!==value){element.value=value;element.dispatchEvent(new Event('change'));}
|
if(element.value!==value){element.value=value;element.dispatchEvent(new Event("change"));}
|
||||||
if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}}
|
if(bind){element.addEventListener("input",sync);element.addEventListener("change",sync);}}else{if(element.textContent!=value){element.textContent=value;}}};let sync=(()=>{return()=>{if(debug){console.info("debug-ls-bind","sync-path",paths);console.info("debug-ls-bind","sync-syntax",syntax);console.info("debug-ls-bind","sync-syntax-parsed",parsedSyntax);console.info("debug-ls-bind","sync-value",element.value);}
|
||||||
else{if(element.textContent!=value){element.textContent=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);}
|
for(let i=0;i<paths.length;i++){if("{{"+paths[i]+"}}"!==parsedSyntax){if(debug){console.info("debug-ls-bind","sync-skipped-path",paths[i]);console.info("debug-ls-bind","sync-skipped-syntax",syntax);console.info("debug-ls-bind","sync-skipped-syntax-parsed",parsedSyntax);}
|
||||||
for(let i=0;i<paths.length;i++){if('{{'+paths[i]+'}}'!==parsedSyntax){if(debug){console.info('debug-ls-bind','sync-skipped-path',paths[i]);console.info('debug-ls-bind','sync-skipped-syntax',syntax);console.info('debug-ls-bind','sync-skipped-syntax-parsed',parsedSyntax);}
|
|
||||||
continue;}
|
continue;}
|
||||||
if(debug){console.info('debug-ls-bind','sync-loop-path',paths[i]);console.info('debug-ls-bind','sync-loop-syntax',parsedSyntax);}
|
if(debug){console.info("debug-ls-bind","sync-loop-path",paths[i]);console.info("debug-ls-bind","sync-loop-syntax",parsedSyntax);}
|
||||||
container.path(paths[i],element.value);}}})();let syntax=element.getAttribute('data-ls-bind');let parsedSyntax=container.scope(syntax);let unsync=(!!element.getAttribute('data-unsync'))||false;let result=expression.parse(syntax);let paths=expression.getPaths();echo(result,!unsync);element.addEventListener('looped',function(){echo(expression.parse(parsedSyntax),false);});for(let i=0;i<paths.length;i++){let path=paths[i].split('.');if(debug){console.info('debug-ls-bind','bind-path',path);console.info('debug-ls-bind','bind-syntax',syntax);}
|
container.path(paths[i],element.value);}};})();let syntax=element.getAttribute("data-ls-bind");let parsedSyntax=container.scope(syntax);let unsync=!!element.getAttribute("data-unsync")||false;let result=expression.parse(syntax);let paths=expression.getPaths();echo(result,!unsync);element.addEventListener("looped",function(){echo(expression.parse(parsedSyntax),false);});for(let i=0;i<paths.length;i++){let path=paths[i].split(".");if(debug){console.info("debug-ls-bind","bind-path",path);console.info("debug-ls-bind","bind-syntax",syntax);}
|
||||||
while(path.length){container.bind(element,path.join('.'),()=>{echo(expression.parse(parsedSyntax),false);});path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-if',controller:function(element,expression,container,view){let result='';let syntax=element.getAttribute('data-ls-if')||'';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=()=>{if(debug){console.info('debug-ls-if',expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true));}
|
while(path.length){container.bind(element,path.join("."),()=>{echo(expression.parse(parsedSyntax),false);});path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-if",controller:function(element,expression,container,view){let result="";let syntax=element.getAttribute("data-ls-if")||"";let debug=element.getAttribute("data-debug")||false;let paths=[];let check=()=>{if(debug){console.info("debug-ls-if",expression.parse(syntax.replace(/(\r\n|\n|\r)/gm," "),"undefined",true));}
|
||||||
try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));}
|
try{result=eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm," "),"undefined",true));}catch(error){throw new Error('Failed to evaluate expression "'+
|
||||||
catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);}
|
syntax+' (resulted with: "'+
|
||||||
if(debug){console.info('debug-ls-if result:',result);}
|
result+'")": '+
|
||||||
paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility='hidden';element.style.display='none';}
|
error);}
|
||||||
else{element.style.removeProperty('display');element.style.removeProperty('visibility');}
|
if(debug){console.info("debug-ls-if result:",result);}
|
||||||
if(prv===true&&element.$lsSkip===false){view.render(element)}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-loop',template:false,nested:false,controller:function(element,view,container,window,expression){let expr=expression.parse(element.getAttribute('data-ls-loop'));let as=element.getAttribute('data-ls-as');let key=element.getAttribute('data-ls-key')||'$index';let limit=parseInt(expression.parse(element.getAttribute('data-limit')||'')||-1);let debug=element.getAttribute('data-debug')||false;let echo=function(){let array=container.path(expr);let counter=0;array=(!array)?[]:array;let watch=!!(array&&array.__proxy);while(element.hasChildNodes()){element.removeChild(element.lastChild);element.lastChild=null;}
|
paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility="hidden";element.style.display="none";}else{element.style.removeProperty("display");element.style.removeProperty("visibility");}
|
||||||
if(array instanceof Array&&typeof array!=='object'){throw new Error('Reference value must be array or object. '+(typeof array)+' given');}
|
if(prv===true&&element.$lsSkip===false){view.render(element);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-loop",template:false,nested:false,controller:function(element,view,container,window,expression){let expr=expression.parse(element.getAttribute("data-ls-loop"));let as=element.getAttribute("data-ls-as");let key=element.getAttribute("data-ls-key")||"$index";let limit=parseInt(expression.parse(element.getAttribute("data-limit")||"")||-1);let debug=element.getAttribute("data-debug")||false;let echo=function(){let array=container.path(expr);let counter=0;array=!array?[]:array;let watch=!!(array&&array.__proxy);while(element.hasChildNodes()){element.removeChild(element.lastChild);element.lastChild=null;}
|
||||||
let children=[];element.$lsSkip=true;element.style.visibility=(0===array.length&&element.style.visibility=='')?'hidden':'visible';for(let prop in array){if(counter==limit){break;}
|
if(array instanceof Array&&typeof array!=="object"){throw new Error("Reference value must be array or object. "+typeof array+" given");}
|
||||||
|
let children=[];element.$lsSkip=true;element.style.visibility=0===array.length&&element.style.visibility==""?"hidden":"visible";for(let prop in array){if(counter==limit){break;}
|
||||||
counter++;if(!array.hasOwnProperty(prop)){continue;}
|
counter++;if(!array.hasOwnProperty(prop)){continue;}
|
||||||
children[prop]=template.cloneNode(true);element.appendChild(children[prop]);(index=>{let context=expr+'.'+index;container.addNamespace(as,context);if(debug){console.info('debug-ls-loop','index',index);console.info('debug-ls-loop','context',context);console.info('debug-ls-loop','context-path',container.path(context).name);console.info('debug-ls-loop','namespaces',container.namespaces);}
|
children[prop]=template.cloneNode(true);element.appendChild(children[prop]);((index)=>{let context=expr+"."+index;container.addNamespace(as,context);if(debug){console.info("debug-ls-loop","index",index);console.info("debug-ls-loop","context",context);console.info("debug-ls-loop","context-path",container.path(context).name);console.info("debug-ls-loop","namespaces",container.namespaces);}
|
||||||
container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);}
|
container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);}
|
||||||
element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}
|
element.dispatchEvent(new Event("looped"));};let template=element.children.length===1?element.children[0]:window.document.createElement("li");echo();container.bind(element,expr+".length",echo);let path=(expr+".length").split(".");while(path.length){container.bind(element,path.join("."),echo);path.pop();}},});window.ls.container.get("view").add({selector:"data-ls-template",template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute("data-ls-template")||"";let type=element.getAttribute("data-type")||"url";let debug=element.getAttribute("data-debug")||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML="";if("script"===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent("template-loaded",{bubbles:true,cancelable:false,}));}else{if(debug){console.error('Missing template "'+source+'"');}}
|
||||||
else{if(debug){console.error('Missing template "'+source+'"');}}
|
|
||||||
if(!init){view.render(element);}
|
if(!init){view.render(element);}
|
||||||
return;}
|
return;}
|
||||||
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
|
http.get(source).then((function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent("template-loaded",{bubbles:true,cancelable:false,}));};})(element),function(){throw new Error("Failed loading template");});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
|
||||||
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
|
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
|
||||||
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
|
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
|
||||||
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}
|
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}
|
||||||
|
|
175
public/dist/scripts/app.js
vendored
|
@ -1,143 +1,126 @@
|
||||||
|
|
||||||
window.ls=window.ls||{};window.ls.container=function(){let stock={};let listeners={};let namespaces={};let set=function(name,object,singleton,watch=true){if(typeof name!=='string'){throw new Error('var name must be of type string');}
|
window.ls=window.ls||{};window.ls.container=(function(){let stock={};let listeners={};let namespaces={};let set=function(name,object,singleton,watch=true){if(typeof name!=="string"){throw new Error("var name must be of type string");}
|
||||||
if(typeof singleton!=='boolean'){throw new Error('var singleton "'+singleton+'" of service "'+name+'" must be of type boolean');}
|
if(typeof singleton!=="boolean"){throw new Error('var singleton "'+
|
||||||
|
singleton+'" of service "'+
|
||||||
|
name+'" must be of type boolean');}
|
||||||
stock[name]={name:name,object:object,singleton:singleton,instance:null,watch:watch,};if(!watch){return this;}
|
stock[name]={name:name,object:object,singleton:singleton,instance:null,watch:watch,};if(!watch){return this;}
|
||||||
let binds=listeners[name]||{};for(let key in binds){if(binds.hasOwnProperty(key)){document.dispatchEvent(new CustomEvent(key));}}
|
let binds=listeners[name]||{};for(let key in binds){if(binds.hasOwnProperty(key)){document.dispatchEvent(new CustomEvent(key));}}
|
||||||
return this;};let get=function(name){let service=(undefined!==stock[name])?stock[name]:null;if(null==service){return null;}
|
return this;};let get=function(name){let service=undefined!==stock[name]?stock[name]:null;if(null==service){return null;}
|
||||||
if(service.instance){return service.instance;}
|
if(service.instance){return service.instance;}
|
||||||
let instance=(typeof service.object==='function')?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=='window'&&name!=='document'&&name!=='element'&&typeof instance==='object'&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;}
|
let instance=typeof service.object==="function"?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=="window"&&name!=="document"&&name!=="element"&&typeof instance==="object"&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;}
|
||||||
if(key==="__watch"){return this.watch;}
|
if(key==="__watch"){return this.watch;}
|
||||||
if(key==="__proxy"){return true;}
|
if(key==="__proxy"){return true;}
|
||||||
if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)}
|
if(typeof target[key]==="object"&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+"."+key;return new Proxy(target[key],handler);}else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return(this.name=value);}
|
||||||
else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;}
|
if(key==="__watch"){return(this.watch=value);}
|
||||||
if(key==="__watch"){return this.watch=value;}
|
target[key]=value;let path=receiver.__name+"."+key;document.dispatchEvent(new CustomEvent(path+".changed"));if(skip){return true;}
|
||||||
target[key]=value;let path=receiver.__name+'.'+key;document.dispatchEvent(new CustomEvent(path+'.changed'));if(skip){return true;}
|
skip=true;container.set("$prop",key,true);container.set("$value",value,true);container.resolve(this.watch);container.set("$key",null,true);container.set("$value",null,true);skip=false;return true;},};instance=new Proxy(instance,handler);}
|
||||||
skip=true;container.set('$prop',key,true);container.set('$value',value,true);container.resolve(this.watch);container.set('$key',null,true);container.set('$value',null,true);skip=false;return true;},};instance=new Proxy(instance,handler);}
|
|
||||||
if(service.singleton){service.instance=instance;}
|
if(service.singleton){service.instance=instance;}
|
||||||
return instance;};let resolve=function(target){if(!target){return()=>{};}
|
return instance;};let resolve=function(target){if(!target){return()=>{};}
|
||||||
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;function getParams(func){let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,'');functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==='('){functionAsString=functionAsString.slice(1,-1);}
|
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;function getParams(func){let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,"");functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==="("){functionAsString=functionAsString.slice(1,-1);}
|
||||||
while(match=REGEX_PARAMETERS_VALUES.exec(functionAsString)){params.push(match[1]);}
|
while((match=REGEX_PARAMETERS_VALUES.exec(functionAsString))){params.push(match[1]);}
|
||||||
return params;}
|
return params;}
|
||||||
let args=getParams(target);return target.apply(target,args.map(function(value){return self.get(value.trim());}));};let path=function(path,value,type){type=(type)?type:'assign';path=container.scope(path).split('.');let name=path.shift();let object=container.get(name);let result=null;while(path.length>1){if(!object){return null;}
|
let args=getParams(target);return target.apply(target,args.map(function(value){return self.get(value.trim());}));};let path=function(path,value,type){type=type?type:"assign";path=container.scope(path).split(".");let name=path.shift();let object=container.get(name);let result=null;while(path.length>1){if(!object){return null;}
|
||||||
object=object[path.shift()];}
|
object=object[path.shift()];}
|
||||||
let shift=path.shift();if(value!==null&&value!==undefined&&object&&shift&&(object[shift]!==undefined||object[shift]!==null)){switch(type){case'append':if(!Array.isArray(object[shift])){object[shift]=[];}
|
let shift=path.shift();if(value!==null&&value!==undefined&&object&&shift&&(object[shift]!==undefined||object[shift]!==null)){switch(type){case"append":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].push(value);break;case'prepend':if(!Array.isArray(object[shift])){object[shift]=[];}
|
object[shift].push(value);break;case"prepend":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].unshift(value);break;case'splice':if(!Array.isArray(object[shift])){object[shift]=[];}
|
object[shift].unshift(value);break;case"splice":if(!Array.isArray(object[shift])){object[shift]=[];}
|
||||||
object[shift].splice(value,1);break;default:object[shift]=value;}
|
object[shift].splice(value,1);break;default:object[shift]=value;}
|
||||||
return true;}
|
return true;}
|
||||||
if(!object){return null;}
|
if(!object){return null;}
|
||||||
if(!shift){result=object;}
|
if(!shift){result=object;}else{return object[shift];}
|
||||||
else{return object[shift];}
|
return result;};let bind=function(element,path,callback){let event=container.scope(path)+".changed";let service=event.split(".").slice(0,1).pop();let debug=element.getAttribute("data-debug")||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;}
|
||||||
return result;};let bind=function(element,path,callback){let event=container.scope(path)+'.changed';let service=event.split('.').slice(0,1).pop();let debug=element.getAttribute('data-debug')||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;}
|
let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;};})(Object.assign({},namespaces));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;};let removeNamespace=function(key){delete namespaces[key];return this;};let scope=function(path){for(let[key,value]of Object.entries(namespaces)){path=path.indexOf(".")>-1?path.replace(key+".",value+"."):path.replace(key,value);}
|
||||||
let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;}}(Object.assign({},namespaces)));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;}
|
return path;};let container={set:set,get:get,resolve:resolve,path:path,bind:bind,scope:scope,addNamespace:addNamespace,removeNamespace:removeNamespace,stock:stock,listeners:listeners,namespaces:namespaces,};set("container",container,true,false);return container;})();window.ls.container.set("http",function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){param=encodeURIComponent(param);let a=document.createElement("a");param+=value?"="+encodeURIComponent(value):"";a.href=url;a.search+=(a.search?"&":"")+param;return a.href;};let request=function(method,url,headers,payload,progress){let i;if(-1===["GET","POST","PUT","DELETE","TRACE","HEAD","OPTIONS","CONNECT","PATCH",].indexOf(method)){throw new Error("var method must contain a valid HTTP method name");}
|
||||||
let removeNamespace=function(key){delete namespaces[key];return this;}
|
if(typeof url!=="string"){throw new Error("var url must be of type string");}
|
||||||
let scope=function(path){for(let[key,value]of Object.entries(namespaces)){path=(path.indexOf('.')>-1)?path.replace(key+'.',value+'.'):path.replace(key,value);}
|
if(typeof headers!=="object"){throw new Error("var headers must be of type object");}
|
||||||
return path;}
|
if(typeof url!=="string"){throw new Error("var url must be of type string");}
|
||||||
let container={set:set,get:get,resolve:resolve,path:path,bind:bind,scope:scope,addNamespace:addNamespace,removeNamespace:removeNamespace,stock:stock,listeners:listeners,namespaces:namespaces,};set('container',container,true,false);return container;}();window.ls.container.set('http',function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){param=encodeURIComponent(param);let a=document.createElement('a');param+=(value?"="+encodeURIComponent(value):"");a.href=url;a.search+=(a.search?"&":"")+param;return a.href;};let request=function(method,url,headers,payload,progress){let i;if(-1===['GET','POST','PUT','DELETE','TRACE','HEAD','OPTIONS','CONNECT','PATCH'].indexOf(method)){throw new Error('var method must contain a valid HTTP method name');}
|
|
||||||
if(typeof url!=='string'){throw new Error('var url must be of type string');}
|
|
||||||
if(typeof headers!=='object'){throw new Error('var headers must be of type object');}
|
|
||||||
if(typeof url!=='string'){throw new Error('var url must be of type string');}
|
|
||||||
for(i=0;i<globalParams.length;i++){url=addParam(url,globalParams[i].key,globalParams[i].value);}
|
for(i=0;i<globalParams.length;i++){url=addParam(url,globalParams[i].key,globalParams[i].value);}
|
||||||
return new Promise(function(resolve,reject){let xmlhttp=new XMLHttpRequest();xmlhttp.open(method,url,true);for(i=0;i<globalHeaders.length;i++){xmlhttp.setRequestHeader(globalHeaders[i].key,globalHeaders[i].value);}
|
return new Promise(function(resolve,reject){let xmlhttp=new XMLHttpRequest();xmlhttp.open(method,url,true);for(i=0;i<globalHeaders.length;i++){xmlhttp.setRequestHeader(globalHeaders[i].key,globalHeaders[i].value);}
|
||||||
for(let key in headers){if(headers.hasOwnProperty(key)){xmlhttp.setRequestHeader(key,headers[key]);}}
|
for(let key in headers){if(headers.hasOwnProperty(key)){xmlhttp.setRequestHeader(key,headers[key]);}}
|
||||||
xmlhttp.onload=function(){if(4===xmlhttp.readyState&&200===xmlhttp.status){resolve(xmlhttp.response);}
|
xmlhttp.onload=function(){if(4===xmlhttp.readyState&&200===xmlhttp.status){resolve(xmlhttp.response);}else{document.dispatchEvent(new CustomEvent("http-"+method.toLowerCase()+"-"+xmlhttp.status));reject(new Error(xmlhttp.statusText));}};if(progress){xmlhttp.addEventListener("progress",progress);xmlhttp.upload.addEventListener("progress",progress,false);}
|
||||||
else{document.dispatchEvent(new CustomEvent('http-'+method.toLowerCase()+'-'+xmlhttp.status));reject(new Error(xmlhttp.statusText));}};if(progress){xmlhttp.addEventListener('progress',progress);xmlhttp.upload.addEventListener('progress',progress,false);}
|
xmlhttp.onerror=function(){reject(new Error("Network Error"));};xmlhttp.send(payload);});};return{get:function(url){return request("GET",url,{},"");},post:function(url,headers,payload){return request("POST",url,headers,payload);},put:function(url,headers,payload){return request("PUT",url,headers,payload);},patch:function(url,headers,payload){return request("PATCH",url,headers,payload);},delete:function(url){return request("DELETE",url,{},"");},addGlobalParam:function(key,value){globalParams.push({key:key,value:value});},addGlobalHeader:function(key,value){globalHeaders.push({key:key,value:value});},};},true,false);window.ls.container.set("cookie",function(document){function get(name){let value="; "+document.cookie,parts=value.split("; "+name+"=");if(parts.length===2){return parts.pop().split(";").shift();}
|
||||||
xmlhttp.onerror=function(){reject(new Error("Network Error"));};xmlhttp.send(payload);})};return{'get':function(url){return request('GET',url,{},'')},'post':function(url,headers,payload){return request('POST',url,headers,payload)},'put':function(url,headers,payload){return request('PUT',url,headers,payload)},'patch':function(url,headers,payload){return request('PATCH',url,headers,payload)},'delete':function(url){return request('DELETE',url,{},'')},'addGlobalParam':function(key,value){globalParams.push({key:key,value:value});},'addGlobalHeader':function(key,value){globalHeaders.push({key:key,value:value});}}},true,false);window.ls.container.set('cookie',function(document){function get(name){let value="; "+document.cookie,parts=value.split("; "+name+"=");if(parts.length===2){return parts.pop().split(";").shift();}
|
|
||||||
return null;}
|
return null;}
|
||||||
function set(name,value,days){let date=new Date();date.setTime(date.getTime()+(days*24*60*60*1000));let expires=(0<days)?'expires='+date.toUTCString():'expires=0';document.cookie=name+"="+value+";"+expires+";path=/";return this;}
|
function set(name,value,days){let date=new Date();date.setTime(date.getTime()+days*24*60*60*1000);let expires=0<days?"expires="+date.toUTCString():"expires=0";document.cookie=name+"="+value+";"+expires+";path=/";return this;}
|
||||||
return{'get':get,'set':set}},true,false);window.ls.container.set('view',function(http,container){let stock={};let execute=function(view,node,container){container.set('element',node,true,false);container.resolve(view.controller);if(true!==view.repeat){node.removeAttribute(view.selector);}};let parse=function(node,skip,callback){if(node.tagName==='SCRIPT'){return;}
|
return{get:get,set:set};},true,false);window.ls.container.set("view",function(http,container){let stock={};let execute=function(view,node,container){container.set("element",node,true,false);container.resolve(view.controller);if(true!==view.repeat){node.removeAttribute(view.selector);}};let parse=function(node,skip,callback){if(node.tagName==="SCRIPT"){return;}
|
||||||
if(node.attributes&&skip!==true){let attrs=[];let attrsLen=node.attributes.length;for(let x=0;x<attrsLen;x++){attrs.push(node.attributes[x].nodeName);}
|
if(node.attributes&&skip!==true){let attrs=[];let attrsLen=node.attributes.length;for(let x=0;x<attrsLen;x++){attrs.push(node.attributes[x].nodeName);}
|
||||||
if(1!==node.nodeType){return;}
|
if(1!==node.nodeType){return;}
|
||||||
if(attrs&&attrsLen){for(let x=0;x<attrsLen;x++){if(node.$lsSkip===true){break;}
|
if(attrs&&attrsLen){for(let x=0;x<attrsLen;x++){if(node.$lsSkip===true){break;}
|
||||||
let pointer=(!/Edge/.test(navigator.userAgent))?x:(attrsLen-1)-x;let length=attrsLen;let attr=attrs[pointer];if(!stock[attr]){continue;}
|
let pointer=!/Edge/.test(navigator.userAgent)?x:attrsLen-1-x;let length=attrsLen;let attr=attrs[pointer];if(!stock[attr]){continue;}
|
||||||
let comp=stock[attr];if(typeof comp.template==="function"){comp.template=container.resolve(comp.template);}
|
let comp=stock[attr];if(typeof comp.template==="function"){comp.template=container.resolve(comp.template);}
|
||||||
if(!comp.template){(function(comp,node,container){execute(comp,node,container);})(comp,node,container);if(length!==attrsLen){x--;}
|
if(!comp.template){(function(comp,node,container){execute(comp,node,container);})(comp,node,container);if(length!==attrsLen){x--;}
|
||||||
if(callback){callback();}
|
if(callback){callback();}
|
||||||
continue;}
|
continue;}
|
||||||
node.classList.remove('load-end');node.classList.add('load-start');node.$lsSkip=true;http.get(comp.template).then(function(node,comp){return function(data){node.$lsSkip=false;node.innerHTML=data;node.classList.remove('load-start');node.classList.add('load-end');(function(comp,node,container){execute(comp,node,container);})(comp,node,container);parse(node,true);if(callback){callback();}}}(node,comp),function(error){throw new Error('Failed to load comp template: '+error.message);});}}}
|
node.classList.remove("load-end");node.classList.add("load-start");node.$lsSkip=true;http.get(comp.template).then((function(node,comp){return function(data){node.$lsSkip=false;node.innerHTML=data;node.classList.remove("load-start");node.classList.add("load-end");(function(comp,node,container){execute(comp,node,container);})(comp,node,container);parse(node,true);if(callback){callback();}};})(node,comp),function(error){throw new Error("Failed to load comp template: "+error.message);});}}}
|
||||||
if(true===node.$lsSkip){return;}
|
if(true===node.$lsSkip){return;}
|
||||||
let list=(node)?node.childNodes:[];if(node.$lsSkip===true){list=[];}
|
let list=node?node.childNodes:[];if(node.$lsSkip===true){list=[];}
|
||||||
for(let i=0;i<list.length;i++){let child=list[i];parse(child);}};return{stock:stock,add:function(object){if(typeof object!=='object'){throw new Error('object must be of type object');}
|
for(let i=0;i<list.length;i++){let child=list[i];parse(child);}};return{stock:stock,add:function(object){if(typeof object!=="object"){throw new Error("object must be of type object");}
|
||||||
let defaults={'selector':'','controller':function(){},'template':'','repeat':false,'protected':false};for(let prop in defaults){if(!defaults.hasOwnProperty(prop)){continue;}
|
let defaults={selector:"",controller:function(){},template:"",repeat:false,protected:false,};for(let prop in defaults){if(!defaults.hasOwnProperty(prop)){continue;}
|
||||||
if(prop in object){continue;}
|
if(prop in object){continue;}
|
||||||
object[prop]=defaults[prop];}
|
object[prop]=defaults[prop];}
|
||||||
if(!object.selector){throw new Error('View component is missing a selector attribute');}
|
if(!object.selector){throw new Error("View component is missing a selector attribute");}
|
||||||
stock[object.selector]=object;return this;},render:function(element,callback){parse(element,false,callback);element.dispatchEvent(new window.Event('rendered',{bubbles:false}));}}},true,false);window.ls.container.set('router',function(window){let getJsonFromUrl=function(URL){let query;if(URL){let pos=location.search.indexOf('?');if(pos===-1)return[];query=location.search.substr(pos+1);}else{query=location.search.substr(1);}
|
stock[object.selector]=object;return this;},render:function(element,callback){parse(element,false,callback);element.dispatchEvent(new window.Event("rendered",{bubbles:false}));},};},true,false);window.ls.container.set("router",function(window){let getJsonFromUrl=function(URL){let query;if(URL){let pos=location.search.indexOf("?");if(pos===-1)return[];query=location.search.substr(pos+1);}else{query=location.search.substr(1);}
|
||||||
let result={};query.split('&').forEach(function(part){if(!part){return;}
|
let result={};query.split("&").forEach(function(part){if(!part){return;}
|
||||||
part=part.split('+').join(' ');let eq=part.indexOf('=');let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;}
|
part=part.split("+").join(" ");let eq=part.indexOf("=");let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):"";let from=key.indexOf("[");if(from===-1){result[decodeURIComponent(key)]=val;}else{let to=key.indexOf("]");let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];}
|
||||||
else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];}
|
if(!index){result[key].push(val);}else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];}
|
||||||
if(!index){result[key].push(val);}
|
return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=="string"){throw new Error("path must be of type string");}
|
||||||
else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];}
|
if(typeof view!=="object"){throw new Error("view must be of type object");}
|
||||||
return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=='string'){throw new Error('path must be of type string');}
|
states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split("/").length-a.path.split("/").length;if(n!==0){return n;}
|
||||||
if(typeof view!=='object'){throw new Error('view must be of type object');}
|
return b.path.length-a.path.length;});for(let i=0;i<states.length;i++){let value=states[i];value.path=value.path.substring(0,1)!=="/"?location.pathname+value.path:value.path;let match=new RegExp("^"+value.path.replace(/:[^\s/]+/g,"([\\w-]+)")+"$");let found=url.match(match);if(found){previous=current;current=value;return value;}}
|
||||||
states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split('/').length-a.path.split('/').length;if(n!==0){return n;}
|
return null;};let change=function(URL,replace){if(!replace){window.history.pushState({},"",URL);}else{window.history.replaceState({},"",URL);}
|
||||||
return b.path.length-a.path.length;});for(let i=0;i<states.length;i++){let value=states[i];value.path=(value.path.substring(0,1)!=='/')?location.pathname+value.path:value.path;let match=new RegExp("^"+value.path.replace(/:[^\s/]+/g,'([\\w-]+)')+"$");let found=url.match(match);if(found){previous=current;current=value;return value;}}
|
window.dispatchEvent(new PopStateEvent("popstate",{}));return this;};let reload=function(){return change(window.location.href);};return{setParam:setParam,getParam:getParam,getParams:getParams,getURL:getURL,add:add,change:change,reload:reload,match:match,getCurrent:getCurrent,setCurrent:setCurrent,getPrevious:getPrevious,setPrevious:setPrevious,params:params,hash:hash,reset:function(){this.params=getJsonFromUrl(window.location.search);this.hash=window.location.hash;},};},true,true);window.ls.container.set("expression",function(container,filter){let paths=[];return{regex:/(\{{.*?\}})/gi,parse:function(string,def,cast=false){def=def||"";paths=[];return string.replace(this.regex,(match)=>{let reference=match.substring(2,match.length-2).replace("['",".").replace("']","").trim();reference=reference.split("|");let path=container.scope(reference[0]||"");let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);}
|
||||||
return null};let change=function(URL,replace){if(!replace){window.history.pushState({},'',URL);}
|
|
||||||
else{window.history.replaceState({},'',URL);}
|
|
||||||
window.dispatchEvent(new PopStateEvent('popstate',{}));return this;};let reload=function(){return change(window.location.href);};return{setParam:setParam,getParam:getParam,getParams:getParams,getURL:getURL,add:add,change:change,reload:reload,match:match,getCurrent:getCurrent,setCurrent:setCurrent,getPrevious:getPrevious,setPrevious:setPrevious,params:params,hash:hash,reset:function(){this.params=getJsonFromUrl(window.location.search);this.hash=window.location.hash;}};},true,true);window.ls.container.set('expression',function(container,filter){let paths=[];return{regex:/(\{{.*?\}})/gi,parse:function(string,def,cast=false){def=def||'';paths=[];return string.replace(this.regex,match=>{let reference=match.substring(2,match.length-2).replace('[\'','.').replace('\']','').trim();reference=reference.split('|');let path=container.scope((reference[0]||''));let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);}
|
|
||||||
if(reference.length>=2){for(let i=1;i<reference.length;i++){result=filter.apply(reference[i],result);}}
|
if(reference.length>=2){for(let i=1;i<reference.length;i++){result=filter.apply(reference[i],result);}}
|
||||||
if(null===result||undefined===result){result=def;}
|
if(null===result||undefined===result){result=def;}else if(typeof result==="object"){result=JSON.stringify(result,null,4);}else if((typeof result==="object"||typeof result==="string")&&cast){result="'"+result+"'";}
|
||||||
else if(typeof result==='object'){result=JSON.stringify(result,null,4);}
|
return result;}).replace(/\\{/g,"{").replace(/\\}/g,"}");},getPaths:()=>paths,};},true,false);window.ls.container.set("filter",function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set("$value",value,true,false);return container.resolve(filters[name]);};add("uppercase",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
else if(((typeof result==='object')||(typeof result==='string'))&&cast){result='\''+result+'\'';}
|
return $value.toUpperCase();});add("lowercase",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
return result;}).replace(/\\{/g,"{").replace(/\\}/g,"}");},getPaths:()=>paths,}},true,false);window.ls.container.set('filter',function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set('$value',value,true,false);return container.resolve(filters[name]);};add('uppercase',($value)=>{if(typeof $value!=='string'){return $value;}
|
return $value.toLowerCase();});return{add:add,apply:apply};},true,false);window.ls.container.get("filter").add("escape",($value)=>{if(typeof $value!=="string"){return $value;}
|
||||||
return $value.toUpperCase();});add('lowercase',($value)=>{if(typeof $value!=='string'){return $value;}
|
return $value.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\"/g,""").replace(/\'/g,"'").replace(/\//g,"/");});window.ls=window.ls||{};window.ls.container.set("window",window,true,false).set("document",window.document,true,false).set("element",window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return(error)=>{console.error("ls-error",error.message,error.stack,error.toString());};};window.ls.router=window.ls.container.get("router");window.ls.view=window.ls.container.get("view");window.ls.filter=window.ls.container.get("filter");window.ls.container.get("view").add({selector:"data-ls-router",controller:function(element,window,document,view,router){let firstFromServer=element.getAttribute("data-first-from-server")==="true";let scope={selector:"data-ls-scope",template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute("data-ls-scope-count")||0);element.setAttribute("data-ls-scope-count",count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);}
|
||||||
return $value.toLowerCase();});return{add:add,apply:apply}},true,false);window.ls.container.get('filter').add('escape',value=>{if(typeof value!=='string'){return value;}
|
|
||||||
return value.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}
|
|
||||||
catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);}
|
|
||||||
router.reset();if(null===route){return;}
|
router.reset();if(null===route){return;}
|
||||||
scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));}
|
scope.template=undefined!==route.view.template?route.view.template:null;scope.controller=undefined!==route.view.controller?route.view.controller:function(){};document.dispatchEvent(new CustomEvent("state-change"));if(firstFromServer&&null===router.getPrevious()){scope.template="";document.dispatchEvent(new CustomEvent("state-changed"));}else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent("state-changed"));});}else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent("state-changed"));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
||||||
else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}
|
while((el=el.parentNode)){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}}
|
||||||
else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
return null;};element.removeAttribute("data-ls-router");element.setAttribute("data-ls-scope","");element.setAttribute("data-ls-scope-count",1);view.add(scope);document.addEventListener("click",function(event){let target=findParent("a",event.target);if(!target){return false;}
|
||||||
while(el=el.parentNode){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}}
|
|
||||||
return null;};element.removeAttribute('data-ls-router');element.setAttribute('data-ls-scope','');element.setAttribute('data-ls-scope-count',1);view.add(scope);document.addEventListener('click',function(event){let target=findParent('a',event.target);if(!target){return false;}
|
|
||||||
if(!target.href){return false;}
|
if(!target.href){return false;}
|
||||||
if((event.metaKey)){return false;}
|
if(event.metaKey){return false;}
|
||||||
if((target.hasAttribute('target'))&&('_blank'===target.getAttribute('target'))){return false;}
|
if(target.hasAttribute("target")&&"_blank"===target.getAttribute("target")){return false;}
|
||||||
if(target.hostname!==window.location.hostname){return false;}
|
if(target.hostname!==window.location.hostname){return false;}
|
||||||
let route=router.match(target);if(null===route){return false;}
|
let route=router.match(target);if(null===route){return false;}
|
||||||
event.preventDefault();if(window.location===target.href){return false;}
|
event.preventDefault();if(window.location===target.href){return false;}
|
||||||
route.view.state=(undefined===route.view.state)?true:route.view.state;if(true===route.view.state){if(router.getPrevious()&&router.getPrevious().view&&(router.getPrevious().view.scope!==route.view.scope)){window.location.href=target.href;return false;}
|
route.view.state=undefined===route.view.state?true:route.view.state;if(true===route.view.state){if(router.getPrevious()&&router.getPrevious().view&&router.getPrevious().view.scope!==route.view.scope){window.location.href=target.href;return false;}
|
||||||
window.history.pushState({},'Unknown',target.href);}
|
window.history.pushState({},"Unknown",target.href);}
|
||||||
init(route);return true;});window.addEventListener('popstate',function(){init(router.match(window.location));});window.addEventListener('hashchange',function(){init(router.match(window.location));});init(router.match(window.location));}});window.ls.container.get('view').add({selector:'data-ls-attrs',controller:function(element,expression,container){let attrs=element.getAttribute('data-ls-attrs').trim().split(',');let paths=[];let debug=element.getAttribute('data-debug')||false;let check=()=>{container.set('element',element,true,false);if(debug){console.info('debug-ls-attrs attributes:',attrs);}
|
init(route);return true;});window.addEventListener("popstate",function(){init(router.match(window.location));});window.addEventListener("hashchange",function(){init(router.match(window.location));});init(router.match(window.location));},});window.ls.container.get("view").add({selector:"data-ls-attrs",controller:function(element,expression,container){let attrs=element.getAttribute("data-ls-attrs").trim().split(",");let paths=[];let debug=element.getAttribute("data-debug")||false;let check=()=>{container.set("element",element,true,false);if(debug){console.info("debug-ls-attrs attributes:",attrs);}
|
||||||
for(let i=0;i<attrs.length;i++){let attr=attrs[i];let key=expression.parse((attr.substring(0,attr.indexOf('='))||attr));paths=paths.concat(expression.getPaths());let value='';if(attr.indexOf('=')>-1){value=expression.parse(attr.substring(attr.indexOf('=')+1))||'';paths=paths.concat(expression.getPaths());}
|
for(let i=0;i<attrs.length;i++){let attr=attrs[i];let key=expression.parse(attr.substring(0,attr.indexOf("="))||attr);paths=paths.concat(expression.getPaths());let value="";if(attr.indexOf("=")>-1){value=expression.parse(attr.substring(attr.indexOf("=")+1))||"";paths=paths.concat(expression.getPaths());}
|
||||||
if(!key){return null;}
|
if(!key){return null;}
|
||||||
element.setAttribute(key,value);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-bind',controller:function(element,expression,container){let debug=element.getAttribute('data-debug')||false;let echo=function(value,bind=true){if(element.tagName==='INPUT'||element.tagName==='SELECT'||element.tagName==='BUTTON'||element.tagName==='TEXTAREA'){let type=element.getAttribute('type');if('radio'===type){if(value.toString()===element.value){element.setAttribute('checked','checked');}
|
element.setAttribute(key,value);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-bind",controller:function(element,expression,container){let debug=element.getAttribute("data-debug")||false;let echo=function(value,bind=true){if(element.tagName==="INPUT"||element.tagName==="SELECT"||element.tagName==="BUTTON"||element.tagName==="TEXTAREA"){let type=element.getAttribute("type");if("radio"===type){if(value.toString()===element.value){element.setAttribute("checked","checked");}else{element.removeAttribute("checked");}
|
||||||
else{element.removeAttribute('checked');}
|
if(bind){element.addEventListener("change",()=>{for(let i=0;i<paths.length;i++){if(element.checked){value=element.value;}
|
||||||
if(bind){element.addEventListener('change',()=>{for(let i=0;i<paths.length;i++){if(element.checked){value=element.value;}
|
|
||||||
container.path(paths[i],value);}});}
|
container.path(paths[i],value);}});}
|
||||||
return;}
|
return;}
|
||||||
if('checkbox'===type){if(typeof value==='boolean'||value==='true'||value==='false'){if(value===true||value==='true'){element.setAttribute('checked','checked');element.checked=true;}
|
if("checkbox"===type){if(typeof value==="boolean"||value==="true"||value==="false"){if(value===true||value==="true"){element.setAttribute("checked","checked");element.checked=true;}else{element.removeAttribute("checked");element.checked=false;}}else{try{value=JSON.parse(value);element.checked=Array.isArray(value)&&value.indexOf(element.value)>-1;value=element.value;}catch{return null;}}
|
||||||
else{element.removeAttribute('checked');element.checked=false;}}
|
if(bind){element.addEventListener("change",()=>{for(let i=0;i<paths.length;i++){let value=container.path(paths[i]);let index=value.indexOf(element.value);if(element.checked&&index<0){value.push(element.value);}
|
||||||
else{try{value=JSON.parse(value);element.checked=(Array.isArray(value)&&(value.indexOf(element.value)>-1));value=element.value;}
|
|
||||||
catch{return null;}}
|
|
||||||
if(bind){element.addEventListener('change',()=>{for(let i=0;i<paths.length;i++){let value=container.path(paths[i]);let index=value.indexOf(element.value);if(element.checked&&index<0){value.push(element.value);}
|
|
||||||
if(!element.checked&&index>-1){value.splice(index,1);}
|
if(!element.checked&&index>-1){value.splice(index,1);}
|
||||||
container.path(paths[i],value);}});}
|
container.path(paths[i],value);}});}
|
||||||
return;}
|
return;}
|
||||||
if(element.value!==value){element.value=value;element.dispatchEvent(new Event('change'));}
|
if(element.value!==value){element.value=value;element.dispatchEvent(new Event("change"));}
|
||||||
if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}}
|
if(bind){element.addEventListener("input",sync);element.addEventListener("change",sync);}}else{if(element.textContent!=value){element.textContent=value;}}};let sync=(()=>{return()=>{if(debug){console.info("debug-ls-bind","sync-path",paths);console.info("debug-ls-bind","sync-syntax",syntax);console.info("debug-ls-bind","sync-syntax-parsed",parsedSyntax);console.info("debug-ls-bind","sync-value",element.value);}
|
||||||
else{if(element.textContent!=value){element.textContent=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);}
|
for(let i=0;i<paths.length;i++){if("{{"+paths[i]+"}}"!==parsedSyntax){if(debug){console.info("debug-ls-bind","sync-skipped-path",paths[i]);console.info("debug-ls-bind","sync-skipped-syntax",syntax);console.info("debug-ls-bind","sync-skipped-syntax-parsed",parsedSyntax);}
|
||||||
for(let i=0;i<paths.length;i++){if('{{'+paths[i]+'}}'!==parsedSyntax){if(debug){console.info('debug-ls-bind','sync-skipped-path',paths[i]);console.info('debug-ls-bind','sync-skipped-syntax',syntax);console.info('debug-ls-bind','sync-skipped-syntax-parsed',parsedSyntax);}
|
|
||||||
continue;}
|
continue;}
|
||||||
if(debug){console.info('debug-ls-bind','sync-loop-path',paths[i]);console.info('debug-ls-bind','sync-loop-syntax',parsedSyntax);}
|
if(debug){console.info("debug-ls-bind","sync-loop-path",paths[i]);console.info("debug-ls-bind","sync-loop-syntax",parsedSyntax);}
|
||||||
container.path(paths[i],element.value);}}})();let syntax=element.getAttribute('data-ls-bind');let parsedSyntax=container.scope(syntax);let unsync=(!!element.getAttribute('data-unsync'))||false;let result=expression.parse(syntax);let paths=expression.getPaths();echo(result,!unsync);element.addEventListener('looped',function(){echo(expression.parse(parsedSyntax),false);});for(let i=0;i<paths.length;i++){let path=paths[i].split('.');if(debug){console.info('debug-ls-bind','bind-path',path);console.info('debug-ls-bind','bind-syntax',syntax);}
|
container.path(paths[i],element.value);}};})();let syntax=element.getAttribute("data-ls-bind");let parsedSyntax=container.scope(syntax);let unsync=!!element.getAttribute("data-unsync")||false;let result=expression.parse(syntax);let paths=expression.getPaths();echo(result,!unsync);element.addEventListener("looped",function(){echo(expression.parse(parsedSyntax),false);});for(let i=0;i<paths.length;i++){let path=paths[i].split(".");if(debug){console.info("debug-ls-bind","bind-path",path);console.info("debug-ls-bind","bind-syntax",syntax);}
|
||||||
while(path.length){container.bind(element,path.join('.'),()=>{echo(expression.parse(parsedSyntax),false);});path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-if',controller:function(element,expression,container,view){let result='';let syntax=element.getAttribute('data-ls-if')||'';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=()=>{if(debug){console.info('debug-ls-if',expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true));}
|
while(path.length){container.bind(element,path.join("."),()=>{echo(expression.parse(parsedSyntax),false);});path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-if",controller:function(element,expression,container,view){let result="";let syntax=element.getAttribute("data-ls-if")||"";let debug=element.getAttribute("data-debug")||false;let paths=[];let check=()=>{if(debug){console.info("debug-ls-if",expression.parse(syntax.replace(/(\r\n|\n|\r)/gm," "),"undefined",true));}
|
||||||
try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));}
|
try{result=eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm," "),"undefined",true));}catch(error){throw new Error('Failed to evaluate expression "'+
|
||||||
catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);}
|
syntax+' (resulted with: "'+
|
||||||
if(debug){console.info('debug-ls-if result:',result);}
|
result+'")": '+
|
||||||
paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility='hidden';element.style.display='none';}
|
error);}
|
||||||
else{element.style.removeProperty('display');element.style.removeProperty('visibility');}
|
if(debug){console.info("debug-ls-if result:",result);}
|
||||||
if(prv===true&&element.$lsSkip===false){view.render(element)}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-loop',template:false,nested:false,controller:function(element,view,container,window,expression){let expr=expression.parse(element.getAttribute('data-ls-loop'));let as=element.getAttribute('data-ls-as');let key=element.getAttribute('data-ls-key')||'$index';let limit=parseInt(expression.parse(element.getAttribute('data-limit')||'')||-1);let debug=element.getAttribute('data-debug')||false;let echo=function(){let array=container.path(expr);let counter=0;array=(!array)?[]:array;let watch=!!(array&&array.__proxy);while(element.hasChildNodes()){element.removeChild(element.lastChild);element.lastChild=null;}
|
paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility="hidden";element.style.display="none";}else{element.style.removeProperty("display");element.style.removeProperty("visibility");}
|
||||||
if(array instanceof Array&&typeof array!=='object'){throw new Error('Reference value must be array or object. '+(typeof array)+' given');}
|
if(prv===true&&element.$lsSkip===false){view.render(element);}};check();for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.container.get("view").add({selector:"data-ls-loop",template:false,nested:false,controller:function(element,view,container,window,expression){let expr=expression.parse(element.getAttribute("data-ls-loop"));let as=element.getAttribute("data-ls-as");let key=element.getAttribute("data-ls-key")||"$index";let limit=parseInt(expression.parse(element.getAttribute("data-limit")||"")||-1);let debug=element.getAttribute("data-debug")||false;let echo=function(){let array=container.path(expr);let counter=0;array=!array?[]:array;let watch=!!(array&&array.__proxy);while(element.hasChildNodes()){element.removeChild(element.lastChild);element.lastChild=null;}
|
||||||
let children=[];element.$lsSkip=true;element.style.visibility=(0===array.length&&element.style.visibility=='')?'hidden':'visible';for(let prop in array){if(counter==limit){break;}
|
if(array instanceof Array&&typeof array!=="object"){throw new Error("Reference value must be array or object. "+typeof array+" given");}
|
||||||
|
let children=[];element.$lsSkip=true;element.style.visibility=0===array.length&&element.style.visibility==""?"hidden":"visible";for(let prop in array){if(counter==limit){break;}
|
||||||
counter++;if(!array.hasOwnProperty(prop)){continue;}
|
counter++;if(!array.hasOwnProperty(prop)){continue;}
|
||||||
children[prop]=template.cloneNode(true);element.appendChild(children[prop]);(index=>{let context=expr+'.'+index;container.addNamespace(as,context);if(debug){console.info('debug-ls-loop','index',index);console.info('debug-ls-loop','context',context);console.info('debug-ls-loop','context-path',container.path(context).name);console.info('debug-ls-loop','namespaces',container.namespaces);}
|
children[prop]=template.cloneNode(true);element.appendChild(children[prop]);((index)=>{let context=expr+"."+index;container.addNamespace(as,context);if(debug){console.info("debug-ls-loop","index",index);console.info("debug-ls-loop","context",context);console.info("debug-ls-loop","context-path",container.path(context).name);console.info("debug-ls-loop","namespaces",container.namespaces);}
|
||||||
container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);}
|
container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);}
|
||||||
element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}
|
element.dispatchEvent(new Event("looped"));};let template=element.children.length===1?element.children[0]:window.document.createElement("li");echo();container.bind(element,expr+".length",echo);let path=(expr+".length").split(".");while(path.length){container.bind(element,path.join("."),echo);path.pop();}},});window.ls.container.get("view").add({selector:"data-ls-template",template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute("data-ls-template")||"";let type=element.getAttribute("data-type")||"url";let debug=element.getAttribute("data-debug")||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML="";if("script"===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent("template-loaded",{bubbles:true,cancelable:false,}));}else{if(debug){console.error('Missing template "'+source+'"');}}
|
||||||
else{if(debug){console.error('Missing template "'+source+'"');}}
|
|
||||||
if(!init){view.render(element);}
|
if(!init){view.render(element);}
|
||||||
return;}
|
return;}
|
||||||
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
|
http.get(source).then((function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent("template-loaded",{bubbles:true,cancelable:false,}));};})(element),function(){throw new Error("Failed loading template");});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split(".");while(path.length){container.bind(element,path.join("."),check);path.pop();}}},});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
|
||||||
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
|
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
|
||||||
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
|
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
|
||||||
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}
|
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}
|
||||||
|
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 14 KiB |
|
@ -168,5 +168,55 @@ trait TeamsBaseServer
|
||||||
|
|
||||||
$this->assertEquals(401, $response['headers']['status-code']);
|
$this->assertEquals(401, $response['headers']['status-code']);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testUpdateMembershipRoles
|
||||||
|
*/
|
||||||
|
public function testDeleteUserUpdatesTeamMembershipCount($data) {
|
||||||
|
$teamUid = $data['teamUid'] ?? '';
|
||||||
|
$userUid = $data['userUid'] ?? '';
|
||||||
|
|
||||||
|
/** Get Team Count */
|
||||||
|
$response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()));
|
||||||
|
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
|
$this->assertEquals('Arsenal', $response['body']['name']);
|
||||||
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
$this->assertIsInt($response['body']['sum']);
|
||||||
|
$this->assertIsInt($response['body']['dateCreated']);
|
||||||
|
|
||||||
|
|
||||||
|
/** Delete User */
|
||||||
|
$user = $this->client->call(Client::METHOD_DELETE, '/users/' . $userUid, array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()));
|
||||||
|
|
||||||
|
$this->assertEquals($user['headers']['status-code'], 204);
|
||||||
|
|
||||||
|
/** Wait for deletes worker to delete membership and update team membership count */
|
||||||
|
sleep(5);
|
||||||
|
|
||||||
|
/** Get Team Count */
|
||||||
|
$response = $this->client->call(Client::METHOD_GET, '/teams/'.$teamUid, array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()));
|
||||||
|
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
|
$this->assertEquals('Arsenal', $response['body']['name']);
|
||||||
|
$this->assertEquals(0, $response['body']['sum']);
|
||||||
|
$this->assertIsInt($response['body']['sum']);
|
||||||
|
$this->assertIsInt($response['body']['dateCreated']);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -346,7 +346,7 @@ services:
|
||||||
- appwrite-influxdb:/var/lib/influxdb:rw
|
- appwrite-influxdb:/var/lib/influxdb:rw
|
||||||
|
|
||||||
telegraf:
|
telegraf:
|
||||||
image: appwrite/telegraf:1.0.0
|
image: appwrite/telegraf:1.1.0
|
||||||
container_name: appwrite-telegraf
|
container_name: appwrite-telegraf
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
|
|