From ff30ad1cbede7139653d03637501be3ae61eb81d Mon Sep 17 00:00:00 2001 From: Willem Dantuma Date: Thu, 18 Jul 2019 18:59:42 +0200 Subject: [PATCH] Replace resumablejs with ngx-uploadx --- package-lock.json | 10 +- projects/common/package-lock.json | 42 +- projects/common/package.json | 6 +- projects/common/src/assets/resumable.js | 1084 ----------------- projects/common/src/lib/common.module.ts | 6 +- .../resumable-file-upload.component.ts | 27 +- .../resumable-file-upload.service.ts | 186 +-- .../components/timespan/timespan.component.ts | 2 +- .../common/src/lib/services/event.service.ts | 6 +- .../common/src/lib/services/folder.service.ts | 22 +- .../common/src/lib/services/item.service.ts | 37 +- .../src/lib/services/typeahead.service.ts | 11 +- .../common/src/lib/services/user.service.ts | 9 +- src/app/app-content.component.ts | 2 +- src/app/app.component.html | 16 +- src/configuration.json | 4 +- 16 files changed, 130 insertions(+), 1340 deletions(-) delete mode 100644 projects/common/src/assets/resumable.js diff --git a/package-lock.json b/package-lock.json index 721bcf1..2b703f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -646,7 +646,7 @@ "version": "file:dist/common", "requires": { "angular-oauth2-oidc": "^5.0.2", - "resumablejs": "1.1.0", + "ngx-uploadx": "^3.1.2", "tslib": "^1.9.0" } }, @@ -6889,6 +6889,14 @@ } } }, + "ngx-uploadx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/ngx-uploadx/-/ngx-uploadx-3.1.2.tgz", + "integrity": "sha512-4SWS5AjucJFUOU7uBUCxXwstKqLOtbrHHRMlTZWKPnDM/fLdpA31ZBvBr2u7nxYL8amadWYkfmA987p9anyXbg==", + "requires": { + "tslib": "^1.9.0" + } + }, "nice-try": { "version": "1.0.5", "resolved": "https://repository.akkerweb.nl/repository/npm-group/nice-try/-/nice-try-1.0.5.tgz", diff --git a/projects/common/package-lock.json b/projects/common/package-lock.json index ff87861..0be5e8b 100644 --- a/projects/common/package-lock.json +++ b/projects/common/package-lock.json @@ -4,40 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@angular/common": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.0.tgz", - "integrity": "sha512-5HNGT+XsY+7sQcNoFRqhbUfVdnBAtXaupmMbBclnQHTon9y9Ijp0ocYi7zxx39feo6xYF5HhBMnDPkFgtAnsYQ==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@angular/core": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.0.tgz", - "integrity": "sha512-tlCDDM9IknXvVLk1sg0lzCO4OREM54i1bFtTpl5kPtugK6l4kYCOH78UzDPHnOzzI3LGLj8Hb2NiObVa9c4fdg==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@ng-bootstrap/ng-bootstrap": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.2.1.tgz", - "integrity": "sha512-7etP9X9jKIkbuDzU3ngI2jQhHQDZxIu0ErvlkHb7u7YH9akIOLVkXvz2mTMvcFABWZhze64UjFuEgR46b6WGSw==", - "requires": { - "tslib": "^1.9.0" - } - }, - "@ngrx/effects": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-7.2.0.tgz", - "integrity": "sha512-vymKSoubYlUWGbiclPK0N/LwB409sB9atjSTQRy2EisZfFtQ2tCDqmk4JGgDy/gV9SqZWrwPSy1xXsLqYnyN3g==" - }, - "@ngrx/store": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-7.2.0.tgz", - "integrity": "sha512-E9c0cDot0HeE0mXyeqw18SwmJ2+eKnA5mMMfwvoskpMInCYGI2pq1i6/lCVQ2wrEHSH+KvObK4PQbepcA9vP+w==" - }, "angular-oauth2-oidc": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-5.0.2.tgz", @@ -52,6 +18,14 @@ "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.12.tgz", "integrity": "sha1-Iqu5ZW00owuVMENnIINeicLlwxY=" }, + "ngx-uploadx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/ngx-uploadx/-/ngx-uploadx-3.1.2.tgz", + "integrity": "sha512-4SWS5AjucJFUOU7uBUCxXwstKqLOtbrHHRMlTZWKPnDM/fLdpA31ZBvBr2u7nxYL8amadWYkfmA987p9anyXbg==", + "requires": { + "tslib": "^1.9.0" + } + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", diff --git a/projects/common/package.json b/projects/common/package.json index 95f4892..32f376b 100644 --- a/projects/common/package.json +++ b/projects/common/package.json @@ -1,12 +1,12 @@ { "name": "@farmmaps/common", "version": "0.0.1", - "publishConfig":{ - "registry":"https://repository.akkerweb.nl/repository/npm-hosted/" + "publishConfig": { + "registry": "https://repository.akkerweb.nl/repository/npm-hosted/" }, "dependencies": { "angular-oauth2-oidc": "^5.0.2", - "resumablejs": "1.1.0" + "ngx-uploadx": "^3.1.2" }, "peerDependencies": { "@ng-bootstrap/ng-bootstrap": "^4.2.1", diff --git a/projects/common/src/assets/resumable.js b/projects/common/src/assets/resumable.js deleted file mode 100644 index 649e6a2..0000000 --- a/projects/common/src/assets/resumable.js +++ /dev/null @@ -1,1084 +0,0 @@ -/* -* MIT Licensed -* http://www.23developer.com/opensource -* http://github.com/23/resumable.js -* Steffen Tiedemann Christensen, steffen@23company.com -*/ - -(function(){ -"use strict"; - - var Resumable = function(opts){ - if ( !(this instanceof Resumable) ) { - return new Resumable(opts); - } - this.version = 1.0; - // SUPPORTED BY BROWSER? - // Check if these features are support by the browser: - // - File object type - // - Blob object type - // - FileList object type - // - slicing files - this.support = ( - (typeof(File)!=='undefined') - && - (typeof(Blob)!=='undefined') - && - (typeof(FileList)!=='undefined') - && - (!!Blob.prototype.webkitSlice||!!Blob.prototype.mozSlice||!!Blob.prototype.slice||false) - ); - if(!this.support) return(false); - - - // PROPERTIES - var $ = this; - $.files = []; - $.defaults = { - chunkSize:1*1024*1024, - forceChunkSize:false, - simultaneousUploads:3, - fileParameterName:'file', - chunkNumberParameterName: 'resumableChunkNumber', - chunkSizeParameterName: 'resumableChunkSize', - currentChunkSizeParameterName: 'resumableCurrentChunkSize', - totalSizeParameterName: 'resumableTotalSize', - typeParameterName: 'resumableType', - identifierParameterName: 'resumableIdentifier', - fileNameParameterName: 'resumableFilename', - relativePathParameterName: 'resumableRelativePath', - totalChunksParameterName: 'resumableTotalChunks', - throttleProgressCallbacks: 0.5, - query:{}, - headers:{}, - preprocess:null, - method:'multipart', - uploadMethod: 'POST', - testMethod: 'GET', - prioritizeFirstAndLastChunk:false, - target:'/', - testTarget: null, - parameterNamespace:'', - testChunks:true, - generateUniqueIdentifier:null, - getTarget:null, - maxChunkRetries:100, - chunkRetryInterval:undefined, - permanentErrors:[400, 404, 415, 500, 501], - maxFiles:undefined, - withCredentials:false, - xhrTimeout:0, - clearInput:true, - chunkFormat:'blob', - setChunkTypeFromFile:false, - maxFilesErrorCallback:function (files, errorCount) { - var maxFiles = $.getOpt('maxFiles'); - alert('Please upload no more than ' + maxFiles + ' file' + (maxFiles === 1 ? '' : 's') + ' at a time.'); - }, - minFileSize:1, - minFileSizeErrorCallback:function(file, errorCount) { - alert(file.fileName||file.name +' is too small, please upload files larger than ' + $h.formatSize($.getOpt('minFileSize')) + '.'); - }, - maxFileSize:undefined, - maxFileSizeErrorCallback:function(file, errorCount) { - alert(file.fileName||file.name +' is too large, please upload files less than ' + $h.formatSize($.getOpt('maxFileSize')) + '.'); - }, - fileType: [], - fileTypeErrorCallback: function(file, errorCount) { - alert(file.fileName||file.name +' has type not allowed, please upload files of type ' + $.getOpt('fileType') + '.'); - } - }; - $.opts = opts||{}; - $.getOpt = function(o) { - var $opt = this; - // Get multiple option if passed an array - if(o instanceof Array) { - var options = {}; - $h.each(o, function(option){ - options[option] = $opt.getOpt(option); - }); - return options; - } - // Otherwise, just return a simple option - if ($opt instanceof ResumableChunk) { - if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } - else { $opt = $opt.fileObj; } - } - if ($opt instanceof ResumableFile) { - if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } - else { $opt = $opt.resumableObj; } - } - if ($opt instanceof Resumable) { - if (typeof $opt.opts[o] !== 'undefined') { return $opt.opts[o]; } - else { return $opt.defaults[o]; } - } - }; - - // EVENTS - // catchAll(event, ...) - // fileSuccess(file), fileProgress(file), fileAdded(file, event), filesAdded(files, filesSkipped), fileRetry(file), - // fileError(file, message), complete(), progress(), error(message, file), pause() - $.events = []; - $.on = function(event,callback){ - $.events.push(event.toLowerCase(), callback); - }; - $.fire = function(){ - // `arguments` is an object, not array, in FF, so: - var args = []; - for (var i=0; i 0){ - var fileTypeFound = false; - for(var index in o.fileType){ - var extension = '.' + o.fileType[index]; - if(fileName.toLowerCase().indexOf(extension.toLowerCase(), fileName.length - extension.length) !== -1){ - fileTypeFound = true; - break; - } - } - if (!fileTypeFound) { - o.fileTypeErrorCallback(file, errorCount++); - return false; - } - } - - if (typeof(o.minFileSize)!=='undefined' && file.sizeo.maxFileSize) { - o.maxFileSizeErrorCallback(file, errorCount++); - return false; - } - - function addFile(uniqueIdentifier){ - if (!$.getFromUniqueIdentifier(uniqueIdentifier)) {(function(){ - file.uniqueIdentifier = uniqueIdentifier; - var f = new ResumableFile($, file, uniqueIdentifier); - $.files.push(f); - files.push(f); - f.container = (typeof event != 'undefined' ? event.srcElement : null); - window.setTimeout(function(){ - $.fire('fileAdded', f, event) - },0); - })()} else { - filesSkipped.push(file); - }; - decreaseReamining(); - } - // directories have size == 0 - var uniqueIdentifier = $h.generateUniqueIdentifier(file, event); - if(uniqueIdentifier && typeof uniqueIdentifier.then === 'function'){ - // Promise or Promise-like object provided as unique identifier - uniqueIdentifier - .then( - function(uniqueIdentifier){ - // unique identifier generation succeeded - addFile(uniqueIdentifier); - }, - function(){ - // unique identifier generation failed - // skip further processing, only decrease file count - decreaseReamining(); - } - ); - }else{ - // non-Promise provided as unique identifier, process synchronously - addFile(uniqueIdentifier); - } - }); - }; - - // INTERNAL OBJECT TYPES - function ResumableFile(resumableObj, file, uniqueIdentifier){ - var $ = this; - $.opts = {}; - $.getOpt = resumableObj.getOpt; - $._prevProgress = 0; - $.resumableObj = resumableObj; - $.file = file; - $.fileName = file.fileName||file.name; // Some confusion in different versions of Firefox - $.size = file.size; - $.relativePath = file.relativePath || file.webkitRelativePath || $.fileName; - $.uniqueIdentifier = uniqueIdentifier; - $._pause = false; - $.container = ''; - var _error = uniqueIdentifier !== undefined; - - // Callback when something happens within the chunk - var chunkEvent = function(event, message){ - // event can be 'progress', 'success', 'error' or 'retry' - switch(event){ - case 'progress': - $.resumableObj.fire('fileProgress', $, message); - break; - case 'error': - $.abort(); - _error = true; - $.chunks = []; - $.resumableObj.fire('fileError', $, message); - break; - case 'success': - if(_error) return; - $.resumableObj.fire('fileProgress', $); // it's at least progress - if($.isComplete()) { - $.resumableObj.fire('fileSuccess', $, message); - } - break; - case 'retry': - $.resumableObj.fire('fileRetry', $); - break; - } - }; - - // Main code to set up a file object with chunks, - // packaged to be able to handle retries if needed. - $.chunks = []; - $.abort = function(){ - // Stop current uploads - var abortCount = 0; - $h.each($.chunks, function(c){ - if(c.status()=='uploading') { - c.abort(); - abortCount++; - } - }); - if(abortCount>0) $.resumableObj.fire('fileProgress', $); - }; - $.cancel = function(){ - // Reset this file to be void - var _chunks = $.chunks; - $.chunks = []; - // Stop current uploads - $h.each(_chunks, function(c){ - if(c.status()=='uploading') { - c.abort(); - $.resumableObj.uploadNextChunk(); - } - }); - $.resumableObj.removeFile($); - $.resumableObj.fire('fileProgress', $); - }; - $.retry = function(){ - $.bootstrap(); - var firedRetry = false; - $.resumableObj.on('chunkingComplete', function(){ - if(!firedRetry) $.resumableObj.upload(); - firedRetry = true; - }); - }; - $.bootstrap = function(){ - $.abort(); - _error = false; - // Rebuild stack of chunks from file - $.chunks = []; - $._prevProgress = 0; - var round = $.getOpt('forceChunkSize') ? Math.ceil : Math.floor; - var maxOffset = Math.max(round($.file.size/$.getOpt('chunkSize')),1); - for (var offset=0; offset0.99999 ? 1 : ret)); - ret = Math.max($._prevProgress, ret); // We don't want to lose percentages when an upload is paused - $._prevProgress = ret; - return(ret); - }; - $.isUploading = function(){ - var uploading = false; - $h.each($.chunks, function(chunk){ - if(chunk.status()=='uploading') { - uploading = true; - return(false); - } - }); - return(uploading); - }; - $.isComplete = function(){ - var outstanding = false; - $h.each($.chunks, function(chunk){ - var status = chunk.status(); - if(status=='pending' || status=='uploading' || chunk.preprocessState === 1) { - outstanding = true; - return(false); - } - }); - return(!outstanding); - }; - $.pause = function(pause){ - if(typeof(pause)==='undefined'){ - $._pause = ($._pause ? false : true); - }else{ - $._pause = pause; - } - }; - $.isPaused = function() { - return $._pause; - }; - - - // Bootstrap and return - $.resumableObj.fire('chunkingStart', $); - $.bootstrap(); - return(this); - } - - - function ResumableChunk(resumableObj, fileObj, offset, callback){ - var $ = this; - $.opts = {}; - $.getOpt = resumableObj.getOpt; - $.resumableObj = resumableObj; - $.fileObj = fileObj; - $.fileObjSize = fileObj.size; - $.fileObjType = fileObj.file.type; - $.offset = offset; - $.callback = callback; - $.lastProgressCallback = (new Date); - $.tested = false; - $.retries = 0; - $.pendingRetry = false; - $.preprocessState = 0; // 0 = unprocessed, 1 = processing, 2 = finished - - // Computed properties - var chunkSize = $.getOpt('chunkSize'); - $.loaded = 0; - $.startByte = $.offset*chunkSize; - $.endByte = Math.min($.fileObjSize, ($.offset+1)*chunkSize); - if ($.fileObjSize-$.endByte < chunkSize && !$.getOpt('forceChunkSize')) { - // The last chunk will be bigger than the chunk size, but less than 2*chunkSize - $.endByte = $.fileObjSize; - } - $.xhr = null; - - // test() makes a GET request without any data to see if the chunk has already been uploaded in a previous session - $.test = function(){ - // Set up request and listen for event - $.xhr = new XMLHttpRequest(); - - var testHandler = function(e){ - $.tested = true; - var status = $.status(); - if(status=='success') { - $.callback(status, $.message()); - $.resumableObj.uploadNextChunk(); - } else { - $.send(); - } - }; - $.xhr.addEventListener('load', testHandler, false); - $.xhr.addEventListener('error', testHandler, false); - $.xhr.addEventListener('timeout', testHandler, false); - - // Add data from the query options - var params = []; - var parameterNamespace = $.getOpt('parameterNamespace'); - var customQuery = $.getOpt('query'); - if(typeof customQuery == 'function') customQuery = customQuery($.fileObj, $); - $h.each(customQuery, function(k,v){ - params.push([encodeURIComponent(parameterNamespace+k), encodeURIComponent(v)].join('=')); - }); - // Add extra data to identify chunk - params = params.concat( - [ - // define key/value pairs for additional parameters - ['chunkNumberParameterName', $.offset + 1], - ['chunkSizeParameterName', $.getOpt('chunkSize')], - ['currentChunkSizeParameterName', $.endByte - $.startByte], - ['totalSizeParameterName', $.fileObjSize], - ['typeParameterName', $.fileObjType], - ['identifierParameterName', $.fileObj.uniqueIdentifier], - ['fileNameParameterName', $.fileObj.fileName], - ['relativePathParameterName', $.fileObj.relativePath], - ['totalChunksParameterName', $.fileObj.chunks.length] - ].filter(function(pair){ - // include items that resolve to truthy values - // i.e. exclude false, null, undefined and empty strings - return $.getOpt(pair[0]); - }) - .map(function(pair){ - // map each key/value pair to its final form - return [ - parameterNamespace + $.getOpt(pair[0]), - encodeURIComponent(pair[1]) - ].join('='); - }) - ); - // Append the relevant chunk and send it - $.xhr.open($.getOpt('testMethod'), $h.getTarget('test', params)); - $.xhr.timeout = $.getOpt('xhrTimeout'); - $.xhr.withCredentials = $.getOpt('withCredentials'); - // Add data from header options - var customHeaders = $.getOpt('headers'); - if(typeof customHeaders === 'function') { - customHeaders = customHeaders($.fileObj, $); - } - $h.each(customHeaders, function(k,v) { - $.xhr.setRequestHeader(k, v); - }); - $.xhr.send(null); - }; - - $.preprocessFinished = function(){ - $.preprocessState = 2; - $.send(); - }; - - // send() uploads the actual data in a POST call - $.send = function(){ - var preprocess = $.getOpt('preprocess'); - if(typeof preprocess === 'function') { - switch($.preprocessState) { - case 0: $.preprocessState = 1; preprocess($); return; - case 1: return; - case 2: break; - } - } - if($.getOpt('testChunks') && !$.tested) { - $.test(); - return; - } - - // Set up request and listen for event - $.xhr = new XMLHttpRequest(); - - // Progress - $.xhr.upload.addEventListener('progress', function(e){ - if( (new Date) - $.lastProgressCallback > $.getOpt('throttleProgressCallbacks') * 1000 ) { - $.callback('progress'); - $.lastProgressCallback = (new Date); - } - $.loaded=e.loaded||0; - }, false); - $.loaded = 0; - $.pendingRetry = false; - $.callback('progress'); - - // Done (either done, failed or retry) - var doneHandler = function(e){ - var status = $.status(); - if(status=='success'||status=='error') { - $.callback(status, $.message()); - $.resumableObj.uploadNextChunk(); - } else { - $.callback('retry', $.message()); - $.abort(); - $.retries++; - var retryInterval = $.getOpt('chunkRetryInterval'); - if(retryInterval !== undefined) { - $.pendingRetry = true; - setTimeout($.send, retryInterval); - } else { - $.send(); - } - } - }; - $.xhr.addEventListener('load', doneHandler, false); - $.xhr.addEventListener('error', doneHandler, false); - $.xhr.addEventListener('timeout', doneHandler, false); - - // Set up the basic query data from Resumable - var query = [ - ['chunkNumberParameterName', $.offset + 1], - ['chunkSizeParameterName', $.getOpt('chunkSize')], - ['currentChunkSizeParameterName', $.endByte - $.startByte], - ['totalSizeParameterName', $.fileObjSize], - ['typeParameterName', $.fileObjType], - ['identifierParameterName', $.fileObj.uniqueIdentifier], - ['fileNameParameterName', $.fileObj.fileName], - ['relativePathParameterName', $.fileObj.relativePath], - ['totalChunksParameterName', $.fileObj.chunks.length], - ].filter(function(pair){ - // include items that resolve to truthy values - // i.e. exclude false, null, undefined and empty strings - return $.getOpt(pair[0]); - }) - .reduce(function(query, pair){ - // assign query key/value - query[$.getOpt(pair[0])] = pair[1]; - return query; - }, {}); - // Mix in custom data - var customQuery = $.getOpt('query'); - if(typeof customQuery == 'function') customQuery = customQuery($.fileObj, $); - $h.each(customQuery, function(k,v){ - query[k] = v; - }); - - var func = ($.fileObj.file.slice ? 'slice' : ($.fileObj.file.mozSlice ? 'mozSlice' : ($.fileObj.file.webkitSlice ? 'webkitSlice' : 'slice'))); - var bytes = $.fileObj.file[func]($.startByte, $.endByte, $.getOpt('setChunkTypeFromFile') ? $.fileObj.file.type : ""); - var data = null; - var params = []; - - var parameterNamespace = $.getOpt('parameterNamespace'); - if ($.getOpt('method') === 'octet') { - // Add data from the query options - data = bytes; - $h.each(query, function (k, v) { - params.push([encodeURIComponent(parameterNamespace + k), encodeURIComponent(v)].join('=')); - }); - } else { - // Add data from the query options - data = new FormData(); - $h.each(query, function (k, v) { - data.append(parameterNamespace + k, v); - params.push([encodeURIComponent(parameterNamespace + k), encodeURIComponent(v)].join('=')); - }); - if ($.getOpt('chunkFormat') == 'blob') { - data.append(parameterNamespace + $.getOpt('fileParameterName'), bytes, $.fileObj.fileName); - } - else if ($.getOpt('chunkFormat') == 'base64') { - var fr = new FileReader(); - fr.onload = function (e) { - data.append(parameterNamespace + $.getOpt('fileParameterName'), fr.result); - $.xhr.send(data); - } - fr.readAsDataURL(bytes); - } - } - - var target = $h.getTarget('upload', params); - var method = $.getOpt('uploadMethod'); - - $.xhr.open(method, target); - if ($.getOpt('method') === 'octet') { - $.xhr.setRequestHeader('Content-Type', 'application/octet-stream'); - } - $.xhr.timeout = $.getOpt('xhrTimeout'); - $.xhr.withCredentials = $.getOpt('withCredentials'); - // Add data from header options - var customHeaders = $.getOpt('headers'); - if(typeof customHeaders === 'function') { - customHeaders = customHeaders($.fileObj, $); - } - - $h.each(customHeaders, function(k,v) { - $.xhr.setRequestHeader(k, v); - }); - - if ($.getOpt('chunkFormat') == 'blob') { - $.xhr.send(data); - } - }; - $.abort = function(){ - // Abort and reset - if($.xhr) $.xhr.abort(); - $.xhr = null; - }; - $.status = function(){ - // Returns: 'pending', 'uploading', 'success', 'error' - if($.pendingRetry) { - // if pending retry then that's effectively the same as actively uploading, - // there might just be a slight delay before the retry starts - return('uploading'); - } else if(!$.xhr) { - return('pending'); - } else if($.xhr.readyState<4) { - // Status is really 'OPENED', 'HEADERS_RECEIVED' or 'LOADING' - meaning that stuff is happening - return('uploading'); - } else { - if($.xhr.status == 200 || $.xhr.status == 201) { - // HTTP 200, 201 (created) - return('success'); - } else if($h.contains($.getOpt('permanentErrors'), $.xhr.status) || $.retries >= $.getOpt('maxChunkRetries')) { - // HTTP 415/500/501, permanent error - return('error'); - } else { - // this should never happen, but we'll reset and queue a retry - // a likely case for this would be 503 service unavailable - $.abort(); - return('pending'); - } - } - }; - $.message = function(){ - return($.xhr ? $.xhr.responseText : ''); - }; - $.progress = function(relative){ - if(typeof(relative)==='undefined') relative = false; - var factor = (relative ? ($.endByte-$.startByte)/$.fileObjSize : 1); - if($.pendingRetry) return(0); - if(!$.xhr || !$.xhr.status) factor*=.95; - var s = $.status(); - switch(s){ - case 'success': - case 'error': - return(1*factor); - case 'pending': - return(0*factor); - default: - return($.loaded/($.endByte-$.startByte)*factor); - } - }; - return(this); - } - - // QUEUE - $.uploadNextChunk = function(){ - var found = false; - - // In some cases (such as videos) it's really handy to upload the first - // and last chunk of a file quickly; this let's the server check the file's - // metadata and determine if there's even a point in continuing. - if ($.getOpt('prioritizeFirstAndLastChunk')) { - $h.each($.files, function(file){ - if(file.chunks.length && file.chunks[0].status()=='pending' && file.chunks[0].preprocessState === 0) { - file.chunks[0].send(); - found = true; - return(false); - } - if(file.chunks.length>1 && file.chunks[file.chunks.length-1].status()=='pending' && file.chunks[file.chunks.length-1].preprocessState === 0) { - file.chunks[file.chunks.length-1].send(); - found = true; - return(false); - } - }); - if(found) return(true); - } - - // Now, simply look for the next, best thing to upload - $h.each($.files, function(file){ - if(file.isPaused()===false){ - $h.each(file.chunks, function(chunk){ - if(chunk.status()=='pending' && chunk.preprocessState === 0) { - chunk.send(); - found = true; - return(false); - } - }); - } - if(found) return(false); - }); - if(found) return(true); - - // The are no more outstanding chunks to upload, check is everything is done - var outstanding = false; - $h.each($.files, function(file){ - if(!file.isComplete()) { - outstanding = true; - return(false); - } - }); - if(!outstanding) { - // All chunks have been uploaded, complete - $.fire('complete'); - } - return(false); - }; - - - // PUBLIC METHODS FOR RESUMABLE.JS - $.assignBrowse = function(domNodes, isDirectory){ - if(typeof(domNodes.length)=='undefined') domNodes = [domNodes]; - - $h.each(domNodes, function(domNode) { - var input; - if(domNode.tagName==='INPUT' && domNode.type==='file'){ - input = domNode; - } else { - input = document.createElement('input'); - input.setAttribute('type', 'file'); - input.style.display = 'none'; - domNode.addEventListener('click', function(){ - input.style.opacity = 0; - input.style.display='block'; - input.focus(); - input.click(); - input.style.display='none'; - }, false); - domNode.appendChild(input); - } - var maxFiles = $.getOpt('maxFiles'); - if (typeof(maxFiles)==='undefined'||maxFiles!=1){ - input.setAttribute('multiple', 'multiple'); - } else { - input.removeAttribute('multiple'); - } - if(isDirectory){ - input.setAttribute('webkitdirectory', 'webkitdirectory'); - } else { - input.removeAttribute('webkitdirectory'); - } - var fileTypes = $.getOpt('fileType'); - if (typeof (fileTypes) !== 'undefined' && fileTypes.length >= 1) { - input.setAttribute('accept', fileTypes.map(function (e) { return '.' + e }).join(',')); - } - else { - input.removeAttribute('accept'); - } - // When new files are added, simply append them to the overall list - input.addEventListener('change', function(e){ - appendFilesFromFileList(e.target.files,e); - var clearInput = $.getOpt('clearInput'); - if (clearInput) { - e.target.value = ''; - } - }, false); - }); - }; - $.assignDrop = function(domNodes){ - if(typeof(domNodes.length)=='undefined') domNodes = [domNodes]; - - $h.each(domNodes, function(domNode) { - domNode.addEventListener('dragover', preventDefault, false); - domNode.addEventListener('dragenter', preventDefault, false); - domNode.addEventListener('drop', onDrop, false); - }); - }; - $.unAssignDrop = function(domNodes) { - if (typeof(domNodes.length) == 'undefined') domNodes = [domNodes]; - - $h.each(domNodes, function(domNode) { - domNode.removeEventListener('dragover', preventDefault); - domNode.removeEventListener('dragenter', preventDefault); - domNode.removeEventListener('drop', onDrop); - }); - }; - $.isUploading = function(){ - var uploading = false; - $h.each($.files, function(file){ - if (file.isUploading()) { - uploading = true; - return(false); - } - }); - return(uploading); - }; - $.upload = function(){ - // Make sure we don't start too many uploads at once - if($.isUploading()) return; - // Kick off the queue - $.fire('uploadStart'); - for (var num=1; num<=$.getOpt('simultaneousUploads'); num++) { - $.uploadNextChunk(); - } - }; - $.pause = function(){ - // Resume all chunks currently being uploaded - $h.each($.files, function(file){ - file.abort(); - }); - $.fire('pause'); - }; - $.cancel = function(){ - $.fire('beforeCancel'); - for(var i = $.files.length - 1; i >= 0; i--) { - $.files[i].cancel(); - } - $.fire('cancel'); - }; - $.progress = function(){ - var totalDone = 0; - var totalSize = 0; - // Resume all chunks currently being uploaded - $h.each($.files, function(file){ - totalDone += file.progress()*file.size; - totalSize += file.size; - }); - return(totalSize>0 ? totalDone/totalSize : 0); - }; - $.addFile = function(file, event){ - appendFilesFromFileList([file], event); - }; - $.addFiles = function(files, event){ - appendFilesFromFileList(files, event); - }; - $.removeFile = function(file){ - for(var i = $.files.length - 1; i >= 0; i--) { - if($.files[i] === file) { - $.files.splice(i, 1); - } - } - }; - $.getFromUniqueIdentifier = function(uniqueIdentifier){ - var ret = false; - $h.each($.files, function(f){ - if(f.uniqueIdentifier==uniqueIdentifier) ret = f; - }); - return(ret); - }; - $.getSize = function(){ - var totalSize = 0; - $h.each($.files, function(file){ - totalSize += file.size; - }); - return(totalSize); - }; - $.handleDropEvent = function (e) { - onDrop(e); - }; - $.handleChangeEvent = function (e) { - appendFilesFromFileList(e.target.files, e); - e.target.value = ''; - }; - $.updateQuery = function(query){ - $.opts.query = query; - }; - - return(this); - }; - - - // Node.js-style export for Node and Component - if (typeof module != 'undefined') { - module.exports = Resumable; - } else if (typeof define === "function" && define.amd) { - // AMD/requirejs: Define the module - define(function(){ - return Resumable; - }); - } else { - // Browser: Expose to window - window.Resumable = Resumable; - } - -})(); diff --git a/projects/common/src/lib/common.module.ts b/projects/common/src/lib/common.module.ts index 35b1cb4..4d9d9e7 100644 --- a/projects/common/src/lib/common.module.ts +++ b/projects/common/src/lib/common.module.ts @@ -9,6 +9,7 @@ import { OAuthModule,AuthConfig, OAuthService, OAuthStorage } from 'angular-oaut import { StoreModule,Store } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import {UploadxModule } from 'ngx-uploadx'; // routing module @@ -98,7 +99,8 @@ export {FolderService, EffectsModule.forFeature([commonEffects.AppCommonEffects]), OAuthModule.forRoot(), NgbModule, - FormsModule + FormsModule, + UploadxModule ], providers: [ DatePipe @@ -113,7 +115,7 @@ export {FolderService, TagInputComponent, SessionClearedComponent ], - exports: [NgbModule, ResumableFileUploadComponent, SidePanelComponent, CommonModule, HttpClientModule, SafePipe, TimespanComponent, TagInputComponent ] + exports: [NgbModule,UploadxModule, ResumableFileUploadComponent, SidePanelComponent, CommonModule, HttpClientModule, SafePipe, TimespanComponent, TagInputComponent ] }) export class AppCommonModule { static forRoot(): ModuleWithProviders { diff --git a/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.component.ts b/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.component.ts index 8f6c561..9fece47 100644 --- a/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.component.ts +++ b/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, ElementRef, HostListener, ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, HostListener, ChangeDetectorRef, OnDestroy, OnInit } from '@angular/core'; import { ResumableFileUploadService, File } from './resumable-file-upload.service'; import { Subscription } from 'rxjs'; @@ -11,28 +11,6 @@ import { Subscription } from 'rxjs'; export class ResumableFileUploadComponent implements OnInit, OnDestroy { - private browseFileElement$: ElementRef; - - @Input('browseFileElement') - get browseFileElement(): ElementRef { - return this.browseFileElement$; - } - - set browseFileElement(element: ElementRef) { - this.uploadService.assignFileBrowse(element); - this.browseFileElement$ = element; - } - - @Input('browseDirectoryElement') - set browseDirectoryElement(element: ElementRef) { - this.uploadService.assignDirectoryBrowse(element); - } - - @Input('fileDropElement') - set fileDropElement(element: ElementRef) { - this.uploadService.assignDrop(element); - } - @Input('parentCode') set parentCode(parentCode: string) { if (parentCode && parentCode != "null" && parentCode != "") @@ -47,6 +25,7 @@ export class ResumableFileUploadComponent implements OnInit, OnDestroy { private refreshSub: Subscription; ngOnInit() { + this.uploadService.init(); this.refreshSub = this.uploadService.refresh.subscribe((e: any) => { this.cd.markForCheck(); }); @@ -56,7 +35,7 @@ export class ResumableFileUploadComponent implements OnInit, OnDestroy { if(this.refreshSub) this.refreshSub.unsubscribe(); } - //this.cd.markForCheck(); + //TODO do this with an canunload guard @HostListener('window:beforeunload') windowBeforeUnload = function () { if (this.uploadService.isUploading) { diff --git a/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.service.ts b/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.service.ts index 156e830..d6166a5 100644 --- a/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.service.ts +++ b/projects/common/src/lib/components/resumable-file-upload/resumable-file-upload.service.ts @@ -1,17 +1,13 @@ -import { Injectable, ElementRef } from '@angular/core'; +import { Injectable, OnDestroy } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; -import { Subject , of } from 'rxjs'; -import { HttpClient, HttpParams } from "@angular/common/http"; +import { Subject , Subscription } from 'rxjs'; +import { HttpClient } from "@angular/common/http"; +import { UploadxService, UploadState} from 'ngx-uploadx'; +import { AppConfig } from '../../shared/app.config'; -declare var require; // avoid missing property error on require - -@Injectable() -export class ResumableFileUploadService { - private resumable: any; - private dropElement: ElementRef; - private fileBrowseElement: ElementRef; - private directoryBrowseElement: ElementRef; +@Injectable({ providedIn: 'root' }) +export class ResumableFileUploadService implements OnDestroy{ public files: Array = new Array(); public isUploading = false; public totalProgress = "0"; @@ -19,138 +15,58 @@ export class ResumableFileUploadService { public isMinimized = false; public parentCode: string; public refresh: Subject = new Subject(); + private _eventSub:Subscription; + private initialized = false; - constructor(private httpClient: HttpClient,private oauthService: OAuthService) { - this.init(); + constructor(private httpClient: HttpClient,private oauthService: OAuthService,private uploadService: UploadxService,public appConfig: AppConfig) { + } - init = function () { - this.ref - require.ensure([], require => { - let Resumable = require('./resumable.js'); - var other = this; - this.resumable = new Resumable( - { - target: '/api/v1/file/chunk', - query: function (file, chunk) { - var options = {}; - if (file.parentCode) options["parentCode"] = file.parentCode; - if (chunk.tested) { - if (file.file.geoRefJson) options["geoRefJson"] = file.file.geoRefJson; - if (file.file.attributes) options["attributes"] = file.file.attributes; - } - return options; - }, - headers: function (file) { - return { Authorization: "Bearer " + other.oauthService.getAccessToken() } - }, - generateUniqueIdentifier: function (file, event) { - var params = new HttpParams() - .set("name", file.fileName || file.name) - .set("size", file.size); + endPoint() { + return `${this.appConfig.getConfig("apiEndPoint")}/api/v1/file`; + } - return other.httpClient.post("/api/v1/file",params).toPromise().then(res => res.code); - }, - chunkNumberParameterName: 'chunkNumber', - chunkSizeParameterName: 'chunkSize', - currentChunkSizeParameterName: 'currentChunkSize', - totalSizeParameterName: 'size', - typeParameterName: 'type', - identifierParameterName: 'code', - fileNameParameterName: 'name', - relativePathParameterName: 'relativePath', - totalChunksParameterName: 'totalChunks' - } - ) as any; + init() { + if(!this.initialized) { + this._eventSub=this.uploadService.init({ + endpoint:this.endPoint(), + token:() => this.oauthService.getAccessToken(), + chunkSize: 2097152}).subscribe((uploadState:UploadState) => { + this.handleState(uploadState); + } ); + this.initialized=true; + } + } - var other = this; - - this.resumable.on('catchAll', function (event) { - other.isUploading = other.resumable.isUploading(); - other.totalProgress = (other.resumable.progress() * 100).toFixed(0); - other.refresh.next({}); - }); - - this.resumable.on('filesAdded', function (files) { - files.forEach(function (file) { - file.parentCode = other.parentCode; - other.files.push(new File(file)); - }); - other.isClosed = false; - other.resumable.upload(); - }); - - this.resumable.on('fileSuccess', function (file) { - var index = other.getIndex(file); - if (index >= 0) { - other.files[index].success = true; - } - }); - - this.resumable.on('error', function (message,file) { - var index = other.getIndex(file); - if (index >= 0) { - other.files[index].error = true; - other.files[index].errorMessage = message; - } - }); - - this.resumable.on('fileProgress', function (file) { - var index = other.getIndex(file); - if (index >= 0) { - other.files[index].progress = (file.progress() * 100) + '%'; - } - }); - - if (this.dropElement) this.resumable.assignDrop(this.dropElement); - if (this.fileBrowseElement) this.resumable.assignBrowse(this.fileBrowseElement); - if (this.directoryBrowseElement) this.resumable.assignBrowse(this.directoryBrowseElement, true); - }); + handleState(state:UploadState) { + switch(state.status) { + case "added": { + this.files.push(new File(state)); + };break; + case "uploading": + case "complete": { + var file =this.files.find((f) => f.identifier == state.uploadId ) + if(file) { + file.progress = (state.progress * 100) + '%'; + } + };break; + } } addFiles = (files: any[], event: any, geoRefJson?: string, attributes?: any) => { for (let f of files) { - if (geoRefJson) f.geoRefJson = geoRefJson; - if (attributes) f.attributes = JSON.stringify(attributes); + this.uploadService.handleFile(f); + // if (geoRefJson) f.geoRefJson = geoRefJson; + // if (attributes) f.attributes = JSON.stringify(attributes); } - this.resumable.addFiles(files, event); } - - assignDrop = function (element: ElementRef) { - if (this.resumable) { - this.resumable.assignDrop(element); - } - this.dropElement = element; - } - - assignFileBrowse = function (element: ElementRef) { - if (this.resumable) { - this.resumable.assignBrowse(element); - } - this.fileBrowseElement = element; - } - - assignDirectoryBrowse = function (element: ElementRef) { - if (this.resumable) { - this.resumable.assignBrowse(element, true); - } - this.directoryBrowseElement = element; - } - - getIndex = function (file) { - for (var i = 0; i < this.files.length; i++) { - if (this.files[i].identifier == file.uniqueIdentifier) - return i; - } - return -1; - } - + toggleMinimize = function () { this.isMinimized = !this.isMinimized; }; cancelFile = function (file) { - file.file.cancel(); + this.uploadService.control({action:'cancel',uploadId:file.identifier}); var index = this.files.indexOf(file, 0); if (index > -1) { this.files.splice(index, 1); @@ -158,7 +74,7 @@ export class ResumableFileUploadService { }; doClose = function () { - this.resumable.cancel(); + this.uploadService.control({action:'cancelAll'}); this.files = new Array(); this.isClosed = true; } @@ -172,6 +88,10 @@ export class ResumableFileUploadService { this.doClose(); } } + + ngOnDestroy() { + if(this._eventSub) this._eventSub.unsubscribe(); + } } export class File { @@ -184,11 +104,11 @@ export class File { public errorMessage: string; - constructor(file: any) { - this.file = file; - this.fileName = file.fileName; - this.progress = (file.progress() * 100) + '%'; - this.identifier = file.uniqueIdentifier; + constructor(state: UploadState) { + this.file = state; + this.fileName = state.file.name; + this.progress = (state.progress * 100) + '%'; + this.identifier = state.uploadId; this.success = false; this.error = false; this.errorMessage = ""; diff --git a/projects/common/src/lib/components/timespan/timespan.component.ts b/projects/common/src/lib/components/timespan/timespan.component.ts index e3aea90..7deb6bf 100644 --- a/projects/common/src/lib/components/timespan/timespan.component.ts +++ b/projects/common/src/lib/components/timespan/timespan.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit,Input,ViewChild,ElementRef,OnChanges,AfterViewInit,ChangeDetectorRef,Output, EventEmitter,SimpleChanges } from '@angular/core'; +import { Component, OnInit,Input,ViewChild,OnChanges,ChangeDetectorRef,Output, EventEmitter,SimpleChanges } from '@angular/core'; import { DatePipe } from '@angular/common'; import {NgbPopover} from '@ng-bootstrap/ng-bootstrap'; diff --git a/projects/common/src/lib/services/event.service.ts b/projects/common/src/lib/services/event.service.ts index 882214b..41f5525 100644 --- a/projects/common/src/lib/services/event.service.ts +++ b/projects/common/src/lib/services/event.service.ts @@ -9,13 +9,13 @@ import { AppConfig } from "../shared/app.config"; @Injectable() export class EventService { - public event:Subject = new Subject(); + public event:Subject = new Subject(); private _connection: HubConnection = null; private _apiEndPoint: string; constructor(private oauthService: OAuthService, private appConfig: AppConfig) { - this._apiEndPoint = ""; //appConfig.getConfig("apiEndPoint"); - this._connection = new HubConnectionBuilder().withUrl(`${this._apiEndPoint}/eventHub`).configureLogging(LogLevel.Information).build(); + this._apiEndPoint = appConfig.getConfig("apiEndPoint"); + this._connection = new HubConnectionBuilder().withUrl(`${ this._apiEndPoint}/eventHub`).configureLogging(LogLevel.Information).build(); this._connection.start().then(() => { var accessToken = oauthService.getAccessToken(); if (accessToken) { diff --git a/projects/common/src/lib/services/folder.service.ts b/projects/common/src/lib/services/folder.service.ts index 26139d0..f714b77 100644 --- a/projects/common/src/lib/services/folder.service.ts +++ b/projects/common/src/lib/services/folder.service.ts @@ -8,10 +8,12 @@ import { AppConfig } from "../shared/app.config"; @Injectable() export class FolderService { - private _apiEndPoint: string; - constructor(public httpClient: HttpClient, public appConfig: AppConfig) { - this._apiEndPoint = "";//appConfig.getConfig("apiEndPoint"); + constructor(public httpClient: HttpClient, public appConfig: AppConfig) { + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); } parseDates(item: any): IListItem { @@ -22,31 +24,31 @@ export class FolderService { } getFolder(code: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/folders/${code}`).pipe(map(i => this.parseDates(i))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/folders/${code}`).pipe(map(i => this.parseDates(i))); } getMyRoots(): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/folders/my_roots`).pipe(map(ia => ia.map(i => this.parseDates(i)))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/folders/my_roots`).pipe(map(ia => ia.map(i => this.parseDates(i)))); } getFolderParents(code: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/folders/${code}/parents`).pipe(map(ia => ia.map(i => this.parseDates(i)))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/folders/${code}/parents`).pipe(map(ia => ia.map(i => this.parseDates(i)))); } getChildFolders(code: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/folders/${code}/listfolders`).pipe(map(ia => ia.map(i => this.parseDates(i)))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/folders/${code}/listfolders`).pipe(map(ia => ia.map(i => this.parseDates(i)))); } getItems(code: string,skip:number, take:number): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/folders/${code}/list?skip=${skip}&take=${take}`).pipe(map(ia => ia.map(i => this.parseDates(i)))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/folders/${code}/list?skip=${skip}&take=${take}`).pipe(map(ia => ia.map(i => this.parseDates(i)))); } moveItem(itemCode: string, newParentCode: string): Observable { const body = { itemCode: itemCode,newParentCode: newParentCode }; - return this.httpClient.post(`${this._apiEndPoint}/api/v1/items/move`, body).pipe(map(i => this.parseDates(i))); + return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/items/move`, body).pipe(map(i => this.parseDates(i))); } createFolder(folder: IItem): Observable { - return this.httpClient.post(`${this._apiEndPoint}/api/v1/folders/`, folder).pipe(map(i => this.parseDates(i))); + return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/folders/`, folder).pipe(map(i => this.parseDates(i))); } } diff --git a/projects/common/src/lib/services/item.service.ts b/projects/common/src/lib/services/item.service.ts index af72fe3..dd1f8db 100644 --- a/projects/common/src/lib/services/item.service.ts +++ b/projects/common/src/lib/services/item.service.ts @@ -9,10 +9,11 @@ import { AppConfig } from "../shared/app.config"; @Injectable() export class ItemService { - private _apiEndPoint: string; - constructor(public httpClient: HttpClient, public appConfig: AppConfig) { - this._apiEndPoint = ""; //appConfig.getConfig("apiEndPoint"); + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); } parseDates(item: any): IItem { @@ -23,7 +24,7 @@ export class ItemService { } getItemTypes(): Observable<{ [id: string]: IItemType }> { - return this.httpClient.get<{ [id: string]: IItemType }>(`${this._apiEndPoint}/api/v1/itemtypes/`); + return this.httpClient.get<{ [id: string]: IItemType }>(`${this.ApiEndpoint()}/api/v1/itemtypes/`); } getFeatures(extent: number[], crs: string, searchText?: string, searchTags?:string,startDate?:Date,endDate?:Date): Observable { @@ -34,21 +35,21 @@ export class ItemService { if (searchTags) params = params.append("t", searchTags); if (startDate) params = params.append("sd", startDate.toISOString()); if (endDate) params = params.append("ed", endDate.toISOString()); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/features/`, {params:params}); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/features/`, {params:params}); } getFeature(code:string, crs: string): Observable { var params = new HttpParams(); params = params.append("crs", crs); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/feature/`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/feature/`, { params: params }); } getItem(code: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}`).pipe(map(i => this.parseDates(i))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}`).pipe(map(i => this.parseDates(i))); } getItemByCodeAndType(code: string, itemType: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/${itemType}`); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/${itemType}`); } getItemList(itemType: string, dataFilter?: any, level: number = 1): Observable { @@ -58,7 +59,7 @@ export class ItemService { params = params.append("df", JSON.stringify(dataFilter)); } params = params.append("lvl", itemType); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/`, { params: params }).pipe(map(ia => ia.map(i => this.parseDates(i)))); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/`, { params: params }).pipe(map(ia => ia.map(i => this.parseDates(i)))); } getChildItemList(parentcode: string, itemType: string, dataFilter?: any, level: number = 1): Observable { @@ -68,7 +69,7 @@ export class ItemService { params = params.append("df", JSON.stringify(dataFilter)); } params = params.append("lvl", level.toString()); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${parentcode}/children`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children`, { params: params }); } getChildItemListByExtent(parentcode: string, itemType: string, extent: number[], crs: string, dataFilter?: any, level: number = 1): Observable { @@ -80,7 +81,7 @@ export class ItemService { params = params.append("df", JSON.stringify(dataFilter)); } params = params.append("lvl", level.toString()); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${parentcode}/children`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${parentcode}/children`, { params: params }); } getItemFeatures(code: string, extent: number[], crs: string, layerIndex?:number): Observable { @@ -88,32 +89,32 @@ export class ItemService { params = params.append("bbox", extent.join(",")); params = params.append("crs", crs); if(layerIndex!=null) - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/features/layer/${layerIndex}`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/features/layer/${layerIndex}`, { params: params }); else - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/features`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/features`, { params: params }); } putItem(item:IItem): Observable { - return this.httpClient.put(`${this._apiEndPoint}/api/v1/items/${item.code}`,item); + return this.httpClient.put(`${this.ApiEndpoint()}/api/v1/items/${item.code}`,item); } deleteItems(itemCodes:string[]): Observable { - return this.httpClient.post(`${this._apiEndPoint}/api/v1/items/delete`, itemCodes); + return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/items/delete`, itemCodes); } getTemporalLast(code: string): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/temporal/last`); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/temporal/last`); } getTemporal(code: string, startDate?: Date, endDate?: Date): Observable { var params = new HttpParams(); if (startDate) params = params.append("sd", startDate.toISOString()); if (endDate) params = params.append("ed", endDate.toISOString()); - return this.httpClient.get(`${this._apiEndPoint}/api/v1/items/${code}/temporal/`, { params: params }); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/items/${code}/temporal/`, { params: params }); } postItemTask(item: IItem, task: IItemTask): Observable { - return this.httpClient.post(`${this._apiEndPoint}/api/v1/items/${item.code}/tasks`, task); + return this.httpClient.post(`${this.ApiEndpoint()}/api/v1/items/${item.code}/tasks`, task); } } diff --git a/projects/common/src/lib/services/typeahead.service.ts b/projects/common/src/lib/services/typeahead.service.ts index 180fb5f..d979092 100644 --- a/projects/common/src/lib/services/typeahead.service.ts +++ b/projects/common/src/lib/services/typeahead.service.ts @@ -6,17 +6,18 @@ import { AppConfig } from "../shared/app.config"; @Injectable() export class TypeaheadService { - private _apiEndPoint: string; - constructor(public httpClient: HttpClient, public appConfig: AppConfig) { - this._apiEndPoint = appConfig.getConfig("apiEndPoint"); + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); } getSearchTypeaheadItems(searchText:string,skip:number = 0,take:number = 10): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/typeahead/search/?q=${searchText}&skip=${skip}&take=${take}`); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/typeahead/search/?q=${searchText}&skip=${skip}&take=${take}`); } getTagTypeaheadItems(searchText: string, skip: number = 0, take: number = 10): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/typeahead/tag/?q=${searchText}&skip=${skip}&take=${take}`); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/typeahead/tag/?q=${searchText}&skip=${skip}&take=${take}`); } } diff --git a/projects/common/src/lib/services/user.service.ts b/projects/common/src/lib/services/user.service.ts index 9c5daa4..2c29fc2 100644 --- a/projects/common/src/lib/services/user.service.ts +++ b/projects/common/src/lib/services/user.service.ts @@ -6,13 +6,14 @@ import { AppConfig } from "../shared/app.config"; @Injectable() export class UserService { - private _apiEndPoint: string; - constructor(public httpClient: HttpClient, public appConfig: AppConfig) { - this._apiEndPoint = "";//appConfig.getConfig("apiEndPoint"); + } + + ApiEndpoint() { + return this.appConfig.getConfig("apiEndPoint"); } getCurrentUser(): Observable { - return this.httpClient.get(`${this._apiEndPoint}/api/v1/currentuser`); + return this.httpClient.get(`${this.ApiEndpoint()}/api/v1/currentuser`); } } diff --git a/src/app/app-content.component.ts b/src/app/app-content.component.ts index 9feb023..ea9a83f 100644 --- a/src/app/app-content.component.ts +++ b/src/app/app-content.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-content', - template: '
Hello daar
' + template: '
Hello daar
' }) export class AppContentComponent { } \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index 676801c..18154b0 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,23 +1,9 @@ -

Welcome to {{ title }}!

- Angular Logo

Common Test

-
    -

    Here are some links to help you start:

    - + diff --git a/src/configuration.json b/src/configuration.json index 3c074a5..875949d 100644 --- a/src/configuration.json +++ b/src/configuration.json @@ -1,8 +1,8 @@ { "issuer": "http://accounts.awtest.nl", "clientId": "v1t", - "audience": "http://localhost:8082/,http://awtest.nl/,http://aan.awtest.nl", + "audience": "http://localhost:8083/,http://awtest.nl/,http://aan.awtest.nl", "requireHttps": false, - "apiEndPoint": "http://localhost:8082" + "apiEndPoint": "http://localhost:8083" } \ No newline at end of file