Merge branch 'feat-sb-uis' into feat-s3-integration

This commit is contained in:
Damodar Lohani 2021-11-19 15:37:28 +05:45
commit a3d7b5f60b
19 changed files with 16493 additions and 17673 deletions

View file

@ -37,6 +37,7 @@ body:
label: "🎲 Appwrite version"
description: "What version of Appwrite are you running?"
options:
- Version 0.11.x
- Version 0.10.x
- Version 0.9.x
- Version 0.8.x

View file

@ -102,7 +102,6 @@ Getting started with Appwrite is as easy as creating a new project, choosing you
* [Getting Started for Android](https://appwrite.io/docs/getting-started-for-android)
* [Getting Started for Server](https://appwrite.io/docs/getting-started-for-server)
* [Getting Started for CLI](https://appwrite.io/docs/command-line)
* Getting Started for iOS (Coming soon...)
### Services
@ -139,8 +138,9 @@ Below is a list of currently supported platforms and languages. If you wish to h
* ✅   [.NET](https://github.com/appwrite/sdk-for-dotnet) - **Experimental** (Maintained by the Appwrite Team)
#### Community
* ✅   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/))
* ✅   [Appcelerator Titanium](https://github.com/m1ga/ti.appwrite) (Maintained by [Michael Gangolf](https://github.com/m1ga/))
* ✅   [Godot Engine](https://github.com/GodotNuts/appwrite-sdk) (Maintained by [fenix-hub @GodotNuts](https://github.com/fenix-hub))
Looking for more SDKs? - Help us by contributing a pull request to our [SDK Generator](https://github.com/appwrite/sdk-generator)!
## Contributing

View file

@ -15,7 +15,7 @@ return [
[
'key' => 'web',
'name' => 'Web',
'version' => '4.0.4',
'version' => '5.0.0',
'url' => 'https://github.com/appwrite/sdk-for-web',
'package' => 'https://www.npmjs.com/package/appwrite',
'enabled' => true,
@ -190,7 +190,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '2.5.1',
'version' => '3.0.0',
'url' => 'https://github.com/appwrite/sdk-for-node',
'package' => 'https://www.npmjs.com/package/node-appwrite',
'enabled' => true,
@ -208,11 +208,11 @@ return [
[
'key' => 'deno',
'name' => 'Deno',
'version' => '0.4.1',
'version' => '1.0.0',
'url' => 'https://github.com/appwrite/sdk-for-deno',
'package' => 'https://deno.land/x/appwrite',
'enabled' => true,
'beta' => true,
'beta' => false,
'dev' => false,
'hidden' => false,
'family' => APP_PLATFORM_SERVER,

View file

@ -46,9 +46,20 @@ App::get('/v1/health/db')
->action(function ($response, $utopia) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\App $utopia */
$utopia->getResource('db');
try {
$db = $utopia->getResource('db'); /* @var $db PDO */
$response->json(['status' => 'OK']);
// Run a small test to check the connection
$statement = $db->prepare("SELECT 1;");
$statement->closeCursor();
$statement->execute();
} catch (Exception $_e) {
throw new Exception('Database is not available', 500);
}
return $response->json(['status' => 'OK']);
});
App::get('/v1/health/cache')
@ -64,9 +75,14 @@ App::get('/v1/health/cache')
->action(function ($response, $utopia) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\App $utopia */
$utopia->getResource('cache');
/** @var Redis */
$redis = $utopia->getResource('cache');
$response->json(['status' => 'OK']);
if ($redis->ping(true)) {
return $response->json(['status' => 'OK']);
} else {
throw new Exception('Cache is not available', 500);
}
});
App::get('/v1/health/time')

View file

@ -234,29 +234,74 @@ App::post('/v1/mock/tests/general/upload')
->param('z', null, new ArrayList(new Text(256)), 'Sample array param')
->param('file', [], new File(), 'Sample file param', false)
->inject('request')
->action(function ($x, $y, $z, $file, $request) {
->inject('response')
->action(function ($x, $y, $z, $file, $request, $response) {
/** @var Utopia\Swoole\Request $request */
/** @var Utopia\Swoole\Response $response */
$file = $request->getFiles('file');
$file['tmp_name'] = (\is_array($file['tmp_name'])) ? $file['tmp_name'] : [$file['tmp_name']];
$file['name'] = (\is_array($file['name'])) ? $file['name'] : [$file['name']];
$file['size'] = (\is_array($file['size'])) ? $file['size'] : [$file['size']];
$contentRange = $request->getHeader('content-range');
if(!empty($contentRange)) {
$start = $request->getContentRangeStart();
$end = $request->getContentRangeEnd();
$size = $request->getContentRangeSize();
$id = $request->getHeader('x-appwrite-id', '');
$file['size'] = (\is_array($file['size'])) ? $file['size'] : [$file['size']];
foreach ($file['name'] as $i => $name) {
if ($name !== 'file.png') {
throw new Exception('Wrong file name', 400);
if(is_null($start) || is_null($end) || is_null($size)) {
throw new Exception('Invalid content-range header', 400);
}
}
foreach ($file['size'] as $i => $size) {
if ($size !== 38756) {
throw new Exception('Wrong file size', 400);
if($start > $end || $end > $size) {
throw new Exception('Invalid content-range header', 400);
}
}
foreach ($file['tmp_name'] as $i => $tmpName) {
if (\md5(\file_get_contents($tmpName)) !== 'd80e7e6999a3eb2ae0d631a96fe135a4') {
throw new Exception('Wrong file uploaded', 400);
if($start === 0 && !empty($id)) {
throw new Exception('First chunked request cannot have id header', 400);
}
if($start !== 0 && $id !== 'newfileid') {
throw new Exception('All chunked request must have id header (except first)', 400);
}
if($end !== $size && $end-$start+1 !== 5*1024*1024) {
throw new Exception('Chunk size must be 5MB (except last chunk)', 400);
}
foreach ($file['size'] as $i => $sz) {
if ($end !== $size && $sz !== 5*1024*1024) {
throw new Exception('Wrong chunk size', 400);
}
if($sz > 5*1024*1024) {
throw new Exception('Chunk size must be 5MB or less', 400);
}
}
if($end !== $size) {
$response->json(['$id'=> 'newfileid']);
}
} else {
$file['tmp_name'] = (\is_array($file['tmp_name'])) ? $file['tmp_name'] : [$file['tmp_name']];
$file['name'] = (\is_array($file['name'])) ? $file['name'] : [$file['name']];
$file['size'] = (\is_array($file['size'])) ? $file['size'] : [$file['size']];
foreach ($file['name'] as $i => $name) {
if ($name !== 'file.png') {
throw new Exception('Wrong file name', 400);
}
}
foreach ($file['size'] as $i => $size) {
if ($size !== 38756) {
throw new Exception('Wrong file size', 400);
}
}
foreach ($file['tmp_name'] as $i => $tmpName) {
if (\md5(\file_get_contents($tmpName)) !== 'd80e7e6999a3eb2ae0d631a96fe135a4') {
throw new Exception('Wrong file uploaded', 400);
}
}
}
});

View file

@ -330,9 +330,9 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<h2>Usage</h2>
<h3 class="margin-bottom-tiny">Objects</h3>
<p class="text-fade">Count of files over time</p>
<div data-service="storage.getBucketUsage" data-event="load" data-name="usage" data-param-bucket-id="{{router.params.id}}">
<h3 class="margin-bottom-tiny">Files</h3>
<p class="text-fade">Count of files over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
@ -345,7 +345,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<li>Files <span data-ls-bind="({{usage.filesCount|statsGetLast|statsTotal}})"></span></li>
</ul>
<h3 class="margin-bottom-tiny">Files</h3>
<h3 class="margin-bottom-tiny">Operations</h3>
<p class="text-fade">Count of files create, read, update and delete operations over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
@ -356,10 +356,10 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
</div>
<ul class="chart-notes crud margin-bottom-large">
<li class="green">Create <span data-ls-bind="({{usage.filesCreate|statsGetLast|statsTotal}})"></span></li>
<li class="green">Read <span data-ls-bind="({{usage.filesRead|statsGetLast|statsTotal}})"></span></li>
<li class="green">Update <span data-ls-bind="({{usage.filesUpdate|statsGetLast|statsTotal}})"></span></li>
<li class="green">Delete <span data-ls-bind="({{usage.filesDelete|statsGetLast|statsTotal}})"></span></li>
<li>Create <span data-ls-bind="({{usage.filesCreate|statsGetLast|statsTotal}})"></span></li>
<li>Read <span data-ls-bind="({{usage.filesRead|statsGetLast|statsTotal}})"></span></li>
<li>Update <span data-ls-bind="({{usage.filesUpdate|statsGetLast|statsTotal}})"></span></li>
<li>Delete <span data-ls-bind="({{usage.filesDelete|statsGetLast|statsTotal}})"></span></li>
</ul>
</div>
</li>

View file

@ -18,7 +18,7 @@
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset="{{router.params.offset}}"
data-param-order-type="ASC"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-buckets">
@ -160,7 +160,7 @@
<div class="box">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-show-y-axis="true" data-forms-chart="Total Files=filesCount,Total Buckets=bucketsCount"/>
<input type="hidden" data-ls-bind="{{usage}}" data-show-y-axis="true" data-forms-chart="Total Files=filesCount,Total Buckets=bucketsCount" data-height="140" />
</div>
</div>
</div>

View file

@ -80,7 +80,7 @@
}
],
"require-dev": {
"appwrite/sdk-generator": "0.16.0",
"appwrite/sdk-generator": "0.16.2",
"phpunit/phpunit": "9.5.6",
"swoole/ide-helper": "4.6.7",
"textalk/websocket": "1.5.2",

14
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bd77c6854e858381edef57388096a498",
"content-hash": "d2f722e3c9fb35f72fba310543755c76",
"packages": [
{
"name": "adhocore/jwt",
@ -2986,16 +2986,16 @@
},
{
"name": "appwrite/sdk-generator",
"version": "0.16.0",
"version": "0.16.2",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "5a57afe89ded393a3eca8d9ba96b8e2c479f2601"
"reference": "e3a20c96a745a9c4aa048fd344650fcfbf41cf6f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5a57afe89ded393a3eca8d9ba96b8e2c479f2601",
"reference": "5a57afe89ded393a3eca8d9ba96b8e2c479f2601",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e3a20c96a745a9c4aa048fd344650fcfbf41cf6f",
"reference": "e3a20c96a745a9c4aa048fd344650fcfbf41cf6f",
"shasum": ""
},
"require": {
@ -3029,9 +3029,9 @@
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.16.0"
"source": "https://github.com/appwrite/sdk-generator/tree/0.16.2"
},
"time": "2021-10-21T06:49:55+00:00"
"time": "2021-11-12T11:09:38+00:00"
},
{
"name": "composer/semver",

View file

@ -12,7 +12,6 @@ client
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
;
```
### Make your first request
@ -22,13 +21,8 @@ Once your SDK object is set, create any of the Appwrite service objects and choo
```typescript
let users = new sdk.Users(client);
let promise = users.create('email@example.com', 'password');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
let response = await users.create('email@example.com', 'password');
console.log(response);
```
### Full Example
@ -45,13 +39,8 @@ client
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
;
let promise = users.create('email@example.com', 'password');
promise.then(function (response) {
console.log(response);
}, function (error) {
console.log(error);
});
let response = await users.create('email@example.com', 'password');
console.log(response);
```
### Error Handling
@ -61,7 +50,7 @@ The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` a
let users = new sdk.Users(client);
try {
let res = await users.create('email@example.com', 'password');
let response = await users.create('email@example.com', 'password');
} catch(e) {
console.log(e.message);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -374,8 +374,10 @@ button.addEventListener("click",function(){var clone=document.createElement(elem
clone.innerHTML=template;clone.className=element.className;var input=clone.querySelector("input, select, textarea");view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
if(input){input.focus();}
Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);button.form.addEventListener('reset',function(event){target.innerHTML='';if(first){button.click();}});if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-chart",controller:function(element,container,date,document){let wrapper=document.createElement("div");let child=document.createElement("canvas");let sources=element.getAttribute('data-forms-chart');let width=element.getAttribute('data-width')||500;let height=element.getAttribute('data-height')||175;let showXAxis=element.getAttribute('data-show-x-axis')||false;let showYAxis=element.getAttribute('data-show-y-axis')||false;let colors=(element.getAttribute('data-colors')||'blue,green,orange,red').split(',');let themes={'blue':'#29b5d9','green':'#4eb55b','orange':'#fba233','red':'#dc3232','create':'#00b680','read':'#009cde','update':'#696fd7','delete':'#da5d95',};let range={'24h':'H:i','7d':'d F Y','30d':'d F Y','90d':'d F Y'}
element.parentNode.insertBefore(wrapper,element.nextSibling);wrapper.classList.add('content');child.width=width;child.height=height;sources=sources.split(',');wrapper.appendChild(child);let chart=null;let check=function(){let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:showXAxis}],yAxes:[{display:showYAxis,ticks:{fontColor:"#8f8f8f"}}]}}};for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let usage=container.get('usage');let data=usage[path];let value=JSON.parse(element.value);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=themes[colors[i]];config.data.datasets[i].backgroundColor=themes[colors[i]]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
let dateFormat=(value.range&&range[value.range])?range[value.range]:'d F Y';for(let x=0;x<data.length;x++){config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format(dateFormat,data[x].date);}}
let ticksCount=5;element.parentNode.insertBefore(wrapper,element.nextSibling);wrapper.classList.add('content');child.width=width;child.height=height;sources=sources.split(',');wrapper.appendChild(child);let chart=null;let check=function(){let config={type:"line",data:{labels:[],datasets:[]},options:{responsive:true,hover:{mode:"nearest",intersect:true},scales:{x:{display:showXAxis},y:{display:showYAxis,min:0,ticks:{count:ticksCount,},}},plugins:{title:{display:false,text:"Stats"},legend:{display:false},tooltip:{mode:"index",intersect:false,caretPadding:0},}}};let highest=0;for(let i=0;i<sources.length;i++){let label=sources[i].substring(0,sources[i].indexOf('='));let path=sources[i].substring(sources[i].indexOf('=')+1);let usage=container.get('usage');let data=usage[path];let value=JSON.parse(element.value);config.data.labels[i]=label;config.data.datasets[i]={};config.data.datasets[i].label=label;config.data.datasets[i].borderColor=themes[colors[i]];config.data.datasets[i].backgroundColor=themes[colors[i]]+'36';config.data.datasets[i].borderWidth=2;config.data.datasets[i].data=[0,0,0,0,0,0,0];config.data.datasets[i].fill=true;if(!data){return;}
let dateFormat=(value.range&&range[value.range])?range[value.range]:'d F Y';for(let x=0;x<data.length;x++){if(data[x].value>highest){highest=data[x].value;}
config.data.datasets[i].data[x]=data[x].value;config.data.labels[x]=date.format(dateFormat,data[x].date);}}
if(highest==0){config.options.scales.y.ticks.stepSize=1;config.options.scales.y.max=ticksCount;}else{highest=Math.ceil(highest/ticksCount)*ticksCount;config.options.scales.y.ticks.stepSize=highest/ticksCount;config.options.scales.y.max=highest;}
if(chart){chart.destroy();}
else{}
chart=new Chart(child.getContext("2d"),config);wrapper.dataset["canvas"]=true;}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
let colors = (element.getAttribute('data-colors') || 'blue,green,orange,red').split(',');
let themes = {'blue': '#29b5d9', 'green': '#4eb55b', 'orange': '#fba233', 'red': '#dc3232', 'create': '#00b680', 'read': '#009cde', 'update': '#696fd7', 'delete': '#da5d95',};
let range = {'24h': 'H:i', '7d': 'd F Y', '30d': 'd F Y', '90d': 'd F Y'}
let ticksCount = 5;
element.parentNode.insertBefore(wrapper, element.nextSibling);
@ -38,40 +39,40 @@
},
options: {
responsive: true,
title: {
display: false,
text: "Stats"
},
legend: {
display: false
},
tooltips: {
mode: "index",
intersect: false,
caretPadding: 0
},
hover: {
mode: "nearest",
intersect: true
},
scales: {
xAxes: [
{
display: showXAxis
}
],
yAxes: [
{
display: showYAxis,
ticks: {
fontColor: "#8f8f8f"
}
}
]
x: {
display: showXAxis
},
y: {
display: showYAxis,
min: 0,
ticks: {
count: ticksCount,
},
}
},
plugins: {
title: {
display: false,
text: "Stats"
},
legend: {
display: false
},
tooltip: {
mode: "index",
intersect: false,
caretPadding: 0
},
}
}
};
let highest = 0;
for (let i = 0; i < sources.length; i++) {
let label = sources[i].substring(0, sources[i].indexOf('='));
let path = sources[i].substring(sources[i].indexOf('=') + 1);
@ -95,10 +96,23 @@
let dateFormat = (value.range && range[value.range]) ? range[value.range] : 'd F Y';
for (let x = 0; x < data.length; x++) {
if(data[x].value > highest) {
highest = data[x].value;
}
config.data.datasets[i].data[x] = data[x].value;
config.data.labels[x] = date.format(dateFormat, data[x].date);
}
}
if(highest == 0) {
config.options.scales.y.ticks.stepSize = 1;
config.options.scales.y.max = ticksCount;
} else {
// ceiling of the highest value
highest = Math.ceil(highest / ticksCount) * ticksCount;
config.options.scales.y.ticks.stepSize = highest / ticksCount;
config.options.scales.y.max = highest;
}
if(chart) {
chart.destroy();

View file

@ -5,6 +5,7 @@
--config-width-large: 700px;
--config-width-medium: 550px;
--config-width-small: 320px;
--config-color-primary: #f02e65;
--config-color-link: #1e849e;
--config-color-background: #eceff1;
--config-color-background-dark: #dfe2e4;
@ -93,6 +94,7 @@
--config-console-nav-switch-arrow: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24'><path fill='%23868686' d='M7.406 7.828l4.594 4.594 4.594-4.594 1.406 1.406-6 6-6-6z'></path></svg>");
.theme-dark {
--config-color-primary: #f02e65;
--config-color-background: #061F2F;
--config-color-background-dark: #262d50;
--config-color-background-fade: #1c223a;