Merge branch 'master' of github.com:appwrite/appwrite
This commit is contained in:
commit
71bcc796f6
33 changed files with 266 additions and 113 deletions
|
@ -9,6 +9,8 @@
|
|||
- 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
|
||||
- Added support for Brotli compression
|
||||
- UI performance & accessibility improvments
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
@ -17,6 +19,7 @@
|
|||
- Fixed network calculation for uploaded files
|
||||
- Fixed a UI bug preventing float values in numeric fields
|
||||
- Fixed scroll positioning when moving rules order up & down
|
||||
- Fixed missing validation for database documents key length (32 chars)
|
||||
|
||||
## Security
|
||||
|
||||
|
|
45
Dockerfile
45
Dockerfile
|
@ -11,7 +11,7 @@ ENV TZ=Asia/Tel_Aviv \
|
|||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests ca-certificates software-properties-common wget curl git openssl && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests ca-certificates software-properties-common wget git openssl && \
|
||||
LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests make php$PHP_VERSION php$PHP_VERSION-dev zip unzip php$PHP_VERSION-zip && \
|
||||
|
@ -23,7 +23,13 @@ RUN \
|
|||
./configure && \
|
||||
make && \
|
||||
# Composer
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
|
||||
wget https://getcomposer.org/composer.phar && \
|
||||
chmod +x ./composer.phar && \
|
||||
mv ./composer.phar /usr/bin/composer && \
|
||||
#Brotli
|
||||
cd / && \
|
||||
git clone https://github.com/eustas/ngx_brotli.git && \
|
||||
cd ngx_brotli && git submodule update --init && cd ..
|
||||
|
||||
WORKDIR /usr/local/src/
|
||||
|
||||
|
@ -75,31 +81,50 @@ ENV TZ=Asia/Tel_Aviv \
|
|||
#ENV _APP_SMTP_PASSWORD ''
|
||||
|
||||
COPY --from=builder /phpredis-5.2.1/modules/redis.so /usr/lib/php/20190902/
|
||||
COPY --from=builder /phpredis-5.2.1/modules/redis.so /usr/lib/php/20190902/
|
||||
COPY --from=builder /ngx_brotli /ngx_brotli
|
||||
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests wget curl ca-certificates software-properties-common openssl gnupg && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests wget ca-certificates software-properties-common build-essential libpcre3-dev zlib1g-dev libssl-dev openssl gnupg htop supervisor && \
|
||||
LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php && \
|
||||
add-apt-repository universe && \
|
||||
add-apt-repository ppa:certbot/certbot && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests htop supervisor php$PHP_VERSION php$PHP_VERSION-fpm \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests php$PHP_VERSION php$PHP_VERSION-fpm \
|
||||
php$PHP_VERSION-mysqlnd php$PHP_VERSION-curl php$PHP_VERSION-imagick php$PHP_VERSION-mbstring php$PHP_VERSION-dom webp certbot && \
|
||||
# Nginx
|
||||
echo "deb http://nginx.org/packages/mainline/ubuntu/ bionic nginx" >> /etc/apt/sources.list.d/nginx.list && \
|
||||
wget -q http://nginx.org/keys/nginx_signing.key && \
|
||||
apt-key add nginx_signing.key && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends --no-install-suggests nginx && \
|
||||
wget http://nginx.org/download/nginx-1.19.0.tar.gz && \
|
||||
tar -xzvf nginx-1.19.0.tar.gz && rm nginx-1.19.0.tar.gz && \
|
||||
cd nginx-1.19.0 && \
|
||||
./configure --prefix=/usr/share/nginx \
|
||||
--sbin-path=/usr/sbin/nginx \
|
||||
--modules-path=/usr/lib/nginx/modules \
|
||||
--conf-path=/etc/nginx/nginx.conf \
|
||||
--error-log-path=/var/log/nginx/error.log \
|
||||
--http-log-path=/var/log/nginx/access.log \
|
||||
--pid-path=/run/nginx.pid \
|
||||
--lock-path=/var/lock/nginx.lock \
|
||||
--user=www-data \
|
||||
--group=www-data \
|
||||
--build=Ubuntu \
|
||||
--with-http_gzip_static_module \
|
||||
--with-http_ssl_module \
|
||||
--with-http_v2_module \
|
||||
--add-module=/ngx_brotli && \
|
||||
make && \
|
||||
make install && \
|
||||
rm -rf ../nginx-1.19.0 && \
|
||||
# Redis Extension
|
||||
echo extension=redis.so >> /etc/php/$PHP_VERSION/fpm/conf.d/redis.ini && \
|
||||
echo extension=redis.so >> /etc/php/$PHP_VERSION/cli/conf.d/redis.ini && \
|
||||
# Cleanup
|
||||
cd ../ && \
|
||||
apt-get purge -y --auto-remove software-properties-common gnupg curl && \
|
||||
apt-get purge -y --auto-remove wget software-properties-common build-essential libpcre3-dev zlib1g-dev libssl-dev gnupg && \
|
||||
apt-get clean && \
|
||||
rm -rf /ngx_brotli && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set Upload Limit (default to 100MB)
|
||||
|
|
|
@ -27,6 +27,7 @@ $services = include __DIR__.'/config/services.php'; // List of services
|
|||
$webhook = new Event('v1-webhooks', 'WebhooksV1');
|
||||
$audit = new Event('v1-audits', 'AuditsV1');
|
||||
$usage = new Event('v1-usage', 'UsageV1');
|
||||
$mail = new Event('v1-mails', 'MailsV1');
|
||||
$deletes = new Event('v1-deletes', 'DeletesV1');
|
||||
|
||||
/**
|
||||
|
@ -53,7 +54,7 @@ $clients = array_unique(array_merge($clientsConsole, array_map(function ($node)
|
|||
return false;
|
||||
}))));
|
||||
|
||||
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $console, $roles, $webhook, $audit, $usage, $clients) {
|
||||
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $console, $roles, $webhook, $mail, $audit, $usage, $clients) {
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
global $utopia, $register, $request, $response, $user, $audit,
|
||||
$webhook, $project, $projectDB, $clients;
|
||||
$webhook, $mail, $project, $projectDB, $clients;
|
||||
|
||||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
|
@ -60,7 +60,7 @@ $utopia->post('/v1/account')
|
|||
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
|
||||
->param('name', '', function () { return new Text(100); }, 'User name.', true)
|
||||
->action(
|
||||
function ($email, $password, $name) use ($register, $request, $response, $audit, $projectDB, $project, $webhook, $oauth2Keys) {
|
||||
function ($email, $password, $name) use ($request, $response, $audit, $projectDB, $project, $webhook, $oauth2Keys) {
|
||||
if ('console' === $project->getId()) {
|
||||
$whitlistEmails = $project->getAttribute('authWhitelistEmails');
|
||||
$whitlistIPs = $project->getAttribute('authWhitelistIPs');
|
||||
|
@ -1053,7 +1053,7 @@ $utopia->post('/v1/account/recovery')
|
|||
->param('email', '', function () { return new Email(); }, 'User email.')
|
||||
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.')
|
||||
->action(
|
||||
function ($email, $url) use ($request, $response, $projectDB, $register, $audit, $project) {
|
||||
function ($email, $url) use ($request, $response, $projectDB, $mail, $audit, $project) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
|
@ -1106,19 +1106,14 @@ $utopia->post('/v1/account/recovery')
|
|||
->setParam('{{redirect}}', $url)
|
||||
;
|
||||
|
||||
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
|
||||
|
||||
$mail->addAddress($profile->getAttribute('email', ''), $profile->getAttribute('name', ''));
|
||||
|
||||
$mail->Subject = Locale::getText('account.emails.recovery.title');
|
||||
$mail->Body = $body->render();
|
||||
$mail->AltBody = strip_tags($body->render());
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
} catch (\Exception $error) {
|
||||
throw new Exception('Error sending mail: ' . $error->getMessage(), 500);
|
||||
}
|
||||
$mail
|
||||
->setParam('event', 'account.recovery.create')
|
||||
->setParam('recipient', $profile->getAttribute('email', ''))
|
||||
->setParam('name', $profile->getAttribute('name', ''))
|
||||
->setParam('subject', Locale::getText('account.emails.recovery.title'))
|
||||
->setParam('body', $body->render())
|
||||
->trigger();
|
||||
;
|
||||
|
||||
$audit
|
||||
->setParam('userId', $profile->getId())
|
||||
|
@ -1214,7 +1209,7 @@ $utopia->post('/v1/account/verification')
|
|||
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.') // TODO add built-in confirm page
|
||||
->action(
|
||||
function ($url) use ($request, $response, $register, $user, $project, $projectDB, $audit) {
|
||||
function ($url) use ($request, $response, $mail, $user, $project, $projectDB, $audit) {
|
||||
$verificationSecret = Auth::tokenGenerator();
|
||||
|
||||
$verification = new Document([
|
||||
|
@ -1255,19 +1250,14 @@ $utopia->post('/v1/account/verification')
|
|||
->setParam('{{redirect}}', $url)
|
||||
;
|
||||
|
||||
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
|
||||
|
||||
$mail->addAddress($user->getAttribute('email'), $user->getAttribute('name'));
|
||||
|
||||
$mail->Subject = Locale::getText('account.emails.verification.title');
|
||||
$mail->Body = $body->render();
|
||||
$mail->AltBody = strip_tags($body->render());
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
} catch (\Exception $error) {
|
||||
throw new Exception('Problem sending mail: ' . $error->getMessage(), 500);
|
||||
}
|
||||
$mail
|
||||
->setParam('event', 'account.verification.create')
|
||||
->setParam('recipient', $user->getAttribute('email'))
|
||||
->setParam('name', $user->getAttribute('name'))
|
||||
->setParam('subject', Locale::getText('account.emails.verification.title'))
|
||||
->setParam('body', $body->render())
|
||||
->trigger()
|
||||
;
|
||||
|
||||
$audit
|
||||
->setParam('userId', $user->getId())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
global $utopia, $register, $request, $response, $projectDB, $project, $user, $audit, $mode, $clients;
|
||||
global $utopia, $register, $request, $response, $projectDB, $project, $user, $audit, $mail, $mode, $clients;
|
||||
|
||||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
|
@ -215,7 +215,7 @@ $utopia->post('/v1/teams/:teamId/memberships')
|
|||
->param('roles', [], function () { return new ArrayList(new Text(128)); }, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions).')
|
||||
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.') // TODO add our own built-in confirm page
|
||||
->action(
|
||||
function ($teamId, $email, $name, $roles, $url) use ($response, $register, $project, $user, $audit, $projectDB, $mode) {
|
||||
function ($teamId, $email, $name, $roles, $url) use ($response, $mail, $project, $user, $audit, $projectDB, $mode) {
|
||||
$name = (empty($name)) ? $email : $name;
|
||||
$team = $projectDB->getDocument($teamId);
|
||||
|
||||
|
@ -332,20 +332,15 @@ $utopia->post('/v1/teams/:teamId/memberships')
|
|||
->setParam('{{redirect}}', $url)
|
||||
;
|
||||
|
||||
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
|
||||
|
||||
$mail->addAddress($email, $name);
|
||||
|
||||
$mail->Subject = sprintf(Locale::getText('account.emails.invitation.title'), $team->getAttribute('name', '[TEAM-NAME]'), $project->getAttribute('name', ['[APP-NAME]']));
|
||||
$mail->Body = $body->render();
|
||||
$mail->AltBody = strip_tags($body->render());
|
||||
|
||||
try {
|
||||
if(APP_MODE_ADMIN !== $mode) { // No need in comfirmation when in admin mode
|
||||
$mail->send();
|
||||
}
|
||||
} catch (\Exception $error) {
|
||||
throw new Exception('Error sending mail: ' . $error->getMessage(), 500);
|
||||
$mail
|
||||
->setParam('event', 'teams.membership.create')
|
||||
->setParam('recipient', $email)
|
||||
->setParam('name', $name)
|
||||
->setParam('subject', sprintf(Locale::getText('account.emails.invitation.title'), $team->getAttribute('name', '[TEAM-NAME]'), $project->getAttribute('name', ['[APP-NAME]'])))
|
||||
->setParam('body', $body->render())
|
||||
->trigger();
|
||||
;
|
||||
}
|
||||
|
||||
$audit
|
||||
|
|
|
@ -14,6 +14,7 @@ use Appwrite\Storage\Storage;
|
|||
|
||||
$utopia->init(function () use ($layout) {
|
||||
$layout
|
||||
->setParam('description', 'Appwrite Console allows you to easily manage, monitor, and control your entire backend API and tools.')
|
||||
->setParam('analytics', 'UA-26264668-5')
|
||||
;
|
||||
});
|
||||
|
|
|
@ -9,21 +9,21 @@ $version = $this->getParam('version', '').'.'.APP_CACHE_BUSTER;
|
|||
data-analytics-event="click"
|
||||
data-analytics-category="console/footer"
|
||||
data-analytics-label="GitHub Link"
|
||||
href="https://github.com/appwrite/appwrite" target="_blank"><i class="icon-github-circled"></i> GitHub</a>
|
||||
href="https://github.com/appwrite/appwrite" target="_blank" rel="noopener"><i class="icon-github-circled"></i> GitHub</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/footer"
|
||||
data-analytics-label="New GitHub Issue"
|
||||
href="https://github.com/appwrite/appwrite/issues/new?body=%0A%0A%0A---%0AAppwrite Version:%20<?php echo $version; ?>" target="_blank">Open an Issue</a>
|
||||
href="https://github.com/appwrite/appwrite/issues/new?body=%0A%0A%0A---%0AAppwrite Version:%20<?php echo $version; ?>" target="_blank" rel="noopener">Open an Issue</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/footer"
|
||||
data-analytics-label="Docs Link"
|
||||
href="<?php echo $home; ?>/docs" target="_blank">Docs</a>
|
||||
href="<?php echo $home; ?>/docs" target="_blank" rel="noopener">Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
v:<?php echo $version; ?>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<span class="name pull-end desktops-only" data-ls-bind="{{account.name}}"></span>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<div class="console-index drop-list bottom end" data-ls-ui-open="" data-button-text="" data-button-aria="Account Options" data-button-icon="" data-button-selector="[data-toggler]" data-button-class="account-button" data-blur="1">
|
||||
<ul class="margin-top-large arrow-end">
|
||||
<li>
|
||||
<a href="/console/account" class="link-animation-disabled"><i class="icon-user"></i> Your Account</a>
|
||||
|
@ -65,15 +65,15 @@
|
|||
|
||||
</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">
|
||||
<nav class="project-only" data-ls-ui-open="" data-button-class="round icon-btn phones-only tablets-only" data-button-aria="Navigation" data-button-icon="icon-dot-3">
|
||||
<a class="logo link-animation-disabled" href="/console"
|
||||
data-analytics-event="click"
|
||||
data-analytics-category="console/navigation"
|
||||
data-analytics-label="Logo Link">
|
||||
<img src="/images/appwrite-nav.svg" alt="Appwrite Logo" class="nav" />
|
||||
<img src="/images/appwrite-nav.svg" loading="lazy" alt="Appwrite Logo" class="nav" />
|
||||
|
||||
<img src="/images/appwrite.svg" alt="Appwrite Light Logo" class="top force-light" />
|
||||
<img src="/images/appwrite-footer-dark.svg" alt="Appwrite Dark Logo" class="top force-dark" />
|
||||
<img src="/images/appwrite.svg" loading="lazy" alt="Appwrite Light Logo" class="top force-light" />
|
||||
<img src="/images/appwrite-footer-dark.svg" loading="lazy" alt="Appwrite Dark Logo" class="top force-dark" />
|
||||
</a>
|
||||
|
||||
<div data-ui-highlight class="container">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
$collection = $this->getParam('collection', []);
|
||||
$rules = $collection->getAttribute('rules', []);
|
||||
$maxCells = 10;
|
||||
?>
|
||||
|
||||
<div
|
||||
|
@ -87,7 +88,10 @@ $rules = $collection->getAttribute('rules', []);
|
|||
<table class="vertical">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach($rules as $rule):
|
||||
<?php foreach($rules as $i => $rule):
|
||||
if($i > $maxCells) {
|
||||
break;
|
||||
}
|
||||
$label = (isset($rule['label'])) ? $rule['label'] : '';
|
||||
?>
|
||||
<th width="120"><?php echo $this->escape($label); ?></th>
|
||||
|
@ -96,7 +100,10 @@ $rules = $collection->getAttribute('rules', []);
|
|||
</thead>
|
||||
<tbody data-ls-loop="project-documents.documents" data-ls-as="node">
|
||||
<tr>
|
||||
<?php foreach($rules as $rule):
|
||||
<?php foreach($rules as $i => $rule):
|
||||
if($i > $maxCells) {
|
||||
break;
|
||||
}
|
||||
$label = (isset($rule['label'])) ? $rule['label'] : '';
|
||||
$key = (isset($rule['key'])) ? $rule['key'] : '';
|
||||
$type = (isset($rule['type'])) ? $rule['type'] : '';
|
||||
|
@ -251,7 +258,7 @@ $rules = $collection->getAttribute('rules', []);
|
|||
<span class="tooltip small" data-tooltip="Attribute key name. Used as the document JSON key in the Database API"><i class="icon-info-circled"></i></span>
|
||||
</label>
|
||||
<div class="input-copy">
|
||||
<input data-forms-copy name="key" type="text" data-ls-bind="{{rule.key}}" max="32" pattern="^(\d|\w)+$" title="No spaces or special charts allowed" />
|
||||
<input data-forms-copy name="key" type="text" data-ls-bind="{{rule.key}}" maxlength="32" pattern="^(\d|\w)+$" title="No spaces or special charts allowed" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -301,17 +308,17 @@ $rules = $collection->getAttribute('rules', []);
|
|||
|
||||
<button type="button" data-ls-ui-trigger="add-rule" class="reverse margin-top"><i class="icon-plus"></i>Add</button>
|
||||
|
||||
<div class="toggle margin-bottom margin-top" data-ls-ui-open>
|
||||
<div class="toggle margin-bottom margin-top" data-ls-ui-open data-button-aria="Open Permissions">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
<h3 class="margin-bottom-large">Permissions</h3>
|
||||
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</span></label>
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
|
||||
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.read}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.write}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
</div>
|
||||
|
@ -404,7 +411,7 @@ $rules = $collection->getAttribute('rules', []);
|
|||
<span class="tooltip small" data-tooltip="Attribute key name. Used as the document JSON key in the Database API"><i class="icon-info-circled"></i></span>
|
||||
</label>
|
||||
<div class="input-copy">
|
||||
<input data-forms-copy name="key" type="text" required max="32" pattern="^(\d|\w)+$" title="No spaces or special charts allowed" />
|
||||
<input data-forms-copy name="key" type="text" required maxlength="32" pattern="^(\d|\w)+$" title="No spaces or special charts allowed" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -246,17 +246,17 @@ $collections = [];
|
|||
echo $comp->render();
|
||||
?>
|
||||
|
||||
<div class="toggle margin-bottom" data-ls-ui-open>
|
||||
<div class="toggle margin-bottom" data-ls-ui-open data-button-aria="Open Permissions">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
<h3 class="margin-bottom-large">Permissions</h3>
|
||||
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</span></label>
|
||||
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
|
||||
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.read}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.write}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ if($type === 'document') {
|
|||
|
||||
<ul data-ls-loop="<?php echo $this->escape($namespace); ?>" data-ls-as="node" class="sortable numbers">
|
||||
<li data-forms-move-up data-forms-move-down>
|
||||
<div class="drop-list bottom end settings" data-ls-ui-open="" data-button-text="" data-button-icon="icon-cog" data-button-selector="[data-toggler]" data-button-class="round dark small margin-bottom-small margin-top-tiny pull-end" data-blur="1" tabindex="1">
|
||||
<div class="drop-list bottom end settings" data-ls-ui-open="" data-button-text="" data-button-icon="icon-cog" data-button-aria="Options" data-button-selector="[data-toggler]" data-button-class="round dark small margin-bottom-small margin-top-tiny pull-end" data-blur="1">
|
||||
<ul class="arrow-end margin-top margin-end-negative-small">
|
||||
<li data-move-up>
|
||||
<button type="button" class="link"><i class="icon-up-dir"></i> Move Up</button>
|
||||
|
@ -41,7 +41,7 @@ if($type === 'document') {
|
|||
</ul>
|
||||
|
||||
<?php if(!empty($list) && $type === 'document'): ?>
|
||||
<div class="drop-list" data-ls-ui-open="" data-button-text="Add" data-button-icon="" data-button-selector="[data-toggler]" data-button-class="reverse margin-bottom-small" data-blur="1" tabindex="1">
|
||||
<div class="drop-list" data-ls-ui-open="" data-button-text="Add" data-button-aria="Add" data-button-icon="" data-button-selector="[data-toggler]" data-button-class="reverse margin-bottom-small" data-blur="1">
|
||||
<ul>
|
||||
<?php foreach($list as $item):
|
||||
$name = (isset($collections[$item])) ? $collections[$item]->getAttribute('name', '') : '';
|
||||
|
|
|
@ -157,22 +157,22 @@ $graph = $this->getParam('graph', false);
|
|||
<a data-ls-attrs="href=/console/keys?project={{router.params.project}}">Manage Your Server API Keys</a>
|
||||
</div>
|
||||
|
||||
<div class="drop-list pull-start" data-ls-ui-open="" data-button-text="Add Platform" data-button-class="button" data-blur="1" tabindex="1">
|
||||
<div class="drop-list pull-start" data-ls-ui-open="" data-button-aria="Choose Platform" data-button-text="Add Platform" data-button-class="button" data-blur="1">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="link web-new"><img src="/images/clients/web.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Web Platform Logo" class="avatar xxs margin-end-small" /> New Web App</div>
|
||||
<div class="link web-new"><img src="/images/clients/web.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Web Platform Logo" class="avatar xxs margin-end-small" loading="lazy" /> New Web App</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="link flutter-new"><img src="/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Flutter Platform Logo" class="avatar xxs margin-end-small" /> New Flutter App <span class="text-size-tiny">(beta)</span></div>
|
||||
<div class="link flutter-new"><img src="/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Flutter Platform Logo" class="avatar xxs margin-end-small" loading="lazy" /> New Flutter App <span class="text-size-tiny">(beta)</span></div>
|
||||
</li>
|
||||
<li class="disabled">
|
||||
<div class="link ios-new"><img src="/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Platform Logo" class="avatar xxs margin-end-small" /> New iOS App</div>
|
||||
<div class="link ios-new"><img src="/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Platform Logo" class="avatar xxs margin-end-small" loading="lazy" /> New iOS App</div>
|
||||
</li>
|
||||
<li class="disabled">
|
||||
<div class="link android-new"><img src="/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Platform Logo" class="avatar xxs margin-end-small" /> New Android App</div>
|
||||
<div class="link android-new"><img src="/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Platform Logo" class="avatar xxs margin-end-small" loading="lazy" /> New Android App</div>
|
||||
</li>
|
||||
<li class="disabled">
|
||||
<div class="link unity-new"><img src="/images/clients/unity.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Unity Platform Logo" class="avatar xxs margin-end-small" /> New Unity Game</div>
|
||||
<div class="link unity-new"><img src="/images/clients/unity.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Unity Platform Logo" class="avatar xxs margin-end-small" loading="lazy" /> New Unity Game</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -209,7 +209,7 @@ $graph = $this->getParam('graph', false);
|
|||
<div class="info margin-top margin-bottom">
|
||||
<div class="text-bold margin-bottom-small">Next Steps</div>
|
||||
|
||||
<p>After adding your new website, install our JS SDK to integrate with your code and read our <a data-ls-attrs="href={{env.HOME}}/docs/getting-started-for-web" target="_blank">getting started</a> tutorial.</p>
|
||||
<p>After adding your new website, install our JS SDK to integrate with your code and read our <a data-ls-attrs="href={{env.HOME}}/docs/getting-started-for-web" target="_blank" rel="noopener">getting started</a> tutorial.</p>
|
||||
|
||||
<div class="margin-bottom-no ide" data-lang="bash" data-lang-label="bash">
|
||||
<pre class="line-numbers"><code class="prism language-bash" data-prism>npm install appwrite</code></pre>
|
||||
|
|
|
@ -9,9 +9,8 @@ $home = $this->getParam('home', '');
|
|||
<p class="margin-bottom margin-top-negative-small">Take advantage of the Appwrite APIs and tools.</p>
|
||||
|
||||
<ul class="margin-bottom-xl clear">
|
||||
<li class="pull-start margin-end margin-bottom-small"><a href="<?php echo $home; ?>/" target="_blank"><i class="icon-lamp"></i> Learn more</a></li>
|
||||
<li class="pull-start margin-end margin-bottom-small"><a href="<?php echo $home; ?>/docs" target="_blank"><i class="icon-book-open"></i> Docs</a></li>
|
||||
<li class="pull-start margin-end margin-bottom-small"><a href="<?php echo $home; ?>/support" target="_blank"><i class="icon-lifebuoy"></i> Support</a></li>
|
||||
<li class="pull-start margin-end margin-bottom-small"><a href="<?php echo $home; ?>/docs" target="_blank" rel="noopener"><i class="icon-book-open"></i> Docs</a></li>
|
||||
<li class="pull-start margin-end margin-bottom-small"><a href="<?php echo $home; ?>/support" target="_blank" rel="noopener"><i class="icon-lifebuoy"></i> Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,7 +64,7 @@ $home = $this->getParam('home', '');
|
|||
|
||||
<div class="row responsive">
|
||||
<div class="col span-6 margin-bottom">
|
||||
<div class="box line">
|
||||
<div class="box line community">
|
||||
<h3 class="margin-bottom-small text-size-normal">Join The Community</h3>
|
||||
|
||||
<p class="text-fade">Join Appwrite growing developers community channels.</p>
|
||||
|
|
|
@ -52,7 +52,7 @@ $scopes = $this->getParam('scopes', []);
|
|||
<label data-ls-attrs="for=name-{{key.$id}}">Name</label>
|
||||
<input type="text" class="full-width" data-ls-attrs="id=name-{{key.$id}}" name="name" required autocomplete="off" data-ls-bind="{{key.name}}" />
|
||||
|
||||
<label data-ls-attrs="for=scopes-{{key.$id}}">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank">Learn more</a>)</label>
|
||||
<label data-ls-attrs="for=scopes-{{key.$id}}">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<div class="row responsive thin">
|
||||
<?php foreach ($scopes as $i => $scope) : ?>
|
||||
<div class="col span-6 text-one-liner margin-bottom text-height-large">
|
||||
|
@ -147,7 +147,7 @@ $scopes = $this->getParam('scopes', []);
|
|||
<label for="name">Name</label>
|
||||
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" />
|
||||
|
||||
<label for="scopes">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank">Learn more</a>)</label>
|
||||
<label for="scopes">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<div class="row responsive thin">
|
||||
<?php foreach ($scopes as $i => $scope) : ?>
|
||||
<div class="col span-6 text-one-liner margin-bottom text-height-large">
|
||||
|
|
|
@ -55,7 +55,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
|||
<label for="logo">Project Logo</label>
|
||||
|
||||
<div class="text-align-center clear">
|
||||
<input type="hidden" name="logo" data-ls-bind="{{console-project.logo}}" data-read="<?php echo $this->escape(json_encode(['*'])); ?>" data-write="<?php echo $this->escape(json_encode(['team:{{console-project.teamId}}'])); ?>" data-accept="image/*" data-forms-upload="" data-label-button="Upload" data-scope="console" data-default="">
|
||||
<input type="hidden" name="logo" data-ls-bind="{{console-project.logo}}" data-read="<?php echo $this->escape(json_encode(['*'])); ?>" data-write="<?php echo $this->escape(json_encode(['team:{{console-project.teamId}}'])); ?>" data-accept="image/*" data-forms-upload="" data-label-button="Upload" data-preview-alt="Project Logo" data-scope="console" data-default="">
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
|
|
@ -43,11 +43,11 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
|
||||
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
|
@ -143,11 +143,11 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
|||
</div>
|
||||
<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>
|
||||
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">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" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
|
||||
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||
<input type="hidden" data-ls-attrs="id=file-write-{{file.$id}}" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$permissions.write}}" placeholder="User ID, Team ID or Role" />
|
||||
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
|
||||
</form>
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="margin-bottom toggle" data-ls-ui-open>
|
||||
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
|
@ -287,7 +287,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="margin-bottom toggle" data-ls-ui-open>
|
||||
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ $events = array_keys($this->getParam('events', []));
|
|||
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
|
||||
<input type="url" class="full-width" data-ls-attrs="id=url-{{webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{webhook.url}}" />
|
||||
|
||||
<div class="margin-bottom toggle" data-ls-ui-open>
|
||||
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
|
@ -187,7 +187,7 @@ $events = array_keys($this->getParam('events', []));
|
|||
<label for="url">POST URL</label>
|
||||
<input type="url" class="full-width" id="url" name="url" required autocomplete="off" placeholder="https://example.com/callback" />
|
||||
|
||||
<div class="margin-bottom toggle" data-ls-ui-open>
|
||||
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
|
||||
<i class="icon-plus pull-end margin-top-tiny"></i>
|
||||
<i class="icon-minus pull-end margin-top-tiny"></i>
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="pull-start margin-end-small margin-bottom">
|
||||
<input type="checkbox" required />
|
||||
</div>
|
||||
By signing up, you agree to the <a data-ls-attrs="href={{env.HOME}}/policy/terms" tabindex="-1" target="_blank">Terms and Conditions</a> and <a data-ls-attrs="href={{env.HOME}}/policy/privacy" target="_blank" tabindex="-1">Privacy Policy</a>
|
||||
By signing up, you agree to the <a data-ls-attrs="href={{env.HOME}}/policy/terms" tabindex="-1" target="_blank" rel="noopener">Terms and Conditions</a> and <a data-ls-attrs="href={{env.HOME}}/policy/privacy" target="_blank" tabindex="-1" rel="noopener">Privacy Policy</a>
|
||||
</div>
|
||||
|
||||
<button type="submit">Sign Up</button>
|
||||
|
|
48
app/workers/mails.php
Normal file
48
app/workers/mails.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/../init.php';
|
||||
|
||||
cli_set_process_title('Mails V1 Worker');
|
||||
|
||||
echo APP_NAME.' mails worker v1 has started';
|
||||
|
||||
class MailsV1
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $args = [];
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
public function perform()
|
||||
{
|
||||
global $register;
|
||||
|
||||
$event = $this->args['event'];
|
||||
$recipient = $this->args['recipient'];
|
||||
$name = $this->args['name'];
|
||||
$subject = $this->args['subject'];
|
||||
$body = $this->args['body'];
|
||||
|
||||
$mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
|
||||
|
||||
$mail->addAddress($recipient, $name);
|
||||
$mail->Subject = $subject;
|
||||
$mail->Body = $body;
|
||||
$mail->AltBody = strip_tags($body);
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
} catch (\Exception $error) {
|
||||
throw new Exception('Error sending mail: ' . $error->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
// ... Remove environment for this job
|
||||
}
|
||||
}
|
|
@ -46,6 +46,16 @@ http {
|
|||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
|
||||
|
||||
# Brotli Settings
|
||||
brotli on;
|
||||
brotli_comp_level 5;
|
||||
brotli_static on;
|
||||
brotli_types application/atom+xml application/javascript application/json application/rss+xml
|
||||
application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
|
||||
application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
|
||||
font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
|
||||
image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
|
||||
|
||||
# Virtual Host Configs
|
||||
server {
|
||||
listen 80; ## listen for ipv4; this line is default and implied
|
||||
|
|
|
@ -65,6 +65,23 @@ stdout_logfile_maxbytes=5000000
|
|||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes = 0
|
||||
|
||||
[program:v1-mails]
|
||||
command=php /usr/share/nginx/html/vendor/bin/resque
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=10
|
||||
environment=QUEUE='v1-mails',APP_INCLUDE='/usr/share/nginx/html/app/workers/mails.php',REDIS_BACKEND='%(ENV__APP_REDIS_HOST)s:%(ENV__APP_REDIS_PORT)s'
|
||||
stdout_events_enabled=true
|
||||
stderr_events_enabled=true
|
||||
stopsignal=QUIT
|
||||
startretries=10
|
||||
;stdout_logfile=/dev/stdout
|
||||
;stdout_logfile_maxbytes=0
|
||||
stdout_logfile=/var/log/appwrite.log
|
||||
stdout_logfile_maxbytes=5000000
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes = 0
|
||||
|
||||
[program:v1-audits]
|
||||
command=php /usr/share/nginx/html/vendor/bin/resque
|
||||
autostart=true
|
||||
|
|
7
public/dist/scripts/app-all.js
vendored
7
public/dist/scripts/app-all.js
vendored
|
@ -2639,11 +2639,11 @@ tag.className="tag";tag.textContent=value;tag.addEventListener("click",function(
|
|||
if(element.required&&array.length===0){add.setCustomValidity("Please add permissions");}else{add.setCustomValidity("");}};tags.className="tags";preview.className="tags-list";add.type="text";add.className="add";add.placeholder=element.placeholder;tags.addEventListener("click",function(){add.focus();});add.addEventListener("keydown",listen);add.addEventListener("blur",function(event){if(add.value!==''){array.push(add.value);add.value="";element.value=JSON.stringify(array);check();}});tags.appendChild(preview);tags.appendChild(add);element.parentNode.insertBefore(tags,element);element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-count",controller:function(element){var counter=document.createElement("div");counter.className="counter";element.parentNode.insertBefore(counter,element.nextSibling);var count=function(){if(0<=element.maxLength){counter.innerText=(element.maxLength-element.value.length).toString()+" / "+
|
||||
element.maxLength;}else{var words=element.value!==""?element.value.trim().split(" ").length:0;counter.innerText=words+" words and "+element.value.length.toString()+" chars";}};element.addEventListener("keyup",count);element.addEventListener("change",count);element.addEventListener("cut",count);element.addEventListener("paste",count);element.addEventListener("drop",count);count();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-direction",controller:function(element,rtl){var setDirection=function(){var value=element.value[0]?element.value:"";var direction="ltr";var align="left";if(rtl.isRTL(value)){direction="rtl";align="right";}
|
||||
element.style.direction=direction;element.style.textAlign=align;};element.addEventListener("keyup",setDirection);element.addEventListener("change",setDirection);element.addEventListener("cut",setDirection);element.addEventListener("paste",setDirection);element.addEventListener("drop",setDirection);setDirection();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-resize",controller:function(element,window){function resize(){var scrollLeft=window.pageXOffset||(window.document.documentElement||window.document.body.parentNode||window.document.body).scrollLeft;var scrollTop=window.pageYOffset||(window.document.documentElement||window.document.body.parentNode||window.document.body).scrollTop;var offset=element.offsetHeight-element.clientHeight;element.style.height="auto";element.style.height=element.scrollHeight+offset+"px";window.scrollTo(scrollLeft,scrollTop);}
|
||||
element.addEventListener("keyup",resize);element.addEventListener("change",resize);element.addEventListener("cut",resize);element.addEventListener("paste",resize);element.addEventListener("drop",resize);window.addEventListener("resize",resize);resize();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-upload",controller:function(element,container,alerts,expression,env,search){var scope=element.dataset["scope"];var project=expression.parse(element.dataset["project"]||"console");var labelButton=element.dataset["labelButton"]||"Upload";var labelLoading=element.dataset["labelLoading"]||"Uploading...";var previewWidth=element.dataset["previewWidth"]||200;var previewHeight=element.dataset["previewHeight"]||200;var accept=element.dataset["accept"]||"";var searchButton=(element.dataset["search"]||0);var required=element.dataset["required"]||false;var className=element.dataset["class"]||"upload";var max=parseInt(element.dataset["max"]||4);var sdk=scope==="sdk"?container.get("sdk"):container.get("console");var output=element.value||null;var wrapper=document.createElement("div");var input=document.createElement("input");var upload=document.createElement("div");var preview=document.createElement("ul");var progress=document.createElement("div");var count=document.createElement("div");wrapper.className=className;input.type="file";input.accept=accept;input.required=required;input.tabIndex=-1;count.className="count";upload.className="button reverse margin-bottom-small";upload.innerHTML='<i class="icon icon-upload"></i> '+labelButton;upload.tabIndex=0;preview.className="preview";progress.className="progress";progress.style.width="0%";progress.style.display="none";var onComplete=function(message){alerts.remove(message);input.disabled=false;upload.classList.remove("disabled");progress.style.width="0%";progress.style.display="none";};var render=function(result){preview.innerHTML="";count.innerHTML="0 / "+max;if(!result){return;}
|
||||
element.addEventListener("keyup",resize);element.addEventListener("change",resize);element.addEventListener("cut",resize);element.addEventListener("paste",resize);element.addEventListener("drop",resize);window.addEventListener("resize",resize);resize();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-upload",controller:function(element,container,alerts,expression,env,search){var scope=element.dataset["scope"];var project=expression.parse(element.dataset["project"]||"console");var labelButton=element.dataset["labelButton"]||"Upload";var labelLoading=element.dataset["labelLoading"]||"Uploading...";var previewWidth=element.dataset["previewWidth"]||200;var previewHeight=element.dataset["previewHeight"]||200;var previewAlt=element.dataset["previewAlt"]||200;var accept=element.dataset["accept"]||"";var searchButton=(element.dataset["search"]||0);var required=element.dataset["required"]||false;var className=element.dataset["class"]||"upload";var max=parseInt(element.dataset["max"]||4);var sdk=scope==="sdk"?container.get("sdk"):container.get("console");var output=element.value||null;var wrapper=document.createElement("div");var input=document.createElement("input");var upload=document.createElement("div");var preview=document.createElement("ul");var progress=document.createElement("div");var count=document.createElement("div");wrapper.className=className;input.type="file";input.accept=accept;input.required=required;input.tabIndex=-1;count.className="count";upload.className="button reverse margin-bottom-small";upload.innerHTML='<i class="icon icon-upload"></i> '+labelButton;upload.tabIndex=0;preview.className="preview";progress.className="progress";progress.style.width="0%";progress.style.display="none";var onComplete=function(message){alerts.remove(message);input.disabled=false;upload.classList.remove("disabled");progress.style.width="0%";progress.style.display="none";};var render=function(result){preview.innerHTML="";count.innerHTML="0 / "+max;if(!result){return;}
|
||||
var file=document.createElement("li");var image=document.createElement("img");image.src=image.src=env.API+"/storage/files/"+
|
||||
result+"/preview?width="+
|
||||
previewWidth+"&height="+
|
||||
previewHeight+"&project="+project+"&mode=admin";file.className="file avatar";file.tabIndex=0;file.appendChild(image);preview.appendChild(file);var remove=(function(result){return function(event){render(result.$id);};})(result);file.addEventListener("click",remove);file.addEventListener("keypress",remove);element.value=result;};input.addEventListener("change",function(){var message=alerts.add({text:labelLoading,class:""},0);var files=input.files;var read=JSON.parse(expression.parse(element.dataset["read"]||"[]"));var write=JSON.parse(expression.parse(element.dataset["write"]||"[]"));sdk.storage.createFile(files[0],read,write,1).then(function(response){onComplete(message);render(response.$id);},function(error){alerts.add({text:"An error occurred!",class:""},3000);onComplete(message);});input.disabled=true;});element.addEventListener("change",function(){if(!element.value){return;}
|
||||
previewHeight+"&project="+project+"&mode=admin";image.alt=previewAlt;file.className="file avatar";file.tabIndex=0;file.appendChild(image);preview.appendChild(file);var remove=(function(result){return function(event){render(result.$id);};})(result);file.addEventListener("click",remove);file.addEventListener("keypress",remove);element.value=result;};input.addEventListener("change",function(){var message=alerts.add({text:labelLoading,class:""},0);var files=input.files;var read=JSON.parse(expression.parse(element.dataset["read"]||"[]"));var write=JSON.parse(expression.parse(element.dataset["write"]||"[]"));sdk.storage.createFile(files[0],read,write,1).then(function(response){onComplete(message);render(response.$id);},function(error){alerts.add({text:"An error occurred!",class:""},3000);onComplete(message);});input.disabled=true;});element.addEventListener("change",function(){if(!element.value){return;}
|
||||
render(element.value);wrapper.scrollIntoView();});upload.addEventListener("keypress",function(){input.click();});element.parentNode.insertBefore(wrapper,element);wrapper.appendChild(preview);wrapper.appendChild(progress);wrapper.appendChild(upload);upload.appendChild(input);render(output);if(searchButton){let searchOpen=document.createElement("button");searchOpen.type='button';searchOpen.innerHTML='<i class="icon icon-search"></i> Search';searchOpen.classList.add('reverse');let path=container.scope(searchButton);searchOpen.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent("open-file-serach",{bubbles:false,cancelable:true}));});wrapper.appendChild(searchOpen);}}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-cookies",controller:function(element,alerts,cookie,env){if(!cookie.get("cookie-alert")){let text=element.dataset["cookies"]||"";alerts.add({text:text,class:"cookie-alert",link:env.HOME+"/policy/cookies",callback:function(){cookie.set("cookie-alert","true",365*10);}},0);}}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-page-title",repeat:true,controller:function(element,document,expression){document.title=expression.parse(element.getAttribute("data-page-title"))||document.title;}});})(window);(function(window){"use strict";window.ls.view.add({selector:'data-general-scroll-to',repeat:false,controller:function(element,window){let button=window.document.createElement('button');button.className='scroll-to icon-up-dir';button.alt='Back To Top';button.title='Back To Top';button.addEventListener('click',function(){element.scrollIntoView(true,{behavior:'smooth'});button.blur();},false);element.appendChild(button);}});})(window);(function(window){"use strict";window.ls.view.add({selector:'data-general-scroll-direction',repeat:false,controller:function(element,window){let position=0;let check=function(){let direction=window.document.documentElement.scrollTop;if(direction>position){element.classList.remove('scroll-to-top')
|
||||
element.classList.add('scroll-to-bottom')}
|
||||
else{element.classList.remove('scroll-to-bottom')
|
||||
|
@ -2663,7 +2663,8 @@ element.classList.add("modal");if(!buttonAlias&&!buttonHide){buttonElements.forE
|
|||
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
|
||||
if(openEvent){document.addEventListener(openEvent,open);}
|
||||
buttonElements.forEach(button=>{button.addEventListener("click",open);});document.addEventListener("keydown",function(event){if(event.which===27){close();}});element.addEventListener("blur",close);let closeButtons=element.querySelectorAll("[data-ui-modal-close]");for(let i=0;i<closeButtons.length;i++){closeButtons[i].addEventListener("click",close);}
|
||||
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.tabIndex=1;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}
|
||||
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonAria=element.dataset["buttonAria"]||"Open";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}
|
||||
if(buttonAria){button.setAttribute('aria-label',buttonAria);}
|
||||
if(def==="close"){element.classList.add("close");element.classList.remove("open");}else{element.classList.add("open");element.classList.remove("close");}
|
||||
button.addEventListener("click",function(){element.classList.toggle("open");element.classList.toggle("close");});if(hover&&!isTouch()){element.addEventListener("mouseover",function(){element.classList.add("open");element.classList.remove("close");});element.addEventListener("mouseout",function(){element.classList.add("close");element.classList.remove("open");});}
|
||||
let close=function(){element.classList.add("close");element.classList.remove("open");};let closeDelay=function(){window.setTimeout(function(){close();},400);};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
||||
|
|
7
public/dist/scripts/app.js
vendored
7
public/dist/scripts/app.js
vendored
|
@ -353,11 +353,11 @@ tag.className="tag";tag.textContent=value;tag.addEventListener("click",function(
|
|||
if(element.required&&array.length===0){add.setCustomValidity("Please add permissions");}else{add.setCustomValidity("");}};tags.className="tags";preview.className="tags-list";add.type="text";add.className="add";add.placeholder=element.placeholder;tags.addEventListener("click",function(){add.focus();});add.addEventListener("keydown",listen);add.addEventListener("blur",function(event){if(add.value!==''){array.push(add.value);add.value="";element.value=JSON.stringify(array);check();}});tags.appendChild(preview);tags.appendChild(add);element.parentNode.insertBefore(tags,element);element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-count",controller:function(element){var counter=document.createElement("div");counter.className="counter";element.parentNode.insertBefore(counter,element.nextSibling);var count=function(){if(0<=element.maxLength){counter.innerText=(element.maxLength-element.value.length).toString()+" / "+
|
||||
element.maxLength;}else{var words=element.value!==""?element.value.trim().split(" ").length:0;counter.innerText=words+" words and "+element.value.length.toString()+" chars";}};element.addEventListener("keyup",count);element.addEventListener("change",count);element.addEventListener("cut",count);element.addEventListener("paste",count);element.addEventListener("drop",count);count();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-direction",controller:function(element,rtl){var setDirection=function(){var value=element.value[0]?element.value:"";var direction="ltr";var align="left";if(rtl.isRTL(value)){direction="rtl";align="right";}
|
||||
element.style.direction=direction;element.style.textAlign=align;};element.addEventListener("keyup",setDirection);element.addEventListener("change",setDirection);element.addEventListener("cut",setDirection);element.addEventListener("paste",setDirection);element.addEventListener("drop",setDirection);setDirection();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-text-resize",controller:function(element,window){function resize(){var scrollLeft=window.pageXOffset||(window.document.documentElement||window.document.body.parentNode||window.document.body).scrollLeft;var scrollTop=window.pageYOffset||(window.document.documentElement||window.document.body.parentNode||window.document.body).scrollTop;var offset=element.offsetHeight-element.clientHeight;element.style.height="auto";element.style.height=element.scrollHeight+offset+"px";window.scrollTo(scrollLeft,scrollTop);}
|
||||
element.addEventListener("keyup",resize);element.addEventListener("change",resize);element.addEventListener("cut",resize);element.addEventListener("paste",resize);element.addEventListener("drop",resize);window.addEventListener("resize",resize);resize();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-upload",controller:function(element,container,alerts,expression,env,search){var scope=element.dataset["scope"];var project=expression.parse(element.dataset["project"]||"console");var labelButton=element.dataset["labelButton"]||"Upload";var labelLoading=element.dataset["labelLoading"]||"Uploading...";var previewWidth=element.dataset["previewWidth"]||200;var previewHeight=element.dataset["previewHeight"]||200;var accept=element.dataset["accept"]||"";var searchButton=(element.dataset["search"]||0);var required=element.dataset["required"]||false;var className=element.dataset["class"]||"upload";var max=parseInt(element.dataset["max"]||4);var sdk=scope==="sdk"?container.get("sdk"):container.get("console");var output=element.value||null;var wrapper=document.createElement("div");var input=document.createElement("input");var upload=document.createElement("div");var preview=document.createElement("ul");var progress=document.createElement("div");var count=document.createElement("div");wrapper.className=className;input.type="file";input.accept=accept;input.required=required;input.tabIndex=-1;count.className="count";upload.className="button reverse margin-bottom-small";upload.innerHTML='<i class="icon icon-upload"></i> '+labelButton;upload.tabIndex=0;preview.className="preview";progress.className="progress";progress.style.width="0%";progress.style.display="none";var onComplete=function(message){alerts.remove(message);input.disabled=false;upload.classList.remove("disabled");progress.style.width="0%";progress.style.display="none";};var render=function(result){preview.innerHTML="";count.innerHTML="0 / "+max;if(!result){return;}
|
||||
element.addEventListener("keyup",resize);element.addEventListener("change",resize);element.addEventListener("cut",resize);element.addEventListener("paste",resize);element.addEventListener("drop",resize);window.addEventListener("resize",resize);resize();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-upload",controller:function(element,container,alerts,expression,env,search){var scope=element.dataset["scope"];var project=expression.parse(element.dataset["project"]||"console");var labelButton=element.dataset["labelButton"]||"Upload";var labelLoading=element.dataset["labelLoading"]||"Uploading...";var previewWidth=element.dataset["previewWidth"]||200;var previewHeight=element.dataset["previewHeight"]||200;var previewAlt=element.dataset["previewAlt"]||200;var accept=element.dataset["accept"]||"";var searchButton=(element.dataset["search"]||0);var required=element.dataset["required"]||false;var className=element.dataset["class"]||"upload";var max=parseInt(element.dataset["max"]||4);var sdk=scope==="sdk"?container.get("sdk"):container.get("console");var output=element.value||null;var wrapper=document.createElement("div");var input=document.createElement("input");var upload=document.createElement("div");var preview=document.createElement("ul");var progress=document.createElement("div");var count=document.createElement("div");wrapper.className=className;input.type="file";input.accept=accept;input.required=required;input.tabIndex=-1;count.className="count";upload.className="button reverse margin-bottom-small";upload.innerHTML='<i class="icon icon-upload"></i> '+labelButton;upload.tabIndex=0;preview.className="preview";progress.className="progress";progress.style.width="0%";progress.style.display="none";var onComplete=function(message){alerts.remove(message);input.disabled=false;upload.classList.remove("disabled");progress.style.width="0%";progress.style.display="none";};var render=function(result){preview.innerHTML="";count.innerHTML="0 / "+max;if(!result){return;}
|
||||
var file=document.createElement("li");var image=document.createElement("img");image.src=image.src=env.API+"/storage/files/"+
|
||||
result+"/preview?width="+
|
||||
previewWidth+"&height="+
|
||||
previewHeight+"&project="+project+"&mode=admin";file.className="file avatar";file.tabIndex=0;file.appendChild(image);preview.appendChild(file);var remove=(function(result){return function(event){render(result.$id);};})(result);file.addEventListener("click",remove);file.addEventListener("keypress",remove);element.value=result;};input.addEventListener("change",function(){var message=alerts.add({text:labelLoading,class:""},0);var files=input.files;var read=JSON.parse(expression.parse(element.dataset["read"]||"[]"));var write=JSON.parse(expression.parse(element.dataset["write"]||"[]"));sdk.storage.createFile(files[0],read,write,1).then(function(response){onComplete(message);render(response.$id);},function(error){alerts.add({text:"An error occurred!",class:""},3000);onComplete(message);});input.disabled=true;});element.addEventListener("change",function(){if(!element.value){return;}
|
||||
previewHeight+"&project="+project+"&mode=admin";image.alt=previewAlt;file.className="file avatar";file.tabIndex=0;file.appendChild(image);preview.appendChild(file);var remove=(function(result){return function(event){render(result.$id);};})(result);file.addEventListener("click",remove);file.addEventListener("keypress",remove);element.value=result;};input.addEventListener("change",function(){var message=alerts.add({text:labelLoading,class:""},0);var files=input.files;var read=JSON.parse(expression.parse(element.dataset["read"]||"[]"));var write=JSON.parse(expression.parse(element.dataset["write"]||"[]"));sdk.storage.createFile(files[0],read,write,1).then(function(response){onComplete(message);render(response.$id);},function(error){alerts.add({text:"An error occurred!",class:""},3000);onComplete(message);});input.disabled=true;});element.addEventListener("change",function(){if(!element.value){return;}
|
||||
render(element.value);wrapper.scrollIntoView();});upload.addEventListener("keypress",function(){input.click();});element.parentNode.insertBefore(wrapper,element);wrapper.appendChild(preview);wrapper.appendChild(progress);wrapper.appendChild(upload);upload.appendChild(input);render(output);if(searchButton){let searchOpen=document.createElement("button");searchOpen.type='button';searchOpen.innerHTML='<i class="icon icon-search"></i> Search';searchOpen.classList.add('reverse');let path=container.scope(searchButton);searchOpen.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent("open-file-serach",{bubbles:false,cancelable:true}));});wrapper.appendChild(searchOpen);}}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-cookies",controller:function(element,alerts,cookie,env){if(!cookie.get("cookie-alert")){let text=element.dataset["cookies"]||"";alerts.add({text:text,class:"cookie-alert",link:env.HOME+"/policy/cookies",callback:function(){cookie.set("cookie-alert","true",365*10);}},0);}}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-page-title",repeat:true,controller:function(element,document,expression){document.title=expression.parse(element.getAttribute("data-page-title"))||document.title;}});})(window);(function(window){"use strict";window.ls.view.add({selector:'data-general-scroll-to',repeat:false,controller:function(element,window){let button=window.document.createElement('button');button.className='scroll-to icon-up-dir';button.alt='Back To Top';button.title='Back To Top';button.addEventListener('click',function(){element.scrollIntoView(true,{behavior:'smooth'});button.blur();},false);element.appendChild(button);}});})(window);(function(window){"use strict";window.ls.view.add({selector:'data-general-scroll-direction',repeat:false,controller:function(element,window){let position=0;let check=function(){let direction=window.document.documentElement.scrollTop;if(direction>position){element.classList.remove('scroll-to-top')
|
||||
element.classList.add('scroll-to-bottom')}
|
||||
else{element.classList.remove('scroll-to-bottom')
|
||||
|
@ -377,7 +377,8 @@ element.classList.add("modal");if(!buttonAlias&&!buttonHide){buttonElements.forE
|
|||
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
|
||||
if(openEvent){document.addEventListener(openEvent,open);}
|
||||
buttonElements.forEach(button=>{button.addEventListener("click",open);});document.addEventListener("keydown",function(event){if(event.which===27){close();}});element.addEventListener("blur",close);let closeButtons=element.querySelectorAll("[data-ui-modal-close]");for(let i=0;i<closeButtons.length;i++){closeButtons[i].addEventListener("click",close);}
|
||||
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.tabIndex=1;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}
|
||||
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonAria=element.dataset["buttonAria"]||"Open";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}
|
||||
if(buttonAria){button.setAttribute('aria-label',buttonAria);}
|
||||
if(def==="close"){element.classList.add("close");element.classList.remove("open");}else{element.classList.add("open");element.classList.remove("close");}
|
||||
button.addEventListener("click",function(){element.classList.toggle("open");element.classList.toggle("close");});if(hover&&!isTouch()){element.addEventListener("mouseover",function(){element.classList.add("open");element.classList.remove("close");});element.addEventListener("mouseout",function(){element.classList.add("close");element.classList.remove("open");});}
|
||||
let close=function(){element.classList.add("close");element.classList.remove("open");};let closeDelay=function(){window.setTimeout(function(){close();},400);};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}
|
||||
|
|
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
|
@ -10,6 +10,7 @@
|
|||
var labelLoading = element.dataset["labelLoading"] || "Uploading...";
|
||||
var previewWidth = element.dataset["previewWidth"] || 200;
|
||||
var previewHeight = element.dataset["previewHeight"] || 200;
|
||||
var previewAlt = element.dataset["previewAlt"] || 200;
|
||||
var accept = element.dataset["accept"] || "";
|
||||
var searchButton = (element.dataset["search"] || 0);
|
||||
var required = element.dataset["required"] || false;
|
||||
|
@ -76,6 +77,8 @@
|
|||
"&project="+project +
|
||||
"&mode=admin";
|
||||
|
||||
image.alt = previewAlt;
|
||||
|
||||
file.className = "file avatar";
|
||||
file.tabIndex = 0;
|
||||
file.appendChild(image);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
let buttonClass = element.dataset["buttonClass"] || "ls-ui-open";
|
||||
let buttonText = element.dataset["buttonText"] || "";
|
||||
let buttonIcon = element.dataset["buttonIcon"] || "";
|
||||
let buttonAria = element.dataset["buttonAria"] || "Open";
|
||||
let buttonSelector = element.dataset["buttonSelector"] || "";
|
||||
let hover = element.hasAttribute("data-hover");
|
||||
let blur = element.hasAttribute("data-blur");
|
||||
|
@ -19,7 +20,7 @@
|
|||
|
||||
button.innerText = buttonText;
|
||||
button.className = buttonClass;
|
||||
button.tabIndex = 1;
|
||||
// button.tabIndex = 1;
|
||||
button.type = "button";
|
||||
|
||||
if (buttonIcon) {
|
||||
|
@ -30,6 +31,10 @@
|
|||
button.insertBefore(icon, button.firstChild);
|
||||
}
|
||||
|
||||
if(buttonAria) {
|
||||
button.setAttribute('aria-label', buttonAria);
|
||||
}
|
||||
|
||||
if (def === "close") {
|
||||
element.classList.add("close");
|
||||
element.classList.remove("open");
|
||||
|
|
|
@ -553,6 +553,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.community {
|
||||
a {
|
||||
padding: 5px 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.link-list {
|
||||
li {
|
||||
margin-bottom: 15px;
|
||||
|
|
|
@ -34,11 +34,15 @@ class Key extends Validator
|
|||
*/
|
||||
public function isValid($value)
|
||||
{
|
||||
if(!is_string($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/[^A-Za-z0-9\-\_]/', $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mb_strlen($value) > 40) {
|
||||
if (mb_strlen($value) > 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ abstract class Scope extends TestCase
|
|||
|
||||
protected function getLastEmail():array
|
||||
{
|
||||
sleep(3);
|
||||
sleep(10);
|
||||
$emails = json_decode(file_get_contents('http://maildev/email'), true);
|
||||
|
||||
if($emails && is_array($emails)) {
|
||||
|
|
36
tests/unit/Database/Validator/KeyTest.php
Normal file
36
tests/unit/Database/Validator/KeyTest.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
|
||||
use Appwrite\Database\Validator\Key;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class KeyTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Key
|
||||
*/
|
||||
protected $object = null;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->object = new Key();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
{
|
||||
$this->assertEquals($this->object->isValid('dasda asdasd'), false);
|
||||
$this->assertEquals($this->object->isValid('asdasdasdas'), true);
|
||||
$this->assertEquals($this->object->isValid('as$$5dasdasdas'), false);
|
||||
$this->assertEquals($this->object->isValid(false), false);
|
||||
$this->assertEquals($this->object->isValid(null), false);
|
||||
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscribers'), false);
|
||||
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscriber'), false);
|
||||
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscribe'), true);
|
||||
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscrib'), true);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue