Merge pull request #2816 from appwrite/feat-console-resumable-upload

This commit is contained in:
Damodar Lohani 2022-02-22 13:01:27 +05:45 committed by GitHub
commit f8cea8cc18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 235 additions and 120 deletions

View file

@ -223,20 +223,20 @@
</form>
</div>
<section class="upload-box" x-data x-show="$store.uploader.files.length > 0">
<section class="upload-box" x-data x-show="$store.uploader.files().length > 0">
<div class="upload-box-header">
<h4 class="upload-box-title">
<span class="text">Uploading files</span>
<span class="amount" x-text="$store.uploader.files.length"></span>
<span class="amount" x-text="$store.uploader.files().length"></span>
</h4>
<button class="icon-button" :class="$store.uploader.isOpen ? '' : 'is-open'" aria-label="toggle upload box" @click="$store.uploader.toggle()"><span class="icon-chevron-down" aria-hidden="true"></span></button>
<button class="icon-button" aria-label="close upload box"><span class="icon-x" aria-hidden="true"></span></button>
<button class="icon-button" @click="$store.uploader.cancelAll()" aria-label="close upload box"><span class="icon-x" aria-hidden="true"></span></button>
</div>
<div class="upload-box-content" :class="$store.uploader.isOpen ? 'is-open' : ''">
<ul class="upload-box-list">
<template x-if="$store.uploader.files.length > 0">
<template x-for="file in $store.uploader.files" :key="file.id">
<li class="upload-box-item">
<template x-if="$store.uploader.files().length > 0">
<template x-for="file in $store.uploader.files()" :key="file.id">
<li x-show="!file.cancelled" class="upload-box-item">
<div class="upload-image u-margin-inline-end-16" :class="file.completed ? 'is-finished' : ''">
<div class="progress"
:style="'--progress-value:' + file.progress"
@ -244,7 +244,8 @@
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"></div>
<span class="icon" x-text="file.progress"></span>
<span x-show="!file.completed" class="icon" x-text="file.progress + '%'"></span>
<span x-show="file.completed" class="icon icon-file"></span>
</div>
<label for="file1" class="file-name trim-inner-text" x-text="file.name"></label>
<span class="pill is-failed" x-show="file.failed">failed</span>

View file

@ -64,7 +64,8 @@ if(typeof scopes!=='undefined'){payload['scopes']=scopes;}
const uri=new URL(this.config.endpoint+path);payload['project']=this.config.project;for(const[key,value]of Object.entries(this.flatten(payload))){uri.searchParams.append(key,value);}
if(typeof window!=='undefined'&&(window===null||window===void 0?void 0:window.location)){window.location.href=uri.toString();}
else{return uri;}},getSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),deleteSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),deleteSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),createVerification:(url)=>__awaiter(this,void 0,void 0,function*(){if(typeof url==='undefined'){throw new AppwriteException('Missing required parameter: "url"');}
let path='/account/verification';let payload={};if(typeof url!=='undefined'){payload['url']=url;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),updateVerification:(userId,secret)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
@ -304,10 +305,10 @@ if(typeof code==='undefined'){throw new AppwriteException('Missing required para
let path='/functions/{functionId}/tags'.replace('{functionId}',functionId);let payload={};if(typeof command!=='undefined'){payload['command']=command;}
if(typeof code!=='undefined'){payload['code']=code;}
const uri=new URL(this.config.endpoint+path);const size=code.size;if(size<=Appwrite.CHUNK_SIZE){return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}
else{let id=undefined;let response=undefined;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(let counter=0;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);const headers={'content-type':'multipart/form-data','content-range':'bytes '+start+'-'+end+'/'+size};if(id){headers['x-appwrite-id']=id;}
let id=undefined;let response=undefined;const headers={'content-type':'multipart/form-data',};let counter=0;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(counter;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);headers['content-range']='bytes '+start+'-'+end+'/'+size;if(id){headers['x-appwrite-id']=id;}
const stream=code.slice(start,end+1);payload['code']=new File([stream],code.name);response=yield this.call('post',uri,headers,payload);if(!id){id=response['$id'];}
if(onProgress){onProgress(Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100);}}
return response;}}),getTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(onProgress){onProgress({$id:response.$id,progress:Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100,sizeUpploaded:end+1,chunksTotal:response.chunksTotal,chunksUploaded:response.chunksUploaded});}}
return response;}),getTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionId).replace('{tagId}',tagId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),deleteTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
@ -491,10 +492,12 @@ if(typeof file!=='undefined'){payload['file']=file;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);const size=file.size;if(size<=Appwrite.CHUNK_SIZE){return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}
else{let id=undefined;let response=undefined;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(let counter=0;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);const headers={'content-type':'multipart/form-data','content-range':'bytes '+start+'-'+end+'/'+size};if(id){headers['x-appwrite-id']=id;}
let id=undefined;let response=undefined;const headers={'content-type':'multipart/form-data',};let counter=0;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);if(fileId!='unique()'){try{response=yield this.call('GET',new URL(this.config.endpoint+path+'/'+fileId),headers);counter=response.chunksUploaded;}
catch(e){}}
for(counter;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);headers['content-range']='bytes '+start+'-'+end+'/'+size;if(id){headers['x-appwrite-id']=id;}
const stream=file.slice(start,end+1);payload['file']=new File([stream],file.name);response=yield this.call('post',uri,headers,payload);if(!id){id=response['$id'];}
if(onProgress){onProgress(Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100);}}
return response;}}),getFile:(bucketId,fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(onProgress){onProgress({$id:response.$id,progress:Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100,sizeUpploaded:end+1,chunksTotal:response.chunksTotal,chunksUploaded:response.chunksUploaded});}}
return response;}),getFile:(bucketId,fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
let path='/storage/buckets/{bucketId}/files/{fileId}'.replace('{bucketId}',bucketId).replace('{fileId}',fileId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateFile:(bucketId,fileId,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
@ -3728,9 +3731,13 @@ if(forcePlaces!==false){rounded=Number(rounded).toFixed(forcePlaces);}
return rounded+abbr;}
window.ls.container.get("view").add({selector:"data-acl",controller:function(element,document,router,alerts){document.body.classList.remove("console");document.body.classList.remove("home");document.body.classList.add(router.getCurrent().view.scope);if(!router.getCurrent().view.project){document.body.classList.add("hide-nav");document.body.classList.remove("show-nav");}else{document.body.classList.add("show-nav");document.body.classList.remove("hide-nav");}
if("/console"===router.getCurrent().path){document.body.classList.add("index");}else{document.body.classList.remove("index");}}}).add({selector:"data-prism",controller:function(window,document,element,alerts){Prism.highlightElement(element);let copy=document.createElement("i");copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.textContent="Click Here to Copy";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(element);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}});(function(window){document.addEventListener('alpine:init',()=>{Alpine.store('uploader',{files:[],isOpen:true,init(){window.addEventListener('beforeunload',(event)=>{this.files.forEach((file)=>{if(!file.completed&&!file.failed){let confirmationMessage="There are incomplete uploads, are you sure you want to leave?";event.returnValue=confirmationMessage;return confirmationMessage;}});});},toggle(){this.isOpen=!this.isOpen;},addFile(file){this.files.push(file);},updateFile(id,file){this.files=this.files.map((oldFile)=>id==oldFile.id?{...oldFile,...file}:oldFile);},removeFile(id){this.files=this.files.filter((file)=>file.id!==id);},async uploadFile(target){const formData=new FormData(target);const sdk=window.ls.container.get('sdk');const file=formData.get('file');const fileId=formData.get('fileId');const id=fileId==='unique()'?performance.now():fileId;let read=formData.get('read');if(read){read=JSON.parse(read);}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}});(function(window){document.addEventListener('alpine:init',()=>{Alpine.store('uploader',{_files:[],files(){return(this._files??[]).filter((file)=>!file.cancelled);},isOpen:true,init(){window.addEventListener('beforeunload',(event)=>{this._files.forEach((file)=>{if(!file.completed&&!file.failed){let confirmationMessage="There are incomplete uploads, are you sure you want to leave?";event.returnValue=confirmationMessage;return confirmationMessage;}});});},cancelAll(){if(confirm("Are you sure? This will cancel and remove any ungoing uploads?")){this._files.forEach(file=>{if(file.completed||file.failed){this.removeFile(file.id);}else{this.updateFile(file.id,{cancelled:true});}});}},toggle(){this.isOpen=!this.isOpen;},addFile(file){this._files.push(file);},updateFile(id,file){this._files=this._files.map((oldFile)=>id==oldFile.id?{...oldFile,...file}:oldFile);},removeFile(id){const file=this.getFile(id)??{};if(file.completed||file.failed){this._files=this._files.filter((file)=>file.id!==id);}else{if(confirm("Are you sure you want to cancel the upload?")){this.updateFile(id,{cancelled:true});}}},getFile(id){return this._files.find((file)=>file.id===id);},async uploadFile(target){const formData=new FormData(target);const sdk=window.ls.container.get('sdk');const bucketId=formData.get('bucketId');const file=formData.get('file');const fileId=formData.get('fileId');let id=fileId==='unique()'?performance.now():fileId;let read=formData.get('read');if(!file||!fileId){return;}
if(read){read=JSON.parse(read);}
let write=formData.get('write');if(write){write=JSON.parse(wirte);}
this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,isCancelled:false,});target.reset();try{const response=await sdk.storage.createFile(formData.get('bucketId'),fileId,file,read,write,(progress)=>{this.updateFile(id,{id:id,progress:Math.round(progress),});});this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){this.updateFile(id,{id:id,failed:true,});document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
if(this.getFile(id)){this.updateFile(id,{name:file.name,completed:false,failed:false,cancelled:false,});}else{this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,cancelled:false,});}
target.reset();try{const response=await sdk.storage.createFile(bucketId,fileId,file,read,write,(progress)=>{this.updateFile(id,{id:progress.$id,progress:Math.round(progress.progress),});id=progress.$id;const file=this.getFile(id)??{};if(file.cancelled===true){throw'USER_CANCELLED';}});const existingFile=this.getFile(id)??{};if(existingFile.cancelled){this.updateFile(id,{id:response.$id,name:response.name,failed:false,});id=response.$id;throw'USER_CANCELLED'}else{this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});id=response.$id;}
document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){if(error==='USER_CANCELLED'){await sdk.storage.deleteFile(bucketId,id);this.updateFile(id,{cancelled:false,failed:true,});this.removeFile(id);}else{this.updateFile(id,{id:id,failed:true,});}
document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){router.change(url||"/");};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}

View file

@ -64,7 +64,8 @@ if(typeof scopes!=='undefined'){payload['scopes']=scopes;}
const uri=new URL(this.config.endpoint+path);payload['project']=this.config.project;for(const[key,value]of Object.entries(this.flatten(payload))){uri.searchParams.append(key,value);}
if(typeof window!=='undefined'&&(window===null||window===void 0?void 0:window.location)){window.location.href=uri.toString();}
else{return uri;}},getSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),deleteSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),deleteSession:(sessionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof sessionId==='undefined'){throw new AppwriteException('Missing required parameter: "sessionId"');}
let path='/account/sessions/{sessionId}'.replace('{sessionId}',sessionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),createVerification:(url)=>__awaiter(this,void 0,void 0,function*(){if(typeof url==='undefined'){throw new AppwriteException('Missing required parameter: "url"');}
let path='/account/verification';let payload={};if(typeof url!=='undefined'){payload['url']=url;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),updateVerification:(userId,secret)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
@ -304,10 +305,10 @@ if(typeof code==='undefined'){throw new AppwriteException('Missing required para
let path='/functions/{functionId}/tags'.replace('{functionId}',functionId);let payload={};if(typeof command!=='undefined'){payload['command']=command;}
if(typeof code!=='undefined'){payload['code']=code;}
const uri=new URL(this.config.endpoint+path);const size=code.size;if(size<=Appwrite.CHUNK_SIZE){return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}
else{let id=undefined;let response=undefined;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(let counter=0;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);const headers={'content-type':'multipart/form-data','content-range':'bytes '+start+'-'+end+'/'+size};if(id){headers['x-appwrite-id']=id;}
let id=undefined;let response=undefined;const headers={'content-type':'multipart/form-data',};let counter=0;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(counter;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);headers['content-range']='bytes '+start+'-'+end+'/'+size;if(id){headers['x-appwrite-id']=id;}
const stream=code.slice(start,end+1);payload['code']=new File([stream],code.name);response=yield this.call('post',uri,headers,payload);if(!id){id=response['$id'];}
if(onProgress){onProgress(Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100);}}
return response;}}),getTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(onProgress){onProgress({$id:response.$id,progress:Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100,sizeUpploaded:end+1,chunksTotal:response.chunksTotal,chunksUploaded:response.chunksUploaded});}}
return response;}),getTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionId).replace('{tagId}',tagId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),deleteTag:(functionId,tagId)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
@ -491,10 +492,12 @@ if(typeof file!=='undefined'){payload['file']=file;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);const size=file.size;if(size<=Appwrite.CHUNK_SIZE){return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}
else{let id=undefined;let response=undefined;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);for(let counter=0;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);const headers={'content-type':'multipart/form-data','content-range':'bytes '+start+'-'+end+'/'+size};if(id){headers['x-appwrite-id']=id;}
let id=undefined;let response=undefined;const headers={'content-type':'multipart/form-data',};let counter=0;const totalCounters=Math.ceil(size/Appwrite.CHUNK_SIZE);if(fileId!='unique()'){try{response=yield this.call('GET',new URL(this.config.endpoint+path+'/'+fileId),headers);counter=response.chunksUploaded;}
catch(e){}}
for(counter;counter<totalCounters;counter++){const start=(counter*Appwrite.CHUNK_SIZE);const end=Math.min((((counter*Appwrite.CHUNK_SIZE)+Appwrite.CHUNK_SIZE)-1),size);headers['content-range']='bytes '+start+'-'+end+'/'+size;if(id){headers['x-appwrite-id']=id;}
const stream=file.slice(start,end+1);payload['file']=new File([stream],file.name);response=yield this.call('post',uri,headers,payload);if(!id){id=response['$id'];}
if(onProgress){onProgress(Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100);}}
return response;}}),getFile:(bucketId,fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(onProgress){onProgress({$id:response.$id,progress:Math.min((counter+1)*Appwrite.CHUNK_SIZE,size)/size*100,sizeUpploaded:end+1,chunksTotal:response.chunksTotal,chunksUploaded:response.chunksUploaded});}}
return response;}),getFile:(bucketId,fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
let path='/storage/buckets/{bucketId}/files/{fileId}'.replace('{bucketId}',bucketId).replace('{fileId}',fileId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateFile:(bucketId,fileId,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof bucketId==='undefined'){throw new AppwriteException('Missing required parameter: "bucketId"');}
if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}

View file

@ -689,9 +689,13 @@ if(forcePlaces!==false){rounded=Number(rounded).toFixed(forcePlaces);}
return rounded+abbr;}
window.ls.container.get("view").add({selector:"data-acl",controller:function(element,document,router,alerts){document.body.classList.remove("console");document.body.classList.remove("home");document.body.classList.add(router.getCurrent().view.scope);if(!router.getCurrent().view.project){document.body.classList.add("hide-nav");document.body.classList.remove("show-nav");}else{document.body.classList.add("show-nav");document.body.classList.remove("hide-nav");}
if("/console"===router.getCurrent().path){document.body.classList.add("index");}else{document.body.classList.remove("index");}}}).add({selector:"data-prism",controller:function(window,document,element,alerts){Prism.highlightElement(element);let copy=document.createElement("i");copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.textContent="Click Here to Copy";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(element);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}});(function(window){document.addEventListener('alpine:init',()=>{Alpine.store('uploader',{files:[],isOpen:true,init(){window.addEventListener('beforeunload',(event)=>{this.files.forEach((file)=>{if(!file.completed&&!file.failed){let confirmationMessage="There are incomplete uploads, are you sure you want to leave?";event.returnValue=confirmationMessage;return confirmationMessage;}});});},toggle(){this.isOpen=!this.isOpen;},addFile(file){this.files.push(file);},updateFile(id,file){this.files=this.files.map((oldFile)=>id==oldFile.id?{...oldFile,...file}:oldFile);},removeFile(id){this.files=this.files.filter((file)=>file.id!==id);},async uploadFile(target){const formData=new FormData(target);const sdk=window.ls.container.get('sdk');const file=formData.get('file');const fileId=formData.get('fileId');const id=fileId==='unique()'?performance.now():fileId;let read=formData.get('read');if(read){read=JSON.parse(read);}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}});(function(window){document.addEventListener('alpine:init',()=>{Alpine.store('uploader',{_files:[],files(){return(this._files??[]).filter((file)=>!file.cancelled);},isOpen:true,init(){window.addEventListener('beforeunload',(event)=>{this._files.forEach((file)=>{if(!file.completed&&!file.failed){let confirmationMessage="There are incomplete uploads, are you sure you want to leave?";event.returnValue=confirmationMessage;return confirmationMessage;}});});},cancelAll(){if(confirm("Are you sure? This will cancel and remove any ungoing uploads?")){this._files.forEach(file=>{if(file.completed||file.failed){this.removeFile(file.id);}else{this.updateFile(file.id,{cancelled:true});}});}},toggle(){this.isOpen=!this.isOpen;},addFile(file){this._files.push(file);},updateFile(id,file){this._files=this._files.map((oldFile)=>id==oldFile.id?{...oldFile,...file}:oldFile);},removeFile(id){const file=this.getFile(id)??{};if(file.completed||file.failed){this._files=this._files.filter((file)=>file.id!==id);}else{if(confirm("Are you sure you want to cancel the upload?")){this.updateFile(id,{cancelled:true});}}},getFile(id){return this._files.find((file)=>file.id===id);},async uploadFile(target){const formData=new FormData(target);const sdk=window.ls.container.get('sdk');const bucketId=formData.get('bucketId');const file=formData.get('file');const fileId=formData.get('fileId');let id=fileId==='unique()'?performance.now():fileId;let read=formData.get('read');if(!file||!fileId){return;}
if(read){read=JSON.parse(read);}
let write=formData.get('write');if(write){write=JSON.parse(wirte);}
this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,isCancelled:false,});target.reset();try{const response=await sdk.storage.createFile(formData.get('bucketId'),fileId,file,read,write,(progress)=>{this.updateFile(id,{id:id,progress:Math.round(progress),});});this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){this.updateFile(id,{id:id,failed:true,});document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
if(this.getFile(id)){this.updateFile(id,{name:file.name,completed:false,failed:false,cancelled:false,});}else{this.addFile({id:id,name:file.name,progress:0,completed:false,failed:false,cancelled:false,});}
target.reset();try{const response=await sdk.storage.createFile(bucketId,fileId,file,read,write,(progress)=>{this.updateFile(id,{id:progress.$id,progress:Math.round(progress.progress),});id=progress.$id;const file=this.getFile(id)??{};if(file.cancelled===true){throw'USER_CANCELLED';}});const existingFile=this.getFile(id)??{};if(existingFile.cancelled){this.updateFile(id,{id:response.$id,name:response.name,failed:false,});id=response.$id;throw'USER_CANCELLED'}else{this.updateFile(id,{id:response.$id,name:response.name,progress:100,completed:true,failed:false,});id=response.$id;}
document.dispatchEvent(new CustomEvent('storage.createFile'));}catch(error){if(error==='USER_CANCELLED'){await sdk.storage.deleteFile(bucketId,id);this.updateFile(id,{cancelled:false,failed:true,});this.removeFile(id);}else{this.updateFile(id,{id:id,failed:true,});}
document.dispatchEvent(new CustomEvent('storage.createFile'));}}});});})(window);(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||null;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){router.change(url||"/");};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -764,6 +764,25 @@
'content-type': 'application/json',
}, payload);
}),
/**
* Update Session (Refresh Tokens)
*
*
* @param {string} sessionId
* @throws {AppwriteException}
* @returns {Promise}
*/
updateSession: (sessionId) => __awaiter(this, void 0, void 0, function* () {
if (typeof sessionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "sessionId"');
}
let path = '/account/sessions/{sessionId}'.replace('{sessionId}', sessionId);
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('patch', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Delete Account Session
*
@ -1463,9 +1482,9 @@
* @param {string} collectionId
* @param {string} key
* @param {boolean} required
* @param {string} min
* @param {string} max
* @param {string} xdefault
* @param {number} min
* @param {number} max
* @param {number} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
@ -2561,32 +2580,37 @@
'content-type': 'multipart/form-data',
}, payload);
}
else {
let id = undefined;
let response = undefined;
const totalCounters = Math.ceil(size / Appwrite.CHUNK_SIZE);
for (let counter = 0; counter < totalCounters; counter++) {
const start = (counter * Appwrite.CHUNK_SIZE);
const end = Math.min((((counter * Appwrite.CHUNK_SIZE) + Appwrite.CHUNK_SIZE) - 1), size);
const headers = {
'content-type': 'multipart/form-data',
'content-range': 'bytes ' + start + '-' + end + '/' + size
};
if (id) {
headers['x-appwrite-id'] = id;
}
const stream = code.slice(start, end + 1);
payload['code'] = new File([stream], code.name);
response = yield this.call('post', uri, headers, payload);
if (!id) {
id = response['$id'];
}
if (onProgress) {
onProgress(Math.min((counter + 1) * Appwrite.CHUNK_SIZE, size) / size * 100);
}
let id = undefined;
let response = undefined;
const headers = {
'content-type': 'multipart/form-data',
};
let counter = 0;
const totalCounters = Math.ceil(size / Appwrite.CHUNK_SIZE);
for (counter; counter < totalCounters; counter++) {
const start = (counter * Appwrite.CHUNK_SIZE);
const end = Math.min((((counter * Appwrite.CHUNK_SIZE) + Appwrite.CHUNK_SIZE) - 1), size);
headers['content-range'] = 'bytes ' + start + '-' + end + '/' + size;
if (id) {
headers['x-appwrite-id'] = id;
}
const stream = code.slice(start, end + 1);
payload['code'] = new File([stream], code.name);
response = yield this.call('post', uri, headers, payload);
if (!id) {
id = response['$id'];
}
if (onProgress) {
onProgress({
$id: response.$id,
progress: Math.min((counter + 1) * Appwrite.CHUNK_SIZE, size) / size * 100,
sizeUpploaded: end + 1,
chunksTotal: response.chunksTotal,
chunksUploaded: response.chunksUploaded
});
}
return response;
}
return response;
}),
/**
* Get Tag
@ -4238,32 +4262,45 @@
'content-type': 'multipart/form-data',
}, payload);
}
else {
let id = undefined;
let response = undefined;
const totalCounters = Math.ceil(size / Appwrite.CHUNK_SIZE);
for (let counter = 0; counter < totalCounters; counter++) {
const start = (counter * Appwrite.CHUNK_SIZE);
const end = Math.min((((counter * Appwrite.CHUNK_SIZE) + Appwrite.CHUNK_SIZE) - 1), size);
const headers = {
'content-type': 'multipart/form-data',
'content-range': 'bytes ' + start + '-' + end + '/' + size
};
if (id) {
headers['x-appwrite-id'] = id;
}
const stream = file.slice(start, end + 1);
payload['file'] = new File([stream], file.name);
response = yield this.call('post', uri, headers, payload);
if (!id) {
id = response['$id'];
}
if (onProgress) {
onProgress(Math.min((counter + 1) * Appwrite.CHUNK_SIZE, size) / size * 100);
}
let id = undefined;
let response = undefined;
const headers = {
'content-type': 'multipart/form-data',
};
let counter = 0;
const totalCounters = Math.ceil(size / Appwrite.CHUNK_SIZE);
if (fileId != 'unique()') {
try {
response = yield this.call('GET', new URL(this.config.endpoint + path + '/' + fileId), headers);
counter = response.chunksUploaded;
}
catch (e) {
}
return response;
}
for (counter; counter < totalCounters; counter++) {
const start = (counter * Appwrite.CHUNK_SIZE);
const end = Math.min((((counter * Appwrite.CHUNK_SIZE) + Appwrite.CHUNK_SIZE) - 1), size);
headers['content-range'] = 'bytes ' + start + '-' + end + '/' + size;
if (id) {
headers['x-appwrite-id'] = id;
}
const stream = file.slice(start, end + 1);
payload['file'] = new File([stream], file.name);
response = yield this.call('post', uri, headers, payload);
if (!id) {
id = response['$id'];
}
if (onProgress) {
onProgress({
$id: response.$id,
progress: Math.min((counter + 1) * Appwrite.CHUNK_SIZE, size) / size * 100,
sizeUpploaded: end + 1,
chunksTotal: response.chunksTotal,
chunksUploaded: response.chunksUploaded
});
}
}
return response;
}),
/**
* Get File
@ -4382,7 +4419,8 @@
* Get a file preview image. Currently, this method supports preview for image
* files (jpg, png, and gif), other supported formats, like pdf, docs, slides,
* and spreadsheets, will return the file icon image. You can also pass query
* string arguments for cutting and resizing your preview image.
* string arguments for cutting and resizing your preview image. Preview is
* supported only for image files smaller than 10MB.
*
* @param {string} bucketId
* @param {string} fileId

View file

@ -1,11 +1,14 @@
(function(window){
document.addEventListener('alpine:init', () => {
Alpine.store('uploader', {
files: [],
_files: [],
files() {
return (this._files ?? []).filter((file) => !file.cancelled);
},
isOpen: true,
init() {
window.addEventListener('beforeunload', (event) => {
this.files.forEach((file) => {
this._files.forEach((file) => {
if(!file.completed && !file.failed) {
let confirmationMessage = "There are incomplete uploads, are you sure you want to leave?";
event.returnValue = confirmationMessage;
@ -14,25 +17,50 @@
});
});
},
cancelAll() {
if(confirm("Are you sure? This will cancel and remove any ungoing uploads?")){
this._files.forEach(file => {
if(file.completed || file.failed) {
this.removeFile(file.id);
} else {
this.updateFile(file.id, {cancelled: true});
}
});
}
},
toggle() {
this.isOpen = !this.isOpen;
},
addFile(file) {
this.files.push(file);
this._files.push(file);
},
updateFile(id, file) {
this.files = this.files.map((oldFile) => id == oldFile.id ? {...oldFile, ...file} : oldFile);
this._files = this._files.map((oldFile) => id == oldFile.id ? {...oldFile, ...file} : oldFile);
},
removeFile(id) {
this.files = this.files.filter((file) => file.id !== id);
const file = this.getFile(id) ?? {};
if(file.completed || file.failed) {
this._files = this._files.filter((file) => file.id !== id);
} else {
if(confirm("Are you sure you want to cancel the upload?")) {
this.updateFile(id, {cancelled: true});
}
}
},
getFile(id) {
return this._files.find((file) => file.id === id);
},
async uploadFile(target) {
const formData = new FormData(target);
const sdk = window.ls.container.get('sdk');
const bucketId = formData.get('bucketId');
const file = formData.get('file');
const fileId = formData.get('fileId');
const id = fileId === 'unique()' ? performance.now() : fileId;
let id = fileId === 'unique()' ? performance.now() : fileId;
let read = formData.get('read');
if(!file || !fileId) {
return;
}
if(read) {
read = JSON.parse(read);
}
@ -41,47 +69,78 @@
write = JSON.parse(wirte);
}
this.addFile({
id: id,
name: file.name,
progress: 0,
completed: false,
failed: false,
isCancelled: false,
});
if(this.getFile(id)) {
this.updateFile(id, {
name: file.name,
completed: false,
failed: false,
cancelled: false,
});
} else {
this.addFile({
id: id,
name: file.name,
progress: 0,
completed: false,
failed: false,
cancelled: false,
});
}
target.reset();
try {
const response = await sdk.storage.createFile(
formData.get('bucketId'),
bucketId,
fileId,
file,
read,
write,
(progress) => {
/*if cancelled
throw something
- When cancelled we need to delete the file
- but we don't yet have the id of the file,
- after resumable upload change, we will have the id
*/
this.updateFile(id, {
id: id,
progress: Math.round(progress),
id: progress.$id,
progress: Math.round(progress.progress),
});
id = progress.$id;
const file = this.getFile(id) ?? {};
if(file.cancelled === true) {
throw 'USER_CANCELLED';
}
});
this.updateFile(id,{
id: response.$id,
name: response.name,
progress: 100,
completed: true,
failed: false,
});
const existingFile = this.getFile(id) ?? {};
if(existingFile.cancelled) {
this.updateFile(id,{
id: response.$id,
name: response.name,
failed: false,
});
id = response.$id;
throw 'USER_CANCELLED'
} else {
this.updateFile(id,{
id: response.$id,
name: response.name,
progress: 100,
completed: true,
failed: false,
});
id = response.$id;
}
document.dispatchEvent(new CustomEvent('storage.createFile'));
} catch(error) {
this.updateFile(id, {
id: id,
failed: true,
});
if(error === 'USER_CANCELLED') {
await sdk.storage.deleteFile(bucketId, id);
this.updateFile(id, {
cancelled: false,
failed: true,
});
this.removeFile(id);
} else {
this.updateFile(id, {
id: id,
failed: true,
});
}
document.dispatchEvent(new CustomEvent('storage.createFile'));
}
}

View file

@ -9,4 +9,7 @@
&.is-disabled { --p-pill-text-color:var(--config-disabled-color-hsl); }
&.is-pending { --p-pill-text-color:var(--config-pending-color-hsl); }
&.is-failed { --p-pill-text-color:var(--config-failed-color-hsl); }
:root .theme-dark &{
&.is-failed {color:#FFCFCF; background-color:#B91C1C;}
}
}

View file

@ -31,21 +31,22 @@
}
&-content {
background-color:var(--p-content-bg-color); color:var(--p-content-text-color);
height:0; overflow:hidden;
height:0; overflow:auto;
transition:var(--transition);
&.is-open {height:200px; /* consider to change to rem */}
}
&-list {}
&-item {
display:flex; padding:13px 20px;
.file-name { @include trim; align-self:center; margin-inline-end:auto; }
display:flex; align-items:center; padding:13px 20px;
.file-name {text-overflow:ellipsis; white-space:nowrap; overflow:hidden; align-self:center; margin-inline-end:auto; line-height:normal; }
.icon-button{ align-self:center; margin-inline-start:16px;}
.pill{margin-inline-start:8px;}
&:not(:last-child) { border-bottom:solid 1px var(--p-border-color); }
}
/* responsive */
@media @phones { inset-inline:16px; inset-block-end:20px; }
@media @tablets, @desktops { inset-inline-end:24px; inset-block-end:24px; }
@media @tablets, @desktops { max-width:285px; inset-inline-end:24px; inset-block-end:24px; }
/* dark theme */
:root .theme-dark &{
@ -58,9 +59,9 @@
@upload-image-size-default: 40px;
--p-upload-image-size:var(--upload-image-size, @upload-image-size-default);
--p-upload-bg-color:var(--config-color-fade-super);
--p-upload-icon-color:var(--config-color-fade-light);
--p-upload-icon-color:var(--config-color-fade);
position:relative; display:grid; place-content:center;
position:relative; display:grid; place-content:center; flex-shrink:0;
width:var(--p-upload-image-size);
height:var(--p-upload-image-size);
background-color:var(--p-upload-bg-color);
@ -86,7 +87,6 @@
hsl(var(--zero-value)) 100%)";
}
&.is-finished {
--p-upload-icon-color:var(--config-color-fade);
.progress{ display:none; }
}
/* dark theme */