Merge branch 'master' of github.com:appwrite/appwrite into team-features
This commit is contained in:
commit
f3c8e57e70
0
.gitattributes
vendored
Normal file
0
.gitattributes
vendored
Normal file
|
@ -2,8 +2,10 @@
|
|||
|
||||
## Features
|
||||
|
||||
- Added a new route in Locale API to fetch a list of languages
|
||||
- New route in Locale API to fetch a list of languages
|
||||
- Added option to force HTTPS connection to the Appwrite server (_APP_OPTIONS_FORCE_HTTPS)
|
||||
- Added Google Fonts to Appwrite for offline availability
|
||||
- Added a new route in the Avatars API to get user initials avatar
|
||||
- Added option to delete team from the console
|
||||
- Added option to view team members from the console
|
||||
- Added option to join a user to any team from the console
|
||||
|
@ -12,6 +14,8 @@
|
|||
|
||||
- Fixed output of /v1/health/queue/certificates returning wrong data
|
||||
- Fixed bug where team members count was wrong in some cases
|
||||
- Fixed network calculation for uploaded files
|
||||
- Fixed a UI bug preventing float values in numeric fields
|
||||
|
||||
## Security
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ ENV TZ=Asia/Tel_Aviv \
|
|||
_APP_HOME=https://appwrite.io \
|
||||
_APP_EDITION=community \
|
||||
_APP_OPTIONS_ABUSE=enabled \
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled \
|
||||
_APP_OPENSSL_KEY_V1=your-secret-key \
|
||||
_APP_STORAGE_LIMIT=104857600 \
|
||||
_APP_STORAGE_ANTIVIRUS=enabled \
|
||||
|
|
12
app/app.php
12
app/app.php
|
@ -82,6 +82,14 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
|
|||
* As recommended at:
|
||||
* @see https://www.owasp.org/index.php/List_of_useful_HTTP_headers
|
||||
*/
|
||||
if ($request->getServer('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||
if(Config::getParam('protocol') !== 'https') {
|
||||
return $response->redirect('https://' . Config::getParam('domain').$request->getServer('REQUEST_URI'));
|
||||
}
|
||||
|
||||
$response->addHeader('Strict-Transport-Security', 'max-age='.(60 * 60 * 24 * 126)); // 126 days
|
||||
}
|
||||
|
||||
$response
|
||||
->addHeader('Server', 'Appwrite')
|
||||
->addHeader('X-XSS-Protection', '1; mode=block; report=/v1/xss?url='.urlencode($request->getServer('REQUEST_URI')))
|
||||
|
@ -236,12 +244,12 @@ $utopia->shutdown(function () use ($response, $request, $webhook, $audit, $usage
|
|||
}
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
|
||||
if($project->getId()
|
||||
&& $mode !== APP_MODE_ADMIN
|
||||
&& !empty($route->getLabel('sdk.namespace', null))) { // Don't calculate console usage and admin mode
|
||||
$usage
|
||||
->setParam('request', $request->getSize())
|
||||
->setParam('request', $request->getSize() + $usage->getParam('storage'))
|
||||
->setParam('response', $response->getSize())
|
||||
->trigger()
|
||||
;
|
||||
|
|
|
@ -16,6 +16,7 @@ use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
|
|||
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
use BaconQrCode\Writer;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Validator\HexColor;
|
||||
|
||||
include_once __DIR__ . '/../shared/api.php';
|
||||
|
||||
|
@ -385,7 +386,83 @@ $utopia->get('/v1/avatars/qr')
|
|||
$response
|
||||
->addHeader('Expires', date('D, d M Y H:i:s', time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
|
||||
->setContentType('image/png')
|
||||
->send('', $writer->writeString($text))
|
||||
->send($writer->writeString($text))
|
||||
;
|
||||
}
|
||||
);
|
||||
|
||||
$utopia->get('/v1/avatars/initials')
|
||||
->desc('Get User Initials')
|
||||
->param('name', '', function () { return new Text(512); }, 'Full Name. When empty, current user name or email will be used.', true)
|
||||
->param('width', 500, function () { return new Range(0, 2000); }, 'Image width. Pass an integer between 0 to 2000. Defaults to 100.', true)
|
||||
->param('height', 500, function () { return new Range(0, 2000); }, 'Image height. Pass an integer between 0 to 2000. Defaults to 100.', true)
|
||||
->param('color', '', function () { return new HexColor(); }, 'Changes text color. By default a random color will be picked and stay will persistent to the given name.', true)
|
||||
->param('background', '', function () { return new HexColor(); }, 'Changes background color. By default a random color will be picked and stay will persistent to the given name.', true)
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
->label('sdk.method', 'getInitials')
|
||||
->label('sdk.methodType', 'location')
|
||||
->label('sdk.description', '/docs/references/avatars/get-initials.md')
|
||||
->action(
|
||||
function ($name, $width, $height, $color, $background) use ($response, $user) {
|
||||
$themes = [
|
||||
['color' => '#27005e', 'background' => '#e1d2f6'], // VIOLET
|
||||
['color' => '#5e2700', 'background' => '#f3d9c6'], // ORANGE
|
||||
['color' => '#006128', 'background' => '#c9f3c6'], // GREEN
|
||||
['color' => '#580061', 'background' => '#f2d1f5'], // FUSCHIA
|
||||
['color' => '#00365d', 'background' => '#c6e1f3'], // BLUE
|
||||
['color' => '#00075c', 'background' => '#d2d5f6'], // INDIGO
|
||||
['color' => '#610038', 'background' => '#f5d1e6'], // PINK
|
||||
['color' => '#386100', 'background' => '#dcf1bd'], // LIME
|
||||
['color' => '#615800', 'background' => '#f1ecba'], // YELLOW
|
||||
['color' => '#610008', 'background' => '#f6d2d5'] // RED
|
||||
];
|
||||
|
||||
$rand = rand(0, count($themes)-1);
|
||||
|
||||
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
|
||||
$words = explode(' ', strtoupper($name));
|
||||
$initials = null;
|
||||
$code = 0;
|
||||
|
||||
foreach ($words as $key => $w) {
|
||||
$initials .= (isset($w[0])) ? $w[0] : '';
|
||||
$code += (isset($w[0])) ? ord($w[0]) : 0;
|
||||
|
||||
if($key == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$length = count($words);
|
||||
$rand = substr($code,-1);
|
||||
$background = (!empty($background)) ? '#'.$background : $themes[$rand]['background'];
|
||||
$color = (!empty($color)) ? '#'.$color : $themes[$rand]['color'];
|
||||
|
||||
$image = new \Imagick();
|
||||
$draw = new \ImagickDraw();
|
||||
$fontSize = min($width, $height) / 2;
|
||||
|
||||
$draw->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-600.ttf");
|
||||
$image->setFont(__DIR__."/../../../public/fonts/poppins-v9-latin-600.ttf");
|
||||
|
||||
$draw->setFillColor(new \ImagickPixel($color));
|
||||
$draw->setFontSize($fontSize);
|
||||
|
||||
$draw->setTextAlignment(\Imagick::ALIGN_CENTER);
|
||||
$draw->annotation($width / 1.97, ($height / 2) + ($fontSize / 3), $initials);
|
||||
|
||||
$image->newImage($width, $height, $background);
|
||||
$image->setImageFormat("png");
|
||||
$image->drawImage($draw);
|
||||
|
||||
//$image->setImageCompressionQuality(9 - round(($quality / 100) * 9));
|
||||
|
||||
$response
|
||||
->addHeader('Expires', date('D, d M Y H:i:s', time() + (60 * 60 * 24 * 45)).' GMT') // 45 days cache
|
||||
->setContentType('image/png')
|
||||
->send($image->getImageBlob())
|
||||
;
|
||||
}
|
||||
);
|
|
@ -424,6 +424,10 @@ $utopia->delete('/v1/projects/:projectId')
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$consoleDB->deleteDocument($project->getAttribute('teamId', null))) {
|
||||
throw new Exception('Failed to remove project team from DB', 500);
|
||||
}
|
||||
|
||||
if (!$consoleDB->deleteDocument($projectId)) {
|
||||
throw new Exception('Failed to remove project from DB', 500);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Your Account</span>
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
<br />
|
||||
|
||||
<a href="https://en.gravatar.com/gravatars/new/" rel="noopener" class="button margin-bottom-small" target="_blank"><i class="icon-upload"></i> Upload</a>
|
||||
<a href="https://en.gravatar.com/gravatars/new/" rel="noopener" class="button margin-bottom-small link-animation-disabled" target="_blank"><i class="icon-upload"></i> Upload</a>
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -317,4 +317,4 @@
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<header class="clear">
|
||||
<a href="/console" class="logo pull-start">
|
||||
<a href="/console" class="logo pull-start link-animation-disabled">
|
||||
<img src="/images/appwrite.svg" alt="Appwrite Light Logo" class="force-light" />
|
||||
<img src="/images/appwrite-footer-dark.svg" alt="Appwrite Dark Logo" class="force-dark" />
|
||||
</a>
|
||||
|
@ -34,10 +34,10 @@
|
|||
data-failure-param-trigger-events="account.deleteSession">
|
||||
|
||||
<div class="console-back">
|
||||
<a href="/console">Back to Console <i class="icon-right-open"></i></a>
|
||||
<a href="/console" class="link-return-animation--end">Back to Console <i class="icon-right-open"></i></a>
|
||||
</div>
|
||||
|
||||
<div class="account link pull-end clear">
|
||||
<div class="account link link-animation-disabled pull-end clear">
|
||||
<img src="" data-ls-attrs="src={{account|gravatar}}" alt="User Avatar" class="avatar margin-start pull-end" />
|
||||
<span class="name pull-end desktops-only" data-ls-bind="{{account.name}}"></span>
|
||||
</div>
|
||||
|
@ -45,10 +45,10 @@
|
|||
<div class="console-index drop-list bottom end" data-ls-ui-open="" data-button-text="" data-button-icon="" data-button-selector="[data-toggler]" data-button-class="account-button" data-blur="1" tabindex="1">
|
||||
<ul class="margin-top-large arrow-end">
|
||||
<li>
|
||||
<a href="/console/account"><i class="icon-user"></i> Your Account</a>
|
||||
<a href="/console/account" class="link-animation-disabled"><i class="icon-user"></i> Your Account</a>
|
||||
</li>
|
||||
<li>
|
||||
<span class="link"><i class="icon-sun-inv force-dark pull-start"></i><i class="icon-moon-inv force-light pull-start"></i> Change Theme
|
||||
<span class="link link-animation-disabled"><i class="icon-sun-inv force-dark pull-start"></i><i class="icon-moon-inv force-light pull-start"></i> Change Theme
|
||||
<div class="pull-end switch-theme">
|
||||
<button data-general-theme
|
||||
data-analytics-event="click"
|
||||
|
@ -66,7 +66,7 @@
|
|||
</div>
|
||||
|
||||
<nav class="project-only" data-ls-ui-open="" data-button-class="round icon-btn phones-only tablets-only" data-button-icon="icon-dot-3">
|
||||
<a class="logo" href="/console"
|
||||
<a class="logo link-animation-disabled" href="/console"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Logo Link">
|
||||
|
@ -83,7 +83,8 @@
|
|||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Home Link">
|
||||
data-analytics-label="Home Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-home"></i>
|
||||
Home
|
||||
</a>
|
||||
|
@ -97,7 +98,8 @@
|
|||
<a data-ls-attrs="href=/console/database?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Database Link">
|
||||
data-analytics-label="Database Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-database"></i>
|
||||
Database
|
||||
</a>
|
||||
|
@ -106,7 +108,8 @@
|
|||
<a data-ls-attrs="href=/console/storage?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Storage Link">
|
||||
data-analytics-label="Storage Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-folder"></i>
|
||||
Storage
|
||||
</a>
|
||||
|
@ -115,7 +118,8 @@
|
|||
<a data-ls-attrs="href=/console/users?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Users Link">
|
||||
data-analytics-label="Users Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-users"></i>
|
||||
Users
|
||||
</a>
|
||||
|
@ -129,7 +133,8 @@
|
|||
<a data-ls-attrs="href=/console/tasks?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Tasks Link">
|
||||
data-analytics-label="Tasks Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-clock"></i>
|
||||
Tasks
|
||||
</a>
|
||||
|
@ -138,7 +143,8 @@
|
|||
<a data-ls-attrs="href=/console/webhooks?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Webhooks Links">
|
||||
data-analytics-label="Webhooks Links"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-link"></i>
|
||||
Webhooks
|
||||
</a>
|
||||
|
@ -147,7 +153,8 @@
|
|||
<a data-ls-attrs="href=/console/keys?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="API Keys Link">
|
||||
data-analytics-label="API Keys Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-key-inv"></i>
|
||||
API Keys
|
||||
</a>
|
||||
|
@ -160,7 +167,8 @@
|
|||
<a data-ls-attrs="href=/console/settings?project={{router.params.project}}"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Settings Link">
|
||||
data-analytics-label="Settings Link"
|
||||
class="link-animation-disabled">
|
||||
<i class="icon-cog"></i> Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -214,4 +222,4 @@
|
|||
<button type="submit">Create</button> <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,7 +12,7 @@ $rules = $collection->getAttribute('rules', []);
|
|||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/database?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Database</a>
|
||||
<a data-ls-attrs="href=/console/database?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Database</a>
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -457,7 +457,7 @@ $rules = $collection->getAttribute('rules', []);
|
|||
<script type="text/html" id="template-validation-numeric">
|
||||
<div class="margin-bottom">
|
||||
<label data-ls-attrs="for=rule-default-{{rule.$id}}">Default Value</label>
|
||||
<input name="default" type="number" data-ls-bind="{{rule.default}}" data-cast-to="integer" placeholder="0" />
|
||||
<input name="default" type="number" data-ls-bind="{{rule.default}}" data-cast-to="numeric" placeholder="0" step="any" />
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
@ -516,4 +516,4 @@ $rules = $collection->getAttribute('rules', []);
|
|||
data-event="load,database.createCollection,database.updateCollection,database.deleteCollection"
|
||||
data-scope="sdk"
|
||||
data-name="project-collections">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ $collections = [];
|
|||
$key = (isset($rule['key'])) ? $rule['key'] : '';
|
||||
$label = (isset($rule['label'])) ? $rule['label'] : '';
|
||||
$type = (isset($rule['type'])) ? $rule['type'] : '';
|
||||
$list = (isset($rule['list'])) ? $rule['list'] : [];
|
||||
$list = (isset($rule['list']) && !empty($list)) ? $rule['list'] : [];
|
||||
?>
|
||||
<?php foreach($list as $item):
|
||||
if($item === $collection->getId()) {
|
||||
|
@ -51,7 +51,7 @@ $collections = [];
|
|||
$key = (isset($rule['key'])) ? $rule['key'] : '';
|
||||
$label = (isset($rule['label'])) ? $rule['label'] : '';
|
||||
$type = (isset($rule['type'])) ? $rule['type'] : '';
|
||||
$list = (isset($rule['list'])) ? $rule['list'] : false;
|
||||
$list = (isset($rule['list'])) ? $rule['list'] : [];
|
||||
$array = (isset($rule['array'])) ? $rule['array'] : false;
|
||||
?>
|
||||
|
||||
|
@ -163,7 +163,7 @@ $collections = [];
|
|||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{router.params.collection}}&project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> <?php echo $this->escape($name); ?></a>
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{router.params.collection}}&project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> <?php echo $this->escape($name); ?></a>
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -315,4 +315,4 @@ $collections = [];
|
|||
</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Database</span>
|
||||
|
@ -65,7 +65,7 @@
|
|||
<div data-ls-if="0 != {{project-collections.sum}}">
|
||||
<ul data-ls-loop="project-collections.collections" data-ls-as="collection" data-ls-append="" class="tiles cell-3 margin-bottom-small" style="visibility: hidden">
|
||||
<li class="margin-bottom">
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{collection.$id}}&project={{router.params.project}}" class="box">
|
||||
<a data-ls-attrs="href=/console/database/collection?id={{collection.$id}}&project={{router.params.project}}" class="box link-animation-disabled">
|
||||
<div data-ls-bind="{{collection.name}}" class="text-one-liner margin-bottom text-bold"> </div>
|
||||
|
||||
<i class="icon-right-open"></i>
|
||||
|
@ -109,4 +109,4 @@
|
|||
</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,4 +4,4 @@ $required = $this->getParam('required', '');
|
|||
$namespace = $this->getParam('namespace', '');
|
||||
?>
|
||||
|
||||
<input name="<?php echo $this->escape($key); ?>" type="number" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-cast-to="integer"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no" />
|
||||
<input name="<?php echo $this->escape($key); ?>" type="number" autocomplete="off" data-ls-bind="{{<?php echo $this->escape($namespace); ?>}}" data-cast-to="numeric"<?php if($required): ?> required<?php endif; ?> class="margin-bottom-no" step=any />
|
|
@ -33,7 +33,7 @@ $home = $this->getParam('home', '');
|
|||
|
||||
<ul data-ls-loop="console-projects" data-ls-as="project" data-ls-append="" class="tiles cell-3" style="visibility: hidden">
|
||||
<li class="margin-bottom">
|
||||
<a data-ls-attrs="href=/console/home?project={{project.$id}}" class="box">
|
||||
<a data-ls-attrs="href=/console/home?project={{project.$id}}" class="box link-animation-disabled">
|
||||
<div data-ls-bind="{{project.name}}" class="text-one-liner margin-bottom-tiny text-bold"> </div>
|
||||
|
||||
<p data-ls-if="({{project.platforms.length}})" class="text-fade text-size-small" data-ls-bind="{{project.platforms.length}} apps"></p>
|
||||
|
@ -102,4 +102,4 @@ $home = $this->getParam('home', '');
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -3,7 +3,7 @@ $scopes = $this->getParam('scopes', []);
|
|||
?>
|
||||
<div class="cover margin-bottom-large">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>API Keys</span>
|
||||
|
@ -167,4 +167,4 @@ $scopes = $this->getParam('scopes', []);
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
|||
?>
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Settings</span>
|
||||
|
@ -27,8 +27,10 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
|||
<li data-state="/console/settings?project={{router.params.project}}">
|
||||
<h2>Overview</h2>
|
||||
|
||||
<div class="row responsive">
|
||||
<div class="row responsive margin-top-negative">
|
||||
<div class="col span-8 margin-bottom">
|
||||
<label> </label>
|
||||
|
||||
<div class="box margin-bottom-large">
|
||||
<form
|
||||
data-analytics-event="submit"
|
||||
|
@ -500,4 +502,4 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
?>
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Storage</span>
|
||||
|
@ -36,7 +36,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
data-failure="alert"
|
||||
data-failure-param-alert-text="Failed to upload file"
|
||||
data-failure-param-alert-classname="error">
|
||||
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="int" value="1">
|
||||
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="integer" value="1">
|
||||
|
||||
<label for="file-read">File</label>
|
||||
<input type="file" name="file" id="file-file" size="1" required>
|
||||
|
@ -141,7 +141,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
<div class="input-copy">
|
||||
<input data-forms-copy type="text" data-ls-attrs="id=file-id-{{file.$id}}" name="fileId" disabled data-ls-bind="{{file.$id}}" />
|
||||
</div>
|
||||
<input type="hidden" data-ls-attrs="id=file-folderId-{{file.$id}}" name="folderId" data-cast-to="int" value="1">
|
||||
<input type="hidden" data-ls-attrs="id=file-folderId-{{file.$id}}" name="folderId" data-cast-to="integer" value="1">
|
||||
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<input type="hidden" data-ls-attrs="id=file-read-{{file.$id}}" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$permissions.read}}" placeholder="User ID, Team ID or Role" />
|
||||
|
@ -240,4 +240,4 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="cover margin-bottom-large">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Tasks</span>
|
||||
|
@ -346,4 +346,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@ $providers = $this->getParam('providers', []);
|
|||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Users</span>
|
||||
|
@ -387,4 +387,4 @@ $providers = $this->getParam('providers', []);
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<div class="cover">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/users?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Users</a>
|
||||
<a data-ls-attrs="href=/console/users?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Users</a>
|
||||
<br />
|
||||
|
||||
<span data-ls-bind="{{user.name}}"> </span>
|
||||
|
@ -255,4 +255,4 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ $events = array_keys($this->getParam('events', []));
|
|||
?>
|
||||
<div class="cover margin-bottom-large">
|
||||
<h1 class="zone xl margin-bottom-large">
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Home</a>
|
||||
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
|
||||
<br />
|
||||
|
||||
<span>Webhooks</span>
|
||||
|
@ -227,4 +227,4 @@ $events = array_keys($this->getParam('events', []));
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="logo text-align-center margin-bottom-xl">
|
||||
<a href="/">
|
||||
<a href="/" class="link-animation-disabled">
|
||||
<img src="/images/appwrite.svg" alt="Appwrite Light Logo" class="force-light" />
|
||||
<img src="/images/appwrite-footer-dark.svg" alt="Appwrite Dark Logo" class="force-dark" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
export PHP_VERSION=$PHP_VERSION
|
||||
|
||||
# Init server settings
|
||||
php /usr/share/nginx/html/app/tasks/migrate.php run
|
|
@ -66,6 +66,7 @@ services:
|
|||
#- _APP_ENV=production
|
||||
- _APP_ENV=development
|
||||
- _APP_OPTIONS_ABUSE=disabled
|
||||
- _APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
- _APP_OPENSSL_KEY_V1=your-secret-key
|
||||
- _APP_DOMAIN=demo.appwrite.io
|
||||
- _APP_DOMAIN_TARGET=demo.appwrite.io
|
||||
|
|
3
docs/references/avatars/get-initials.md
Normal file
3
docs/references/avatars/get-initials.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.
|
||||
|
||||
You can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.
|
|
@ -10,7 +10,11 @@ Set your server running environment. By default, the var is set to 'development'
|
|||
|
||||
### _APP_OPTIONS_ABUSE
|
||||
|
||||
Allows you to disable abuse checks and API rate limiting. By default, set to 'enabled'. To cancel the abuse checking, set to 'disabled'. It is not recommended to disable this check-in a production environment.
|
||||
Allows you to disable abuse checks and API rate limiting. By default, set to 'enabled'. To cancel the abuse checking, set to 'disabled'. It is not recommended to disable this feature in a production environment.
|
||||
|
||||
### _APP_OPTIONS_FORCE_HTTPS
|
||||
|
||||
Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the 'Strict-Transport-Security' header to all HTTP responses. By default, set to 'disabled'. To enable, set to 'enabled'. This feature will work only when your ports are set to default 80 and 443.
|
||||
|
||||
### _APP_OPENSSL_KEY_V1
|
||||
|
||||
|
|
15
public/dist/scripts/app-all.js
vendored
15
public/dist/scripts/app-all.js
vendored
|
@ -2511,7 +2511,7 @@ match=text.match(new RegExp(regex,'gi'))
|
|||
if(!match){return fail}
|
||||
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
||||
return(date.getTime()/1000)}
|
||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||
return value;}
|
||||
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
||||
ref=json[name];}
|
||||
|
@ -2553,15 +2553,10 @@ return k;}
|
|||
function J(k){k=k.replace(/rn/g,"n");let d="";for(let F=0;F<k.length;F++){let x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x);}else{if(x>127&&x<2048){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128);}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128);}}}
|
||||
return d;}
|
||||
let C=Array();let P,h,E,v,g,Y,X,W,V;let S=7,Q=12,N=17,M=22;let A=5,z=9,y=14,w=20;let o=4,m=11,l=16,j=23;let U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g);}
|
||||
let i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};let size=element.dataset["size"]||80;let email=$value.email||$value||"";let name=$value.name||$value||"";name=(typeof name!=='string')?'':name;let theme=name.split("").map(char=>char.charCodeAt(0)).reduce((a,b)=>a+b,0).toString();let themes=[{color:"27005e",background:"e1d2f6"},{color:"5e2700",background:"f3d9c6"},{color:"006128",background:"c9f3c6"},{color:"580061",background:"f2d1f5"},{color:"00365d",background:"c6e1f3"},{color:"00075c",background:"d2d5f6"},{color:"610038",background:"f5d1e6"},{color:"386100",background:"dcf1bd"},{color:"615800",background:"f1ecba"},{color:"610008",background:"f6d2d5"}];name=name.split(" ").map(function(n){if(!isNaN(parseFloat(n))&&isFinite(n)){return"";}
|
||||
return n[0];}).join("")||"--";let background=themes[theme[theme.length-1]]["background"];let color=themes[theme[theme.length-1]]["color"];let def="https://ui-avatars.com/api/"+
|
||||
encodeURIComponent(name)+"/"+
|
||||
size+"/"+
|
||||
encodeURIComponent(background)+"/"+
|
||||
encodeURIComponent(color);return("//www.gravatar.com/avatar/"+
|
||||
MD5(email)+".jpg?s="+
|
||||
size+"&d="+
|
||||
encodeURIComponent(def));}).add("selectedCollection",function($value,router){return $value===router.params.collectionId?"selected":"";}).add("selectedDocument",function($value,router){return $value===router.params.documentId?"selected":"";}).add("localeString",function($value){$value=parseInt($value);return!Number.isNaN($value)?$value.toLocaleString():"";}).add("date",function($value,date){return date.format("Y-m-d",$value);}).add("date-time",function($value,date){return date.format("Y-m-d H:i",$value);}).add("date-text",function($value,date){return date.format("d M Y",$value);}).add("ms2hum",function($value){let temp=$value;const years=Math.floor(temp/31536000),days=Math.floor((temp%=31536000)/86400),hours=Math.floor((temp%=86400)/3600),minutes=Math.floor((temp%=3600)/60),seconds=temp%60;if(days||hours||seconds||minutes){return((years?years+"y ":"")+
|
||||
let i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};let size=element.dataset["size"]||80;let email=$value.email||$value||"";let name=$value.name||$value||"";name=(typeof name!=='string')?'--':name;let def="/v1/avatars/initials?project=console"+"&name="+
|
||||
encodeURIComponent(name)+"&width="+
|
||||
size+"&height="+
|
||||
size;return def;}).add("selectedCollection",function($value,router){return $value===router.params.collectionId?"selected":"";}).add("selectedDocument",function($value,router){return $value===router.params.documentId?"selected":"";}).add("localeString",function($value){$value=parseInt($value);return!Number.isNaN($value)?$value.toLocaleString():"";}).add("date",function($value,date){return date.format("Y-m-d",$value);}).add("date-time",function($value,date){return date.format("Y-m-d H:i",$value);}).add("date-text",function($value,date){return date.format("d M Y",$value);}).add("ms2hum",function($value){let temp=$value;const years=Math.floor(temp/31536000),days=Math.floor((temp%=31536000)/86400),hours=Math.floor((temp%=86400)/3600),minutes=Math.floor((temp%=3600)/60),seconds=temp%60;if(days||hours||seconds||minutes){return((years?years+"y ":"")+
|
||||
(days?days+"d ":"")+
|
||||
(hours?hours+"h ":"")+
|
||||
(minutes?minutes+"m ":"")+
|
||||
|
|
15
public/dist/scripts/app.js
vendored
15
public/dist/scripts/app.js
vendored
|
@ -225,7 +225,7 @@ match=text.match(new RegExp(regex,'gi'))
|
|||
if(!match){return fail}
|
||||
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
||||
return(date.getTime()/1000)}
|
||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||
return value;}
|
||||
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
||||
ref=json[name];}
|
||||
|
@ -267,15 +267,10 @@ return k;}
|
|||
function J(k){k=k.replace(/rn/g,"n");let d="";for(let F=0;F<k.length;F++){let x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x);}else{if(x>127&&x<2048){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128);}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128);}}}
|
||||
return d;}
|
||||
let C=Array();let P,h,E,v,g,Y,X,W,V;let S=7,Q=12,N=17,M=22;let A=5,z=9,y=14,w=20;let o=4,m=11,l=16,j=23;let U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g);}
|
||||
let i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};let size=element.dataset["size"]||80;let email=$value.email||$value||"";let name=$value.name||$value||"";name=(typeof name!=='string')?'':name;let theme=name.split("").map(char=>char.charCodeAt(0)).reduce((a,b)=>a+b,0).toString();let themes=[{color:"27005e",background:"e1d2f6"},{color:"5e2700",background:"f3d9c6"},{color:"006128",background:"c9f3c6"},{color:"580061",background:"f2d1f5"},{color:"00365d",background:"c6e1f3"},{color:"00075c",background:"d2d5f6"},{color:"610038",background:"f5d1e6"},{color:"386100",background:"dcf1bd"},{color:"615800",background:"f1ecba"},{color:"610008",background:"f6d2d5"}];name=name.split(" ").map(function(n){if(!isNaN(parseFloat(n))&&isFinite(n)){return"";}
|
||||
return n[0];}).join("")||"--";let background=themes[theme[theme.length-1]]["background"];let color=themes[theme[theme.length-1]]["color"];let def="https://ui-avatars.com/api/"+
|
||||
encodeURIComponent(name)+"/"+
|
||||
size+"/"+
|
||||
encodeURIComponent(background)+"/"+
|
||||
encodeURIComponent(color);return("//www.gravatar.com/avatar/"+
|
||||
MD5(email)+".jpg?s="+
|
||||
size+"&d="+
|
||||
encodeURIComponent(def));}).add("selectedCollection",function($value,router){return $value===router.params.collectionId?"selected":"";}).add("selectedDocument",function($value,router){return $value===router.params.documentId?"selected":"";}).add("localeString",function($value){$value=parseInt($value);return!Number.isNaN($value)?$value.toLocaleString():"";}).add("date",function($value,date){return date.format("Y-m-d",$value);}).add("date-time",function($value,date){return date.format("Y-m-d H:i",$value);}).add("date-text",function($value,date){return date.format("d M Y",$value);}).add("ms2hum",function($value){let temp=$value;const years=Math.floor(temp/31536000),days=Math.floor((temp%=31536000)/86400),hours=Math.floor((temp%=86400)/3600),minutes=Math.floor((temp%=3600)/60),seconds=temp%60;if(days||hours||seconds||minutes){return((years?years+"y ":"")+
|
||||
let i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};let size=element.dataset["size"]||80;let email=$value.email||$value||"";let name=$value.name||$value||"";name=(typeof name!=='string')?'--':name;let def="/v1/avatars/initials?project=console"+"&name="+
|
||||
encodeURIComponent(name)+"&width="+
|
||||
size+"&height="+
|
||||
size;return def;}).add("selectedCollection",function($value,router){return $value===router.params.collectionId?"selected":"";}).add("selectedDocument",function($value,router){return $value===router.params.documentId?"selected":"";}).add("localeString",function($value){$value=parseInt($value);return!Number.isNaN($value)?$value.toLocaleString():"";}).add("date",function($value,date){return date.format("Y-m-d",$value);}).add("date-time",function($value,date){return date.format("Y-m-d H:i",$value);}).add("date-text",function($value,date){return date.format("d M Y",$value);}).add("ms2hum",function($value){let temp=$value;const years=Math.floor(temp/31536000),days=Math.floor((temp%=31536000)/86400),hours=Math.floor((temp%=86400)/3600),minutes=Math.floor((temp%=3600)/60),seconds=temp%60;if(days||hours||seconds||minutes){return((years?years+"y ":"")+
|
||||
(days?days+"d ":"")+
|
||||
(hours?hours+"h ":"")+
|
||||
(minutes?minutes+"m ":"")+
|
||||
|
|
2
public/dist/styles/default-ltr.css
vendored
2
public/dist/styles/default-ltr.css
vendored
File diff suppressed because one or more lines are too long
2
public/dist/styles/default-rtl.css
vendored
2
public/dist/styles/default-rtl.css
vendored
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,7 @@ window.ls.filter
|
|||
if (!$value) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// MD5 (Message-Digest Algorithm) by WebToolkit
|
||||
let MD5 = function(s) {
|
||||
function L(k, d) {
|
||||
|
@ -216,59 +216,68 @@ window.ls.filter
|
|||
let email = $value.email || $value || "";
|
||||
let name = $value.name || $value || "";
|
||||
|
||||
name = (typeof name !== 'string') ? '' : name;
|
||||
name = (typeof name !== 'string') ? '--' : name;
|
||||
|
||||
let theme = name
|
||||
.split("")
|
||||
.map(char => char.charCodeAt(0))
|
||||
.reduce((a, b) => a + b, 0)
|
||||
.toString();
|
||||
let themes = [
|
||||
{ color: "27005e", background: "e1d2f6" }, // VIOLET
|
||||
{ color: "5e2700", background: "f3d9c6" }, // ORANGE
|
||||
{ color: "006128", background: "c9f3c6" }, // GREEN
|
||||
{ color: "580061", background: "f2d1f5" }, // FUSCHIA
|
||||
{ color: "00365d", background: "c6e1f3" }, // BLUE
|
||||
{ color: "00075c", background: "d2d5f6" }, // INDIGO
|
||||
{ color: "610038", background: "f5d1e6" }, // PINK
|
||||
{ color: "386100", background: "dcf1bd" }, // LIME
|
||||
{ color: "615800", background: "f1ecba" }, // YELLOW
|
||||
{ color: "610008", background: "f6d2d5" } // RED
|
||||
];
|
||||
// let theme = name
|
||||
// .split("")
|
||||
// .map(char => char.charCodeAt(0))
|
||||
// .reduce((a, b) => a + b, 0)
|
||||
// .toString();
|
||||
// let themes = [
|
||||
// { color: "27005e", background: "e1d2f6" }, // VIOLET
|
||||
// { color: "5e2700", background: "f3d9c6" }, // ORANGE
|
||||
// { color: "006128", background: "c9f3c6" }, // GREEN
|
||||
// { color: "580061", background: "f2d1f5" }, // FUSCHIA
|
||||
// { color: "00365d", background: "c6e1f3" }, // BLUE
|
||||
// { color: "00075c", background: "d2d5f6" }, // INDIGO
|
||||
// { color: "610038", background: "f5d1e6" }, // PINK
|
||||
// { color: "386100", background: "dcf1bd" }, // LIME
|
||||
// { color: "615800", background: "f1ecba" }, // YELLOW
|
||||
// { color: "610008", background: "f6d2d5" } // RED
|
||||
// ];
|
||||
|
||||
name =
|
||||
name
|
||||
.split(" ")
|
||||
.map(function(n) {
|
||||
if (!isNaN(parseFloat(n)) && isFinite(n)) {
|
||||
return "";
|
||||
}
|
||||
// name =
|
||||
// name
|
||||
// .split(" ")
|
||||
// .map(function(n) {
|
||||
// if (!isNaN(parseFloat(n)) && isFinite(n)) {
|
||||
// return "";
|
||||
// }
|
||||
|
||||
return n[0];
|
||||
})
|
||||
.join("") || "--";
|
||||
// return n[0];
|
||||
// })
|
||||
// .join("") || "--";
|
||||
|
||||
let background = themes[theme[theme.length - 1]]["background"];
|
||||
let color = themes[theme[theme.length - 1]]["color"];
|
||||
// let background = themes[theme[theme.length - 1]]["background"];
|
||||
// let color = themes[theme[theme.length - 1]]["color"];
|
||||
|
||||
let def =
|
||||
"https://ui-avatars.com/api/" +
|
||||
"/v1/avatars/initials?project=console"+
|
||||
"&name=" +
|
||||
encodeURIComponent(name) +
|
||||
"/" +
|
||||
"&width=" +
|
||||
size +
|
||||
"/" +
|
||||
encodeURIComponent(background) +
|
||||
"/" +
|
||||
encodeURIComponent(color);
|
||||
"&height=" +
|
||||
size;
|
||||
|
||||
return (
|
||||
"//www.gravatar.com/avatar/" +
|
||||
MD5(email) +
|
||||
".jpg?s=" +
|
||||
size +
|
||||
"&d=" +
|
||||
encodeURIComponent(def)
|
||||
);
|
||||
return def;
|
||||
// let def =
|
||||
// "https://ui-avatars.com/api/" +
|
||||
// encodeURIComponent(name) +
|
||||
// "/" +
|
||||
// size +
|
||||
// "/" +
|
||||
// encodeURIComponent(background) +
|
||||
// "/" +
|
||||
// encodeURIComponent(color);
|
||||
// return (
|
||||
// "//www.gravatar.com/avatar/" +
|
||||
// MD5(email) +
|
||||
// ".jpg?s=" +
|
||||
// size +
|
||||
// "&d=" +
|
||||
// encodeURIComponent(def)
|
||||
// );
|
||||
})
|
||||
.add("selectedCollection", function($value, router) {
|
||||
return $value === router.params.collectionId ? "selected" : "";
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
case 'integer':
|
||||
value = parseInt(value);
|
||||
break;
|
||||
case 'numeric':
|
||||
value = Number(value);
|
||||
break;
|
||||
case 'string':
|
||||
value = value.toString();
|
||||
break;
|
||||
|
|
|
@ -334,9 +334,6 @@ a.box {
|
|||
}
|
||||
|
||||
a.box:hover {
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
box-shadow: 0 0 1px rgba(0, 0, 0, .2);
|
||||
opacity: .7;
|
||||
}
|
||||
|
@ -362,4 +359,4 @@ a.box:hover {
|
|||
bottom: 0;
|
||||
.func-start(-6px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,6 @@ header {
|
|||
margin: 7px 0;
|
||||
display: block;
|
||||
|
||||
&:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
|
@ -35,10 +31,6 @@ header {
|
|||
|
||||
.account {
|
||||
.func-margin-start(25px);
|
||||
|
||||
&:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
@ -113,4 +105,4 @@ header {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clik
|
|||
box-shadow: 0 2px 4px 0 rgba(50,50,93,.3);
|
||||
border-radius: 10px;
|
||||
margin-bottom: 30px;
|
||||
&:extend(.force-left);
|
||||
&:extend(.force-ltr);
|
||||
|
||||
* {
|
||||
font-family: 'Source Code Pro', monospace;
|
||||
|
|
|
@ -36,7 +36,6 @@ button,
|
|||
&:hover,
|
||||
&:focus {
|
||||
background: var(--config-color-focus-hover);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.fly {
|
||||
|
@ -175,10 +174,6 @@ button,
|
|||
padding: 0;
|
||||
.func-padding-end(0) !important;
|
||||
|
||||
&:hover {
|
||||
border-bottom: dotted 1px var(--config-color-link);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: inherit;
|
||||
}
|
||||
|
@ -1300,4 +1295,4 @@ ol {
|
|||
.pull-start;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,10 +130,6 @@
|
|||
.account {
|
||||
.func-margin-start(25px);
|
||||
.text-one-liner;
|
||||
|
||||
&:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.switch-theme {
|
||||
|
@ -189,11 +185,6 @@
|
|||
height: 39px;
|
||||
padding: 15px 20px;
|
||||
display: block;
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
|
@ -364,7 +355,6 @@
|
|||
&:hover,
|
||||
&.selected {
|
||||
color: #e4e4e4;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -548,6 +538,7 @@
|
|||
|
||||
@media @tablets, @phones {
|
||||
width: 100%;
|
||||
padding-bottom: 32%;
|
||||
float: none;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,9 @@ html.home {
|
|||
.logo {
|
||||
a {
|
||||
display: block;
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
opacity: .8;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,4 +28,4 @@ html.home {
|
|||
main {
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@ a, .link {
|
|||
text-decoration: none;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: 2px solid transparent;
|
||||
border-bottom: solid 1px transparent;
|
||||
transition: 200ms;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-bottom: dotted 1px var(--config-color-link);
|
||||
cursor: pointer;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
|
@ -29,11 +30,11 @@ a, .link {
|
|||
}
|
||||
|
||||
&.disabled:hover {
|
||||
border-bottom: none;
|
||||
.link.link-animation-disabled();
|
||||
}
|
||||
|
||||
&.tag:hover {
|
||||
border-bottom: none;
|
||||
.link.link-animation-disabled();
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
|
@ -42,6 +43,46 @@ a, .link {
|
|||
}
|
||||
}
|
||||
|
||||
a.link-animation-disabled,
|
||||
.link.link-animation-disabled {
|
||||
&:hover {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.func-link-return-animation(@pos) {
|
||||
.link.link-animation-disabled();
|
||||
|
||||
& > i {
|
||||
display: inline-block;
|
||||
transition: 200ms;
|
||||
}
|
||||
|
||||
&:hover > i {
|
||||
transform: translateX(@pos);
|
||||
}
|
||||
}
|
||||
|
||||
@link-return-animation-offset: 2px;
|
||||
|
||||
.link-return-animation--start {
|
||||
.func-link-return-animation(
|
||||
if((@config-start = right),
|
||||
@link-return-animation-offset,
|
||||
-@link-return-animation-offset
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
.link-return-animation--end {
|
||||
.func-link-return-animation(
|
||||
if((@config-start = right),
|
||||
-@link-return-animation-offset,
|
||||
@link-return-animation-offset
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
@ -196,4 +237,12 @@ small {
|
|||
|
||||
.icon-dot-3:before {
|
||||
.func-rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
// fix icons vertical alignment
|
||||
i[class^='icon-'], i[class*=' icon-']{
|
||||
&:before {
|
||||
display: inline;
|
||||
line-height: unset;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -411,4 +411,95 @@ trait AvatarsBase
|
|||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function testGetInitials()
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/png; charset=UTF-8', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'width' => 200,
|
||||
'height' => 200,
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/png; charset=UTF-8', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'name' => 'W W',
|
||||
'width' => 200,
|
||||
'height' => 200,
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/png; charset=UTF-8', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'name' => 'W W',
|
||||
'width' => 200,
|
||||
'height' => 200,
|
||||
'color' => 'ffffff',
|
||||
'background' => '000000',
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals('image/png; charset=UTF-8', $response['headers']['content-type']);
|
||||
$this->assertNotEmpty($response['body']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'name' => 'W W',
|
||||
'width' => 200000,
|
||||
'height' => 200,
|
||||
'color' => 'ffffff',
|
||||
'background' => '000000',
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'name' => 'W W',
|
||||
'width' => 200,
|
||||
'height' => 200,
|
||||
'color' => 'white',
|
||||
'background' => '000000',
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, '/avatars/initials', [
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'name' => 'W W',
|
||||
'width' => 200,
|
||||
'height' => 200,
|
||||
'color' => 'ffffff',
|
||||
'background' => 'black',
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue