@c8y/ngx-components 1011.0.12 → 1011.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICES +3 -227
- package/bundles/c8y-ngx-components-repository.umd.js +1 -1
- package/bundles/c8y-ngx-components-repository.umd.js.map +1 -1
- package/bundles/c8y-ngx-components-repository.umd.min.js +1 -1
- package/bundles/c8y-ngx-components-repository.umd.min.js.map +1 -1
- package/esm2015/repository/configuration-device-tab/source-code-preview.component.js +2 -2
- package/fesm2015/c8y-ngx-components-repository.js +1 -1
- package/fesm2015/c8y-ngx-components-repository.js.map +1 -1
- package/package.json +2 -2
- package/repository/c8y-ngx-components-repository.metadata.json +1 -1
|
@@ -12,5 +12,5 @@
|
|
|
12
12
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
13
13
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
14
14
|
PERFORMANCE OF THIS SOFTWARE.
|
|
15
|
-
***************************************************************************** */var v,m;function b(e,t,n,i){var r,a=arguments.length,o=a<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,i);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(o=(a<3?r(o):a>3?r(t,n,o):r(t,n))||o);return a>3&&o&&Object.defineProperty(t,n,o),o}function w(e,t,n,i){return new(n||(n=Promise))((function(r,a){function o(e){try{c(i.next(e))}catch(e){a(e)}}function s(e){try{c(i.throw(e))}catch(e){a(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,s)}c((i=i.apply(e,t||[])).next())}))}function S(e,t){var n,i,r,a,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(a){return function(s){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,i&&(r=2&a[0]?i.return:a[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,a[1])).done)return r;switch(i=0,r&&(a=[2&a[0],r.value]),a[0]){case 0:case 1:r=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,i=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(r=o.trys,(r=r.length>0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]<r[3])){o.label=a[1];break}if(6===a[0]&&o.label<r[1]){o.label=r[1],r=a;break}if(r&&o.label<r[2]){o.label=r[2],o.ops.push(a);break}r[2]&&o.ops.pop(),o.trys.pop();continue}a=t.call(e,o)}catch(e){a=[6,e],i=0}finally{n=r=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,s])}}}function x(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,r,a=n.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(i=a.next()).done;)o.push(i.value)}catch(e){r={error:e}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(r)throw r.error}}return o}function I(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(C(arguments[t]));return e}e.RepositoryType=void 0,(m=e.RepositoryType||(e.RepositoryType={})).FIRMWARE="c8y_Firmware",m.SOFTWARE="c8y_Software",m.CONFIGURATION="c8y_ConfigurationDump";var F,T=((v={})[e.RepositoryType.SOFTWARE]="c8y_SoftwareBinary",v[e.RepositoryType.FIRMWARE]="c8y_FirmwareBinary",v[e.RepositoryType.CONFIGURATION]="c8y_ConfigurationDumpBinary",v);e.DeviceConfigurationOperation=void 0,(F=e.DeviceConfigurationOperation||(e.DeviceConfigurationOperation={})).UPLOAD_CONFIG="c8y_UploadConfigFile",F.DOWNLOAD_CONFIG="c8y_DownloadConfigFile",F.CONFIG="c8y_Configuration",F.SEND_CONFIG="c8y_SendConfiguration";var O=function(){function t(e,t,n,i,r,a,o){this.inventory=e,this.inventoryBinary=t,this.operation=n,this.alert=i,this.event=r,this.operationRealtime=a,this.eventBinary=o,this.dateFrom=new Date(0),this.dateTo=new Date(Date.now()+864e5),this.queriesUtil=new c.QueriesUtil}return t.prototype.listRepositoryEntries=function(e,t){var n,i={type:e},r=t&&t.query||{};if(r=this.queriesUtil.addOrderbys(r,[{name:1}],"prepend"),r=this.queriesUtil.addAndFilter(r,i),t&&t.partialTextFilter){var a=t.partialTextFilter,o=a.partialText,s={__or:a.properties.map((function(e){var t;return(t={})[e]="*"+o+"*",t}))};r=this.queriesUtil.addAndFilter(r,s)}return t&&t.partialName&&(r=this.queriesUtil.addAndFilter(r,{name:"*"+t.partialName+"*"})),t&&t.skipLegacy&&(r=this.queriesUtil.addAndFilter(r,{__not:{__has:"url"}})),n=Object.assign({query:this.queriesUtil.buildQuery(r),pageSize:50,withTotalPages:!0},t&&t.params||{}),this.inventory.list(n)},t.prototype.save=function(t,n,i){return void 0===i&&(i={}),w(this,void 0,void 0,(function(){var r,a;return S(this,(function(o){switch(o.label){case 0:switch(n){case e.RepositoryType.CONFIGURATION:Object.assign(i,{type:e.RepositoryType.CONFIGURATION,configurationType:t.selected?t.selected.configurationType:void 0,name:t.version,description:t.description,deviceType:t.deviceType,c8y_Global:{}}),!t.deviceType&&i.id&&(i.deviceType=null),!t.selected&&i.id&&(i.configurationType=null)}return r=i.url,t.binary.url?(i.url=t.binary.url,[3,3]):[3,1];case 1:return t.binary.file?[4,this.inventoryBinary.create(t.binary.file,{c8y_Global:{}})]:[3,3];case 2:a=o.sent(),i.url=a.data.self,o.label=3;case 3:return i.id?[2,this.updateEntry(i,r)]:[2,this.createEntry(i)]}}))}))},t.prototype.create=function(t,n){return w(this,void 0,void 0,(function(){return S(this,(function(i){switch(n){case e.RepositoryType.FIRMWARE:case e.RepositoryType.SOFTWARE:return[2,this.createFirmwareOrSoftware(t,n)]}return[2]}))}))},t.prototype.createFirmwareOrSoftware=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r,a,o,s,c,p,d,u;return S(this,(function(y){switch(y.label){case 0:o=[],s=e.selected.id,c=e.binary,p=c.file,d=c.url,y.label=1;case 1:return y.trys.push([1,9,,10]),p?[4,this.saveBinary(p)]:[3,3];case 2:return n=y.sent().data,i=n.self,o.push(n),[3,4];case 3:i=d,y.label=4;case 4:return[4,this.createOrUpdateRepositoryEntry(e,t)];case 5:return r=y.sent().data,l.isNil(s)&&o.push(r),[4,this.createRepositoryBinary(e,i,t,r)];case 6:return a=y.sent().data,o.push(a),p?[4,this.linkBinary(a,n)]:[3,8];case 7:y.sent(),y.label=8;case 8:return[2,r];case 9:throw u=y.sent(),this.cleanUp(o),this.errorMsg(),u;case 10:return[2]}}))}))},t.prototype.saveBinary=function(e){return this.inventoryBinary.create(e,{c8y_Global:{}})},t.prototype.createOrUpdateRepositoryEntry=function(e,t){var n=e.selected,i=n.id,r=n.name,a=e.description,o=e.deviceType,s={id:i,name:i?void 0:r,description:a,type:i?void 0:t,c8y_Global:{}};return o&&l.set(s,"c8y_Filter.type",o),i?this.inventory.update(s):this.inventory.create(s)},t.prototype.createRepositoryBinary=function(e,t,n,i){var r=this.prepareRepositoryBinaryMO(e,t,n);return this.inventory.childAdditionsCreate(r,i)},t.prototype.prepareRepositoryBinaryMO=function(e,t,n){var i,r=e.version,a=e.patchVersion,o=e.dependency,s=((i={type:T[n]})[n]={url:t},i.c8y_Global={},i);return o?(l.set(s,[n,"version"],a),l.assign(s,{c8y_Patch:{dependency:o.c8y_Firmware.version}})):l.set(s,[n,"version"],r),s},t.prototype.linkBinary=function(e,t){return w(this,void 0,void 0,(function(){var n,i;return S(this,(function(r){return n=e.id,t?(i=t.id,[2,this.inventory.childAdditionsAdd(i,n)]):[2]}))}))},t.prototype.cleanUp=function(e){var t=this;e.forEach((function(e){var n=e.c8y_IsBinary;l.isUndefined(n)?t.delete(e):t.inventoryBinary.delete(e)}))},t.prototype.delete=function(e){return this.inventory.delete(e,{forceCascade:!0})},t.prototype.errorMsg=function(){var e=n.gettext("Failed to save");this.alert.danger(e)},t.prototype.getBaseVersionsCount$=function(e){return this.isLegacyEntry(e)?p.of(1):p.from(this.listBaseVersions(e,{pageSize:1,withTotalPages:!0})).pipe(d.map((function(e){return e.paging.totalPages})))},t.prototype.getBaseVersionFromMO=function(e){return this.isPatch(e)?l.get(e,"c8y_Patch.dependency"):l.get(e,"c8y_Firmware.version")},t.prototype.isPatch=function(e){return!!l.get(e,"c8y_Patch.dependency")},t.prototype.getPatchVersionsCount$=function(e,t){return this.isLegacyEntry(t)?p.of(0):p.from(this.listPatchVersions(e,t,{pageSize:1,withTotalPages:!0})).pipe(d.map((function(e){return e.paging.totalPages})))},t.prototype.isLegacyEntry=function(e){return Boolean(e.url)},t.prototype.listAllVersions=function(e,t){if(void 0===t&&(t={}),this.isLegacyEntry(e))return this.getBaseVersionResultListForLegacyEntry(e);return this.listChildren(e,{__filter:{},__orderby:[{"creationTime.date":-1},{creationTime:-1}]},t)},t.prototype.listBaseVersions=function(e,t){if(void 0===t&&(t={}),this.isLegacyEntry(e))return this.getBaseVersionResultListForLegacyEntry(e);return this.listChildren(e,{__filter:{__not:{__has:"c8y_Patch"}},__orderby:[{"creationTime.date":-1},{creationTime:-1}]},t)},t.prototype.listPatchVersions=function(e,t,n){void 0===n&&(n={});var i={__filter:{"c8y_Patch.dependency":l.isString(t)?t:l.get(t,"c8y_Firmware.version")},__orderby:[{"creationTime.date":-1},{creationTime:-1}]};return this.listChildren(e,i,n)},t.prototype.listBaseVersionAndPatches=function(e,t,n){if(void 0===n&&(n={}),this.isLegacyEntry(e))return Promise.resolve({data:[Object.assign({c8y_Firmware:{version:e.version,url:e.url}},e)]});var i={__filter:{__or:{"c8y_Patch.dependency":t.c8y_Firmware.version,"c8y_Firmware.version":t.c8y_Firmware.version}},__orderby:[{"c8y_Patch.dependency":1},{"c8y_Firmware.version":1}]};return this.listChildren(e,i,n)},t.prototype.listChildren=function(e,t,n){void 0===t&&(t={}),void 0===n&&(n={});var i={__bygroupid:e.id},r=this.queriesUtil.addAndFilter(t,i);return n.withTotalPages=!0,this.inventory.listQuery(r,n)},t.prototype.fetchAllItemsFromList=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a;return S(this,(function(o){switch(o.label){case 0:return e.then?[3,1]:(t=I(e),[3,5]);case 1:return[4,e];case 2:n=o.sent(),i=n.paging,r=n.data,t=I(r),o.label=3;case 3:return i&&i.nextPage?[4,i.next()]:[3,5];case 4:return a=o.sent(),i=a.paging,r=a.data,t=I(t,r),[3,3];case 5:return[2,t]}}))}))},t.prototype.getRepositoryEntryMO$=function(e){if(!e)return p.of(void 0);var t=C(l.get(e,"additionParents.references"),1)[0],n=l.get(t,"managedObject.id");return n?p.from(this.inventory.detail(n,{withChildren:!1})).pipe(d.map((function(e){return e.data}))):p.of(void 0)},t.prototype.getRepositoryBinaryMoByVersion=function(e,t,n){var i,r,a=void 0===n?{}:n,o=a.skipLegacy,s=void 0!==o&&o,c=a.filters,p=void 0===c?{}:c,d=e.version,u=e.url,y=e.name,f=T[t],h=((i={})[t+".version"]=d,i[t+".url"]=u,i.type=f,i),g={url:u,type:t,name:y};return p=Object.assign({withChildren:!1,withParents:!0},p),r=s?{__and:Object.assign({},h)}:{__or:[{__and:Object.assign({},h)},{__and:Object.assign({},g)}]},this.inventory.listQuery(r,p).then((function(e){var t=e.data;return l.head(t)}))},t.prototype.getBinaryName$=function(e){var t=this;if(!e)return p.of("---");var n=this.inventoryBinary.getIdFromUrl(e);return n?p.defer((function(){return t.inventory.detail(n).then((function(e){return e.data}))})).pipe(d.map((function(e){return e.name}))):p.of(e)},t.prototype.getDeviceTypeQuery=function(t,n){var i={type:t};return t===e.RepositoryType.CONFIGURATION?n.type&&(i=this.queriesUtil.addAndFilter(i,{__or:[{deviceType:n.type},{__not:{__has:"deviceType"}}]})):i=this.queriesUtil.addAndFilter(i,{__or:[{"c8y_Filter.type":n.type},{"c8y_Filter.type":""},{__not:{__has:"c8y_Filter.type"}}]}),i},t.prototype.getConfigurationTypeQuery=function(t,n){var i=this.getDeviceTypeQuery(e.RepositoryType.CONFIGURATION,t);return this.queriesUtil.addAndFilter(i,{__or:[{configurationType:n},{configurationType:""},{__not:{__has:"configurationType"}}]})},t.prototype.getDeviceSoftwareList=function(e){return e.c8y_SoftwareList?l.cloneDeep(e.c8y_SoftwareList):e.c8y_Software?l.map(e.c8y_Software,(function(e,t){return{name:t,version:e}})):[]},t.prototype.createSoftwareUpdateOperation=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n=this.getSoftwareUpdateOperation(e,t),[4,this.operation.create(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getSoftwareUpdateOperation=function(e,t){var n={deviceId:e.id,description:"Apply software changes: "+t.map((function(e){return e.action+' "'+e.name+'"'+(e.version?" (version: "+e.version+")":"")})).join(", ")};return e.c8y_SupportedOperations.includes("c8y_SoftwareUpdate")?n.c8y_SoftwareUpdate=l.cloneDeep(t):e.c8y_SupportedOperations.includes("c8y_SoftwareList")?(n.c8y_SoftwareList=l.cloneDeep(e.c8y_SoftwareList)||[],t.forEach((function(e){var t=l.pick(e,["name","version","url"]);"delete"===e.action&&l.remove(n.c8y_SoftwareList,t),"install"===e.action&&n.c8y_SoftwareList.push(t)}))):e.c8y_SupportedOperations.includes("c8y_Software")&&(n.c8y_Software=l.cloneDeep(e.c8y_Software)||{},t.forEach((function(e){"delete"===e.action&&delete n.c8y_Software[e.name],"install"===e.action&&(n.c8y_Software[e.name]=e.version)}))),n},t.prototype.getDeviceSoftwareChangesFromOperation=function(e,t){return e.c8y_SoftwareUpdate?l.cloneDeep(e.c8y_SoftwareUpdate):e.c8y_SoftwareList?this.getDeviceSoftwareChangesFromSoftwareListOperation(e,t):e.c8y_Software?this.getDeviceSoftwareChangesFromSoftwareOperation(e,t):[]},t.prototype.createFirmwareUpdateOperation=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n=this.getFirmwareUpdateOperation(e,t),[4,this.operation.create(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getFirmwareUpdateOperation=function(e,t){return delete t.id,{deviceId:e.id,description:'Update firmware to: "'+t.name+'"'+(t.version?" (version: "+t.version+")":""),c8y_Firmware:Object.assign({},t)}},t.prototype.getUploadConfigurationFileOperation=function(e,t,n){return void 0===n&&(n=!1),n?{deviceId:e.id,description:"Retrieve configuration snapshot from device "+e.name,c8y_UploadConfigFile:{}}:{deviceId:e.id,description:"Retrieve "+t+" configuration snapshot from device "+e.name,c8y_UploadConfigFile:{type:t}}},t.prototype.getDownloadConfigurationFileOperation=function(e,t,n,i){return void 0===i&&(i=!1),i?{deviceId:e.id,description:"Send configuration snapshot "+n.name+" to device "+e.name,c8y_DownloadConfigFile:{url:n.binaryUrl,c8y_ConfigurationDump:{id:n.id}}}:{deviceId:e.id,description:"Send configuration snapshot "+n.name+" of configuration type "+t+" to device "+e.name,c8y_DownloadConfigFile:{url:n.binaryUrl,type:t}}},t.prototype.getLastFirmwareUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_Firmware"})])]}))}))},t.prototype.getLastSoftwareUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_SoftwareUpdate"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_SoftwareList"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_Software"})])]}))}))},t.prototype.getFirstMatchingOperation=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:t=null,l.label=1;case 1:l.trys.push([1,6,7,8]),n=x(e),i=n.next(),l.label=2;case 2:return i.done?[3,5]:(r=i.value,[4,this.operation.list(r)]);case 3:if((a=l.sent().data).length)return t=a[0],[3,5];l.label=4;case 4:return i=n.next(),[3,2];case 5:return[3,8];case 6:return o=l.sent(),s={error:o},[3,8];case 7:try{i&&!i.done&&(c=n.return)&&c.call(n)}finally{if(s)throw s.error}return[7];case 8:return[2,t]}}))}))},t.prototype.createObservedOperation=function(e){var t=this;return p.from(this.operation.create(e)).pipe(d.map((function(e){return e.data})),d.take(1),d.switchMap((function(e){return t.observeOperation(e)})))},t.prototype.observeOperation=function(e){var t=this,n=p.of(e),i=n.pipe(d.switchMap((function(e){return t.operationRealtime.onAll$(e.deviceId)})),d.map((function(e){return e.data})),d.withLatestFrom(n),d.filter((function(e){var t=C(e,2),n=t[0],i=t[1];return n.id===i.id})),d.switchMap((function(e){var t=C(e,1)[0];return t.status===c.OperationStatus.FAILED?p.throwError(t):p.of(t)})),d.takeWhile((function(e){return e.status!==c.OperationStatus.SUCCESSFUL}),!0));return p.merge(n,i)},t.prototype.getLatestConfigurationEvent=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n={source:e,type:t,dateFrom:this.dateFrom.toISOString(),dateTo:this.dateTo.toISOString(),pageSize:1},[4,this.event.list(n)];case 1:return[2,i.sent().data[0]]}}))}))},t.prototype.getConfigFileOperationList=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n={deviceId:e,fragmentType:t,dateFrom:this.dateFrom.toISOString(),dateTo:this.dateTo.toISOString(),revert:!0,pageSize:2e3},[4,this.operation.list(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getConfigSnapshot=function(e,t){return w(this,void 0,void 0,(function(){var i,r,a,o;return S(this,(function(s){switch(s.label){case 0:return[4,this.getLatestConfigurationEvent(e.id,t)];case 1:if(!(i=s.sent()))return[3,6];r={time:i.time,name:i.text,deviceType:e.type,configurationType:t},s.label=2;case 2:return s.trys.push([2,5,,6]),a=r,[4,this.eventBinary.download(i)];case 3:return[4,s.sent().text()];case 4:return a.binary=s.sent(),i.c8y_IsBinary&&(r.binaryType=i.c8y_IsBinary.type),[3,6];case 5:return s.sent(),o=n.gettext("Could not get the binary."),this.alert.danger(o),[3,6];case 6:return[2,r]}}))}))},t.prototype.getLegacyConfigSnapshot=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a;return S(this,(function(o){switch(o.label){case 0:return[4,this.inventory.detail(e,{withChildren:!1})];case 1:if(i=o.sent().data,!(r=i.c8y_ConfigurationDump&&i.c8y_ConfigurationDump.id))return[2];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.inventory.detail(r)];case 3:return n=o.sent().data,[3,5];case 4:return o.sent(),[3,5];case 5:return n?(t={time:n.creationTime,name:n.name},a=t,[4,this.getBinaryText(n.url,{allowExternal:!1})]):[3,7];case 6:a.binary=o.sent(),o.label=7;case 7:return[2,t]}}))}))},t.prototype.getBinaryText=function(e,t){return w(this,void 0,void 0,(function(){var n,i;return S(this,(function(r){switch(r.label){case 0:return(n=this.inventoryBinary.getIdFromUrl(e))||!t.allowExternal?[3,2]:[4,this.getExternalBinaryResponse(e,t)];case 1:return i=r.sent(),[3,4];case 2:return[4,this.getInternalBinaryResponse(n,t)];case 3:i=r.sent(),r.label=4;case 4:return i?[2,i.text()]:[2,null]}}))}))},t.prototype.getBinaryFile=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r,a,o,s;return S(this,(function(c){switch(c.label){case 0:return(n=this.inventoryBinary.getIdFromUrl(e))||t.allowExternal?[4,this.inventory.detail(n)]:[2,null];case 1:return i=c.sent().data,r=i.name,a=i.contentType,n?[4,this.getInternalBinaryResponse(n)]:[3,3];case 2:return o=c.sent(),[3,5];case 3:return[4,this.getExternalBinaryResponse(e)];case 4:o=c.sent(),c.label=5;case 5:return[4,o.arrayBuffer()];case 6:return s=c.sent(),[2,new File([s],r,{type:a})]}}))}))},t.prototype.getLastConfigUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_Configuration"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_SendConfiguration"})])]}))}))},t.prototype.createTextBasedConfigurationReloadOperation=function(e){return{deviceId:e.id,description:n.gettext("Requested current configuration"),c8y_SendConfiguration:{}}},t.prototype.createTextBasedConfigurationUpdateOperation=function(e,t){return{deviceId:e.id,description:n.gettext("Configuration update"),c8y_Configuration:{config:t}}},t.prototype.getBinary=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(i){switch(i.label){case 0:return i.trys.push([0,2,,3]),[4,this.inventoryBinary.download(e)];case 1:return[2,i.sent()];case 2:return i.sent(),t=n.gettext("Could not get the binary."),this.alert.danger(t),[3,3];case 3:return[2]}}))}))},t.prototype.getSnapshotsFromRepository=function(t,n){return w(this,void 0,void 0,(function(){var i;return S(this,(function(r){switch(r.label){case 0:return i=this.getConfigurationTypeQuery(t,n),[4,this.listRepositoryEntries(e.RepositoryType.CONFIGURATION,{query:i,params:{pageSize:100}})];case 1:return[2,r.sent().data]}}))}))},t.prototype.getInternalBinaryResponse=function(e,t){return void 0===t&&(t={}),w(this,void 0,void 0,(function(){var i,r;return S(this,(function(a){switch(a.label){case 0:return a.trys.push([0,2,,3]),[4,this.inventoryBinary.download(e)];case 1:return i=a.sent(),[3,3];case 2:return a.sent(),t.noAlerts||(r=n.gettext("Could not get the binary."),this.alert.danger(r)),[3,3];case 3:return[2,i]}}))}))},t.prototype.getExternalBinaryResponse=function(e,t){return void 0===t&&(t={}),w(this,void 0,void 0,(function(){var i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,2,,3]),[4,fetch(e)];case 1:if((r=o.sent()).status>=400)throw i;return i=r,[3,3];case 2:return o.sent(),t.noAlerts||(a=n.gettext("Could not get the external binary"),this.alert.danger(a)),[3,3];case 3:return[2,i]}}))}))},t.prototype.createEntry=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return[4,this.inventoryBinary.getIdFromUrl(e.url)];case 1:return t=i.sent(),[4,this.inventory.create(e)];case 2:return n=i.sent(),t?[4,this.inventory.childAdditionsAdd(t,n.data)]:[3,4];case 3:i.sent(),i.label=4;case 4:return[2,n]}}))}))},t.prototype.updateEntry=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r;return S(this,(function(a){switch(a.label){case 0:return[4,this.inventoryBinary.getIdFromUrl(t)];case 1:return n=a.sent(),[4,this.inventoryBinary.getIdFromUrl(e.url)];case 2:return i=a.sent(),n&&n!==i?(r=this.inventoryBinary.getIdFromUrl(t),[4,this.inventoryBinary.delete(r)]):[3,4];case 3:a.sent(),a.label=4;case 4:return i?[4,this.inventory.childAdditionsAdd(i,e)]:[3,6];case 5:a.sent(),a.label=6;case 6:return[2,this.inventory.update(e)]}}))}))},t.prototype.getBaseVersionResultListForLegacyEntry=function(e){var t;return Promise.resolve({res:{},data:[Object.assign(Object.assign({},e),(t={},t[e.type]={version:e.version,url:e.url},t))]})},t.prototype.getDeviceSoftwareChangesFromSoftwareListOperation=function(e,t){var n=[];return l.forEach(t.c8y_SoftwareList,(function(t){var i=l.find(e.c8y_SoftwareList,{name:t.name});(i&&i.version)!==(t&&t.version)&&n.push(Object.assign(Object.assign({},t),{action:"delete"}))})),l.forEach(e.c8y_SoftwareList,(function(e){var i=l.find(t.c8y_SoftwareList,{name:e.name});(e&&e.version)!==(i&&i.version)&&n.push(Object.assign(Object.assign({},e),{action:"install"}))})),n},t.prototype.getDeviceSoftwareChangesFromSoftwareOperation=function(e,t){var n=[];return l.forEach(t.c8y_Software,(function(t,i){e.c8y_Software[i]!==t&&n.push({name:i,version:t,action:"delete"})})),l.forEach(e.c8y_Software,(function(e,i){(t.c8y_Software&&t.c8y_Software[i])!==e&&n.push({name:i,version:e,action:"install"})})),n},t}();O.decorators=[{type:t.Injectable}],O.ctorParameters=function(){return[{type:c.InventoryService},{type:c.InventoryBinaryService},{type:c.OperationService},{type:n.AlertService},{type:c.EventService},{type:n.OperationRealtimeService},{type:c.EventBinaryService}]};var $=function(){function i(e,i,r){this.modal=e,this.repositoryService=i,this.alert=r,this.saved=new t.EventEmitter,this.onInput=new p.BehaviorSubject(""),this.model={selected:void 0,version:void 0,description:void 0,deviceType:void 0,binary:{file:void 0,url:void 0}},this.saving=!1,this.firmwarePreselected=!1,this.textForFirmwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /firmware/binaries/firmware1.bin\n https://firmware/binary/123\n ftp://firmware/binary/123.tar.gz\n ")}return i.prototype.ngOnInit=function(){this.setInitialState(),this.loadFirmwares()},i.prototype.setInitialState=function(){this.model.selected&&(this.firmwarePreselected=!0)},i.prototype.loadFirmwares=function(){var e=this;this.inputSubscription$=this.onInput.pipe(d.tap((function(){e.firmwarePreselected||(e.model.description=null,e.form&&e.form.form.get("description").reset())})),d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return e.getFirmwareResult(t)}))).subscribe((function(t){e.firmwaresResult=t}))},i.prototype.getFirmwareResult=function(t){return p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialName:t,skipLegacy:!0}))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repositoryService.create(this.model,e.RepositoryType.FIRMWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Firmware added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.ngOnDestroy=function(){this.inputSubscription$.unsubscribe()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i.prototype.onFirmwareSelect=function(e){l.assign(this.model,{selected:e,description:e.description,deviceType:l.get(e,"c8y_Filter.type")})},i}();$.decorators=[{type:t.Component,args:[{selector:"c8y-add-firmware-software-modal",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-firmware\'"></i>\n <h4 translate>\n Add firmware\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom" *ngIf="!firmwarePreselected">\n <p class="lead m-0" translate>\n Select or create new firmware\n </p>\n </div>\n <form\n class="d-contents"\n autocomplete="off"\n #firmwareForm="ngForm"\n (ngSubmit)="firmwareForm.form.valid && save()"\n >\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="firmwarePreselected">\n <c8y-form-group>\n <label for="firmwareName" translate>Firmware</label>\n <c8y-typeahead\n [(ngModel)]="model.selected"\n name="firmwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="onInput.next($event)"\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let firmware of firmwaresResult;\n loadMore: \'auto\';\n notFound: notFoundTemplate\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="onFirmwareSelect(firmware)"\n [active]="model.selected === firmware"\n >\n <c8y-highlight\n [text]="firmware.name || \'--\'"\n [pattern]="onInput | async"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="(onInput | async)?.length > 0">\n <span translate>No match found, add new`firmware`? </span>\n <button\n title="{{ \'Create new`firmware`\' | translate }}"\n type="button"\n class="btn btn-primary btn-xs m-l-16"\n translate\n >\n Create new`firmware`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="firmwareDescription" translate>Description</label>\n <input\n id="firmwareDescription"\n class="form-control"\n autocomplete="off"\n name="description"\n [(ngModel)]="model.description"\n placeholder="{{ \'e.g. Firmware for hardware revision b\' | translate }}"\n [disabled]="model.selected?.id"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label class="control-label" for="firmwareDeviceTypeFilter">\n {{ \'Device type filter\' | translate }}\n <button\n class="btn btn-clean text-primary"\n popover="{{\n \'If the filter is set, the firmware will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\'\n | translate\n }}"\n triggers="focus"\n container="body"\n placement="right"\n >\n <i [c8yIcon]="\'question-circle-o\'"></i>\n </button>\n </label>\n <input\n id="firmwareDeviceTypeFilter"\n class="form-control"\n name="firmwareDeviceTypeFilter"\n [(ngModel)]="model.deviceType"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [disabled]="model.selected?.id"\n />\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="firmwareVersion" translate>Version</label>\n <input\n id="firmwareVersion"\n class="form-control"\n autocomplete="off"\n name="version"\n [(ngModel)]="model.version"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Firmware file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForFirmwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n\n <button\n title="{{ \'Add firmware\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !firmwareForm.form.valid ||\n firmwareForm.form.pristine ||\n saving ||\n (!model.binary?.url && !model.binary?.file)\n "\n translate\n >\n Add firmware\n </button>\n </div>\n </form>\n</div>\n'}]}],$.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},$.propDecorators={form:[{type:t.ViewChild,args:["firmwareForm",{static:!1}]}],saved:[{type:t.Output}]};var E=function(){function i(i,r,a){var o=this;this.modal=i,this.repository=r,this.alert=a,this.saved=new t.EventEmitter,this.textForFirmwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /firmware/binaries/firmware1.bin\n https://firmware/binary/123\n ftp://firmware/binary/123.tar.gz\n "),this.model={selected:void 0,dependency:null,patchVersion:void 0,binary:{file:void 0,url:void 0}},this.firmwareInput$=new p.BehaviorSubject(""),this.firmwares$=this.firmwareInput$.pipe(d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return p.from(o.repository.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialName:t,skipLegacy:!0}))})),d.shareReplay(1)),this.firmwareSelected$=new p.BehaviorSubject(null),this.patchDependencyInput$=new p.BehaviorSubject(""),this.saving=!1,this.firmwarePreselected=!1,this.baseVersions$=p.merge(this.firmwareInput$.pipe(d.tap((function(){o.model.dependency=null,o.form&&o.form.form.get("patchDependency").reset()})),d.switchMap((function(){return p.of(null)}))),this.firmwareSelected$).pipe(d.switchMap((function(e){return e?o.repository.listBaseVersions(e):p.of(null)})),d.shareReplay(1)),this.baseVersionsFilterPipe=p.pipe(d.switchMap((function(e){return o.patchDependencyInput$.pipe(d.map((function(t){return e.filter((function(e){var n=e.c8y_Firmware.version.toLowerCase();return 0===t.length||n.indexOf(t.toLowerCase())>-1}))})))})))}return i.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){return this.setInitialState(),[2]}))}))},i.prototype.setInitialState=function(){this.model.selected&&(this.firmwarePreselected=!0,this.firmwareSelected$.next(this.model.selected))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repository.create(this.model,e.RepositoryType.FIRMWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Firmware patch added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i}();E.decorators=[{type:t.Component,args:[{selector:"c8y-add-firmware-patch-modal.component",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-firmware\'"></i>\n <h4 translate>\n Add firmware patch\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom">\n <p class="lead m-0" translate>\n Select a firmware version\n </p>\n </div>\n\n <form\n class="d-contents"\n autocomplete="off"\n #firmwarePatchForm="ngForm"\n (ngSubmit)="firmwarePatchForm.form.valid && save()">\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="firmwarePreselected">\n <c8y-form-group>\n <label for="firmwareName" translate>Firmware</label>\n <c8y-typeahead\n [ngModel]="model.selected"\n name="firmwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="firmwareInput$.next($event)"\n [allowFreeEntries]="false"\n [required]="true"\n >\n <c8y-li\n *c8yFor="let firmware of firmwares$ | async; loadMore: \'auto\'"\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="model.selected = firmware; firmwareSelected$.next(firmware)"\n [active]="model.selected === firmware"\n >\n <c8y-highlight\n [text]="firmware.name || \'--\'"\n [pattern]="firmwareInput$ | async"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages\n ><c8y-message\n name="notExisting"\n [text]="\'Select one of the existing firmwares.\' | translate"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="patchDependency" class="m-r-8" translate>Version</label>\n <c8y-typeahead\n [ngModel]="model.dependency"\n name="patchDependency"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="patchDependencyInput$.next($event)"\n [displayProperty]="\'c8y_Firmware.version\'"\n [allowFreeEntries]="false"\n [disabled]="\n (baseVersions$ | async) === null || (baseVersions$ | async)?.data.length === 0\n "\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let baseVersion of baseVersions$;\n loadMore: \'auto\';\n pipe: baseVersionsFilterPipe\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="model.dependency = baseVersion"\n [active]="model.dependency === baseVersion"\n >\n <c8y-highlight\n [text]="baseVersion.c8y_Firmware.version || \'--\'"\n [pattern]="patchDependencyInput$ | async"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages\n ><c8y-message\n name="notExisting"\n [text]="\'Select one of the existing versions.\' | translate"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="patchVersion" translate>Patch</label>\n <input\n id="patchVersion"\n class="form-control"\n autocomplete="off"\n name="patchVersion"\n [(ngModel)]="model.patchVersion"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Patch file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForFirmwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n <button\n title="{{ \'Add firmware patch\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !firmwarePatchForm.form.valid ||\n firmwarePatchForm.form.pristine ||\n (!model.binary?.url && !model.binary?.file) ||\n saving\n "\n translate\n >\n Add firmware patch\n </button>\n </div>\n </form>\n</div>\n'}]}],E.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},E.propDecorators={saved:[{type:t.Output}],dropdown:[{type:t.ViewChild,args:["dropdown",{static:!1}]}],form:[{type:t.ViewChild,args:["firmwarePatchForm",{static:!1}]}]};var R=function(){function t(t,i,r,a,o,s,c){var l=this;this.repositoryService=t,this.modalService=i,this.bsModalService=r,this.translateService=a,this.alertService=o,this.router=s,this.activatedRoute=c,this.textFilter$=new p.BehaviorSubject(""),this.reload$=new p.BehaviorSubject(null),this.reloading=!1,this.firmwares$=p.combineLatest(this.textFilter$.pipe(d.debounceTime(400),d.distinctUntilChanged()),this.reload$).pipe(d.tap((function(){l.reloading=!0})),d.switchMap((function(e){var t=C(e,1)[0];return l.getFirmwares(t)})),d.tap((function(){l.reloading=!1})),d.shareReplay(1)),this.canAddFirmwarePatch$=p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{skipLegacy:!0})).pipe(d.map((function(e){return e.data.length>0}))),this.isLegacy=this.repositoryService.isLegacyEntry.bind(this.repositoryService),this.DEVICE_TYPE_NOT_AVAILABLE=n.gettext("No device type available")}return t.prototype.getFirmwares=function(t){var n={partialText:t,properties:["name","description","c8y_Filter.type"]};return this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialTextFilter:n})},t.prototype.addFirmware=function(){var e=this;this.bsModalService.show($,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editFirmware(t)}))},t.prototype.addFirmwarePatch=function(){var e=this;this.bsModalService.show(E,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editFirmware(t)}))},t.prototype.editFirmware=function(e){this.router.navigate([e.id],{relativeTo:this.activatedRoute})},t.prototype.deleteFirmware=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware"),i="\n "+this.translateService.instant(n.gettext('You are about to delete firmware "{{ name }}" with all its versions and patches.'),{name:e.name})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware deleted.")),this.reload$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},t.prototype.getBaseVersionsCount$=function(e){var t=this;return this.firmwares$.pipe(d.switchMap((function(){return t.repositoryService.getBaseVersionsCount$(e)})),d.shareReplay(1))},t.prototype.getDeviceTypeTitle=function(e){return l.get(e,"c8y_Filter.type",this.translateService.instant(this.DEVICE_TYPE_NOT_AVAILABLE))},t}();R.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-list",template:'<c8y-title>\n {{ \'Firmware repository\' | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]="\'left\'" itemClass="navbar-form">\n <div class="input-group input-group-search">\n <input class="form-control"\n type="search"\n title="{{ \'Filter firmware…\' | translate }}"\n placeholder="{{ \'Filter firmware…\' | translate }}"\n [ngModel]="textFilter$ | async"\n (ngModelChange)="textFilter$.next($event)"\n />\n <span class="input-group-addon">\n <i\n c8yIcon="search"\n *ngIf="(textFilter$ | async).length === 0"\n ></i>\n <i class="text-muted"\n c8yIcon="times"\n *ngIf="(textFilter$ | async).length > 0"\n (click)="textFilter$.next(\'\')"\n ></i>\n </span>\n </div>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" \n title="{{ \'Add firmware\' | translate }}"\n (click)="addFirmware()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n *ngIf="canAddFirmwarePatch$ | async"\n title="{{ \'Add firmware patch\' | translate }}"\n (click)="addFirmwarePatch()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware patch\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n title="{{ \'Reload\' | translate }}"\n (click)="reload$.next()"\n >\n <i c8yIcon="refresh"\n [ngClass]="{ \'icon-spin\': reloading }"\n ></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state--\x3e\n<div class="c8y-empty-state text-center"\n *ngIf="(firmwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length === 0"\n>\n <h1 class="c8y-icon-duocolor"\n c8yIcon="c8y-firmware"\n ></h1>\n <h3 translate>\n No firmwares to display.\n </h3>\n <p translate>\n Add a new firmware by clicking below.\n </p>\n <p>\n <button class="btn btn-primary"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addFirmware()"\n translate\n >\n Add firmware\n </button>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div class="c8y-empty-state"\n *ngIf="(firmwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length > 0"\n >\n <h1 class="c8y-icon-duocolor"\n c8yIcon="search"></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n<c8y-list-group class="m-b-24"\n *ngIf="(firmwares$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': (firmwares$ | async)?.data.length < 10 }"\n \n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs">\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-3">\n {{\'Firmware\' | translate}}\n </div>\n <div class="col-4">\n {{\'Description\' | translate}}\n </div>\n <div class="col-3">\n {{\'Device type\' | translate}}\n </div>\n <div class="col-2">\n {{\'Versions\' | translate}}\n </div>\n </c8y-li-body>\n </c8y-li>\n\n <c8y-li *c8yFor="let firmware of firmwares$ | async; let i = index; loadMore: \'auto\'">\n <c8y-li-icon icon="c8y-firmware"></c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <button class="btn-clean col-3"\n (click)="editFirmware(firmware)"\n >\n <span class="text-truncate"\n title="{{ firmware.name }}"\n >\n {{ firmware.name }}\n </span>\n </button>\n <div class="col-4">\n <p class="text-truncate"\n title="{{ firmware.description }}"\n >\n <span class="text-label-small m-r-4 visible-xs-inline">\n {{\'Description\' | translate }}\n </span>\n <span *ngIf="firmware.description; else emptyDescription">\n {{ firmware.description }}\n </span>\n </p>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n <div class="col-3">\n <div class="text-truncate">\n <span class="text-label-small m-r-4 visible-xs-inline" translate>\n Device type\n </span>\n <span\n *ngIf="firmware.c8y_Filter?.type; else emptyText"\n title="{{ firmware.c8y_Filter?.type }}"\n >\n {{ firmware.c8y_Filter?.type }}\n </span>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n </div>\n <div class="col-2">\n <span class="label label-warning flex-item-right-sm"\n *ngIf="isLegacy(firmware)"\n >\n <span translate>\n Legacy\n </span>\n </span>\n\n <span *ngIf="!isLegacy(firmware)">\n <span *ngIf="(getBaseVersionsCount$(firmware) | async) === null">\n <span class="label label-info flex-item-right-sm">\n <i c8yIcon="circle-o-notch" class="icon-spin"></i>\n </span>\n </span>\n <span *ngIf="(getBaseVersionsCount$(firmware) | async) !== null">\n <span [ngPlural]="getBaseVersionsCount$(firmware) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>\n No versions\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info flex-item-right-sm">\n <span translate>\n 1 version\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info flex-item-right-sm">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getBaseVersionsCount$(firmware) | async }"\n >\n {{ count }} versions\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n\n <c8y-li-action\n (click)="editFirmware(firmware)"\n icon="pencil"\n >\n {{ \'Edit\' | translate }}\n </c8y-li-action>\n\n <c8y-li-action\n (click)="deleteFirmware(firmware)"\n icon="trash"\n >\n {{ \'Delete\' | translate }}\n </c8y-li-action>\n </c8y-li>\n</c8y-list-group>\n'}]}],R.ctorParameters=function(){return[{type:O},{type:n.ModalService},{type:y.BsModalService},{type:f.TranslateService},{type:n.AlertService},{type:u.Router},{type:u.ActivatedRoute}]},b([n.memoize(l.property("id"))],R.prototype,"getBaseVersionsCount$",null);var _=function(){function e(e,t,n,i,r,a,o){var s=this;this.activatedRoute=e,this.inventoryService=t,this.repositoryService=n,this.alertService=i,this.translateService=r,this.modalService=a,this.bsModalService=o,this.reload$=new p.Subject,this.reloading$=new p.BehaviorSubject(!1),this.updateFirmware$=new p.Subject,this.firmwareUpdated$=new p.Subject,this.baseVersionsUpdated$=new p.Subject,this.patchVersionsUpdated$=new p.Subject,this.firmware$=p.merge(this.activatedRoute.params.pipe(d.map((function(e){return e.id})),d.switchMap((function(e){return p.defer((function(){return s.inventoryService.detail(e).then((function(e){return e.data}))}))}))),this.reload$.pipe(d.tap((function(){return s.reloading$.next(!0)})),d.switchMap((function(){return s.activatedRoute.params})),d.map((function(e){return e.id})),d.switchMap((function(e){return p.defer((function(){return s.inventoryService.detail(e).then((function(e){return e.data}))}))})),d.tap((function(){return s.reloading$.next(!1)}))),this.firmwareUpdated$).pipe(d.shareReplay(1)),this.baseVersions$=p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return s.firmware$})),d.switchMap((function(e){return s.repositoryService.listBaseVersions(e)})),d.shareReplay(1)),this.isLegacy$=this.firmware$.pipe(d.map((function(e){return s.repositoryService.isLegacyEntry(e)})),d.shareReplay(1)),this.canAddPatchVersions$=p.combineLatest(this.isLegacy$,this.baseVersions$.pipe(d.map((function(e){return e.data.length>0})))).pipe(d.map((function(e){var t=C(e,2),n=t[0],i=t[1];return!n&&i}))),this.expanded={},this.destroy$=new p.Subject}return e.prototype.ngOnInit=function(){var e=this;this.updateFirmware$.pipe(d.withLatestFrom(this.firmware$),d.switchMap((function(t){var n=C(t,2),i=n[0],r=n[1];return e.inventoryService.update(Object.assign({id:r.id},i))})),d.map((function(e){return e.data})),d.tap((function(t){return e.firmwareUpdated$.next(t)})),d.tap((function(){return e.alertService.success(n.gettext("Saved."))})),d.takeUntil(this.destroy$)).subscribe()},e.prototype.getPatchVersionsCount$=function(e){var t=this;return p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return t.firmware$})),d.switchMap((function(n){return t.repositoryService.getPatchVersionsCount$(n,e)})),d.shareReplay(1))},e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.getPatchVersions$=function(e){var t=this;return p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return t.firmware$})),d.switchMap((function(n){return t.repositoryService.listPatchVersions(n,e)})),d.shareReplay(1))},e.prototype.addBaseVersion=function(){var e=this;this.firmware$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t,description:t.description}}};return e.bsModalService.show($,n).content.saved}))).subscribe((function(){return e.baseVersionsUpdated$.next()}))},e.prototype.addPatchVersion=function(){var e=this;this.firmware$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t}}};return e.bsModalService.show(E,n).content.saved}))).subscribe((function(){return e.patchVersionsUpdated$.next()}))},e.prototype.deleteBaseVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware"),i="\n "+this.translateService.instant(n.gettext("You are about to delete firmware {{ version }} with all its patches."),{version:e.c8y_Firmware.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware deleted.")),this.baseVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.deletePatchVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware patch"),i="\n "+this.translateService.instant(n.gettext("You are about to delete firmware patch {{ version }}."),{version:e.c8y_Firmware.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware patch deleted.")),this.patchVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.ngOnDestroy=function(){this.destroy$.next(!0),this.destroy$.unsubscribe()},e}();_.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-details",template:'<c8y-title>\n {{ (firmware$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n path="#/firmware"\n label="{{ \'Firmware repository\' | translate }}"\n icon="c8y-firmware"\n >\n </c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="!(isLegacy$ | async)"\n class="btn btn-link"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addBaseVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="canAddPatchVersions$ | async"\n class="btn btn-link"\n title="{{ \'Add firmware patch\' | translate }}"\n (click)="addPatchVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware patch\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading$ | async }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card m-b-4">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Name, description and device type filter\n </h4>\n </div>\n <div class="card-block">\n <div class="row">\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Name\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #nameInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.name"\n #nameModel="ngModel"\n placeholder="{{ \'e.g. My firmware\' | translate }}"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.name?.length || 31 }"\n required\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateFirmware$.next({ name: nameInput.value }); nameModel.reset()"\n [disabled]="nameInput.value.length == 0"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Description\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #descriptionInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.description"\n #descriptionModel="ngModel"\n placeholder="{{ \'e.g. Firmware for hardware revision b\' | translate }}"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.description?.length || 31 }"\n\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateFirmware$.next({ description: descriptionInput.value }); descriptionModel.reset() "\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Device type filter\' | translate }}\n\n <button\n class="btn-clean"\n popover="{{ \'If the filter is set, the firmware will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\' | translate }}"\n [outsideClick]="true"\n container="body"\n >\n <i c8yIcon="question-circle-o" class="text-info"></i>\n </button>\n </label>\n <div class="input-group input-group-editable">\n <input\n #deviceTypeInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.c8y_Filter?.type"\n #deviceTypeModel="ngModel"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.type?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateFirmware$.next({ c8y_Filter: { type: deviceTypeInput.value } }); deviceTypeModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Versions and patches\n </h4>\n </div>\n\n <div class="card-block p-t-0 p-b-24">\n <div *ngIf="(baseVersions$ | async)?.data.length === 0">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-firmware" class="c8y-icon-duocolor"></h1>\n <h3 translate>No versions to display.</h3>\n <p translate>Add a new version by clicking below.</p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addBaseVersion()"\n >\n {{ \'Add firmware\' | translate }}\n </button>\n </p>\n </div>\n </div>\n\n <c8y-list-group\n [ngClass]="{ \'dd-low\': (baseVersions$ | async)?.data.length < 10 }"\n *ngIf="(baseVersions$ | async)?.data.length > 0"\n >\n <c8y-li\n *c8yFor="let baseVersion of baseVersions$ | async; let i = index; loadMore: \'auto\'"\n [ngClass]="{ \'c8y-list__item--empty-actions\': !(getPatchVersions$(baseVersion) | async)?.data.length }"\n [collapsed]="!expanded[baseVersion.id]"\n (collapsedChange)="expanded[baseVersion.id] = !$event"\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n <p class="text-truncate-wrap" title="{{ baseVersion.c8y_Firmware.version }}">\n {{ baseVersion.c8y_Firmware.version }}\n </p>\n </div>\n <div class="col-5">\n <p class="text-truncate-wrap">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <span title="{{ getBinaryName$(baseVersion.c8y_Firmware.url) | async }}">\n <c8y-file-download url="{{ baseVersion.c8y_Firmware.url }}"></c8y-file-download>\n </span>\n </p>\n </div>\n <div class="col-2 flex-row a-i-start">\n <span *ngIf="isLegacy$ | async" class="label label-warning flex-item-right-sm">\n {{ \'Legacy\' | translate }}\n </span>\n\n <span *ngIf="!(isLegacy$ | async)">\n <span *ngIf="(getPatchVersionsCount$(baseVersion) | async) === null">\n <span class="label label-info">\n <i c8yIcon="circle-o-notch" class="icon-spin"></i>\n </span>\n </span>\n <span *ngIf="(getPatchVersionsCount$(baseVersion) | async) !== null">\n <span [ngPlural]="getPatchVersionsCount$(baseVersion) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>No patches</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info">\n <span translate>1 patch</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getPatchVersionsCount$(baseVersion) | async }"\n >\n {{ count }} patches\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n <div class="fit-h-20 visible-xs" *ngIf="!(isLegacy$ | async)">\n <button\n class="btn btn-danger btn-xs m-t-8 "\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n <div *ngIf="!(isLegacy$ | async)" class="flex-item-right fit-h-20 p-r-8 hidden-xs">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n <c8y-li-collapse *ngIf="(getPatchVersions$(baseVersion) | async)?.data.length">\n <c8y-list-group class="separator-top">\n <c8y-li\n *c8yFor=" let patchVersion of getPatchVersions$(baseVersion) | async; let i = index; loadMore: \'auto\' "\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n {{ patchVersion.c8y_Firmware.version }}\n </div>\n <div class="col-5">\n <div class="text-truncate">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <c8y-file-download\n url="{{ patchVersion.c8y_Firmware.url }}"\n ></c8y-file-download>\n </div>\n </div>\n <div class="visible-xs m-t-8">\n <button\n class="btn btn-danger btn-xs"\n (click)="deletePatchVersion(patchVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n <div class="flex-item-right p-r-8 hidden-xs fit-h-20">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deletePatchVersion(patchVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n</div>\n'}]}],_.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:c.InventoryService},{type:O},{type:n.AlertService},{type:f.TranslateService},{type:n.ModalService},{type:y.BsModalService}]},b([n.memoize(l.property("id"))],_.prototype,"getPatchVersionsCount$",null),b([n.memoize()],_.prototype,"getBinaryName$",null),b([n.memoize(l.property("id"))],_.prototype,"getPatchVersions$",null);var D=function(){function i(e,i,r){this.modal=e,this.repositoryService=i,this.alert=r,this.saved=new t.EventEmitter,this.onInput=new p.BehaviorSubject(""),this.model={selected:void 0,version:void 0,description:void 0,deviceType:void 0,binary:{file:void 0,url:void 0}},this.saving=!1,this.softwarePreselected=!1,this.textForSoftwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /software/binaries/software1.bin\n https://software/binary/123\n ftp://software/binary/123.tar.gz\n ")}return i.prototype.ngOnInit=function(){this.setInitialState(),this.loadSoftwares()},i.prototype.setInitialState=function(){this.model.selected&&(this.softwarePreselected=!0)},i.prototype.loadSoftwares=function(){var e=this;this.inputSubscription$=this.onInput.pipe(d.tap((function(){e.softwarePreselected||(e.model.description=null,e.form&&e.form.form.get("description").reset())})),d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return e.getSoftwareResult(t)}))).subscribe((function(t){e.softwaresResult=t}))},i.prototype.getSoftwareResult=function(t){return p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.SOFTWARE,{partialName:t,skipLegacy:!0}))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repositoryService.create(this.model,e.RepositoryType.SOFTWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Software added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.ngOnDestroy=function(){this.inputSubscription$.unsubscribe()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i.prototype.onSoftwareSelect=function(e){l.assign(this.model,{selected:e,description:e.description,deviceType:l.get(e,"c8y_Filter.type")})},i}();D.decorators=[{type:t.Component,args:[{selector:"c8y-add-software-software-modal",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-tools\'"></i>\n <h4 translate>\n Add software\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom" *ngIf="!softwarePreselected">\n <p class="lead m-0" translate>\n Select or create new software\n </p>\n </div>\n <form\n class="d-contents"\n autocomplete="off"\n #softwareForm="ngForm"\n (ngSubmit)="softwareForm.form.valid && save()"\n >\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="softwarePreselected">\n <c8y-form-group>\n <label for="softwareName" translate>Software</label>\n <c8y-typeahead\n [(ngModel)]="model.selected"\n name="softwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="onInput.next($event)"\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let software of softwaresResult;\n loadMore: \'auto\';\n notFound: notFoundTemplate\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="onSoftwareSelect(software)"\n [active]="model.selected === software"\n >\n <c8y-highlight\n [text]="software.name || \'--\'"\n [pattern]="onInput | async"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="(onInput | async)?.length > 0">\n <span translate>No match found, add new`software`? </span>\n <button\n title="{{ \'Create new`software`\' | translate }}"\n type="button"\n class="btn btn-primary btn-xs m-l-16"\n translate\n >\n Create new`software`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="softwareDescription" translate>Description</label>\n <input\n id="softwareDescription"\n class="form-control"\n autocomplete="off"\n name="description"\n [(ngModel)]="model.description"\n placeholder="{{ \'e.g. Cloud connectivity software\' | translate }}"\n [disabled]="model.selected?.id"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label class="control-label" for="softwareDeviceTypeFilter">\n {{ \'Device type filter\' | translate }}\n <button\n class="btn btn-clean text-primary"\n popover="{{\n \'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\'\n | translate\n }}"\n triggers="focus"\n container="body"\n placement="right"\n >\n <i [c8yIcon]="\'question-circle-o\'"></i>\n </button>\n </label>\n <input\n id="softwareDeviceTypeFilter"\n class="form-control"\n name="softwareDeviceTypeFilter"\n [(ngModel)]="model.deviceType"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [disabled]="model.selected?.id"\n />\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="softwareVersion" translate>Version</label>\n <input\n id="softwareVersion"\n class="form-control"\n autocomplete="off"\n name="version"\n [(ngModel)]="model.version"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Software file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForSoftwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n\n <button\n title="{{ \'Add software\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !softwareForm.form.valid ||\n softwareForm.form.pristine ||\n saving ||\n (!model.binary?.url && !model.binary?.file)\n "\n translate\n >\n Add software\n </button>\n </div>\n </form>\n</div>\n'}]}],D.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},D.propDecorators={form:[{type:t.ViewChild,args:["softwareForm",{static:!1}]}],saved:[{type:t.Output}]};var A=function(){function t(e,t,i,r,a,o,s){var c=this;this.repositoryService=e,this.modalService=t,this.bsModalService=i,this.translateService=r,this.alertService=a,this.router=o,this.activatedRoute=s,this.textFilter$=new p.BehaviorSubject(""),this.reload$=new p.BehaviorSubject(null),this.reloading=!1,this.softwares$=p.combineLatest(this.textFilter$.pipe(d.debounceTime(400),d.distinctUntilChanged()),this.reload$).pipe(d.tap((function(){c.reloading=!0})),d.switchMap((function(e){var t=C(e,1)[0];return c.getSoftwares(t)})),d.tap((function(){c.reloading=!1})),d.shareReplay(1)),this.isLegacy=this.repositoryService.isLegacyEntry.bind(this.repositoryService),this.DEVICE_TYPE_NOT_AVAILABLE=n.gettext("No device type available")}return t.prototype.getSoftwares=function(t){var n={partialText:t,properties:["name","description","c8y_Filter.type"]};return this.repositoryService.listRepositoryEntries(e.RepositoryType.SOFTWARE,{partialTextFilter:n})},t.prototype.addSoftware=function(){var e=this;this.bsModalService.show(D,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editSoftware(t)}))},t.prototype.editSoftware=function(e){this.router.navigate([e.id],{relativeTo:this.activatedRoute})},t.prototype.deleteSoftware=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete software"),i="\n "+this.translateService.instant(n.gettext('You are about to delete software "{{ name }}" with all its versions.'),{name:e.name})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Software deleted.")),this.reload$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},t.prototype.getBaseVersionsCount$=function(e){var t=this;return this.softwares$.pipe(d.switchMap((function(){return t.repositoryService.getBaseVersionsCount$(e)})),d.shareReplay(1))},t.prototype.getDeviceTypeTitle=function(e){return l.get(e,"c8y_Filter.type",this.translateService.instant(this.DEVICE_TYPE_NOT_AVAILABLE))},t}();A.decorators=[{type:t.Component,args:[{selector:"c8y-software-list",template:'<c8y-title>\n {{ \'Software repository\' | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]="\'left\'" itemClass="navbar-form">\n <div class="input-group input-group-search">\n <input\n class="form-control"\n type="search"\n title="{{ \'Filter software…\' | translate }}"\n placeholder="{{ \'Filter software…\' | translate }}"\n [ngModel]="textFilter$ | async"\n (ngModelChange)="textFilter$.next($event)"\n />\n <span class="input-group-addon">\n <i c8yIcon="search" *ngIf="(textFilter$ | async).length === 0"></i>\n <i\n class="text-muted"\n c8yIcon="times"\n *ngIf="(textFilter$ | async).length > 0"\n (click)="textFilter$.next(\'\')"\n ></i>\n </span>\n </div>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Add software\' | translate }}" (click)="addSoftware()">\n <i c8yIcon="plus-circle"></i>\n {{ \'Add software\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i [ngClass]="{ \'icon-spin\': reloading }" c8yIcon="refresh"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state--\x3e\n<div\n class="c8y-empty-state text-center"\n *ngIf="(softwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length === 0"\n>\n <h1 class="c8y-icon-duocolor" c8yIcon="c8y-tools"></h1>\n <h3 translate>\n No software to display.\n </h3>\n <p translate>\n Add a new software by clicking below.\n </p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add software\' | translate }}"\n (click)="addSoftware()"\n translate\n >\n Add software\n </button>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div\n class="c8y-empty-state"\n *ngIf="(softwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length > 0"\n>\n <h1 class="c8y-icon-duocolor" c8yIcon="search"></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n\x3c!-- apply the class \'dd-low\' when the list contains less than 10 records--\x3e\n<c8y-list-group\n class="m-b-24"\n *ngIf="(softwares$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': (softwares$ | async)?.data.length < 10 }"\n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs">\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-3">\n {{ \'Software\' | translate }}\n </div>\n <div class="col-4">\n {{ \'Description\' | translate }}\n </div>\n <div class="col-3">\n {{ \'Device type\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Versions\' | translate }}\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-li *c8yFor="let software of softwares$ | async; let i = index; loadMore: \'auto\'">\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-60">\n <button class="btn-clean col-3" (click)="editSoftware(software)">\n <span class="text-truncate" title="{{ software.name }}">\n {{ software.name }}\n </span>\n </button>\n\n <div class="col-4">\n <p class="text-truncate" title="{{ software.description }}">\n <span class="text-label-small m-r-4 visible-xs-inline">\n {{ \'Description\' | translate }}\n </span>\n <span *ngIf="software.description; else emptyDescription">\n {{ software.description }}\n </span>\n </p>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n\n <div class="col-3">\n <div\n class="text-truncate"\n title="{{ \'Device type\' | translate }}: {{ software.c8y_Filter?.type || \'-\' }}"\n >\n <span class="text-label-small m-r-8 visible-xs-inline" translate>\n Device type\n </span>\n <span *ngIf="software.c8y_Filter?.type; else emptyText">\n {{ software.c8y_Filter?.type }}\n </span>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n </div>\n\n <div class="col-2">\n <span class="label label-warning flex-item-right-sm" *ngIf="isLegacy(software)">\n <span translate>\n Legacy\n </span>\n </span>\n <span *ngIf="!isLegacy(software)">\n <span *ngIf="(getBaseVersionsCount$(software) | async) === null">\n <span class="label label-info flex-item-right-sm">\n <i class="icon-spin" c8yIcon="circle-o-notch"></i>\n </span>\n </span>\n <span *ngIf="(getBaseVersionsCount$(software) | async) !== null">\n <span [ngPlural]="getBaseVersionsCount$(software) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>\n No versions\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info flex-item-right-sm">\n <span translate>\n 1 version\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info flex-item-right-sm">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getBaseVersionsCount$(software) | async }"\n >\n {{ count }} versions\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n\n <c8y-li-action (click)="editSoftware(software)" icon="pencil">\n {{ \'Edit\' | translate }}\n </c8y-li-action>\n <c8y-li-action (click)="deleteSoftware(software)" icon="trash">\n {{ \'Delete\' | translate }}\n </c8y-li-action>\n </c8y-li>\n</c8y-list-group>\n'}]}],A.ctorParameters=function(){return[{type:O},{type:n.ModalService},{type:y.BsModalService},{type:f.TranslateService},{type:n.AlertService},{type:u.Router},{type:u.ActivatedRoute}]},b([n.memoize(l.property("id"))],A.prototype,"getBaseVersionsCount$",null);var B=function(){function e(e,t,n,i,r,a,o){var s=this;this.activatedRoute=e,this.inventoryService=t,this.repositoryService=n,this.alertService=i,this.translateService=r,this.modalService=a,this.bsModalService=o,this.reload$=new p.Subject,this.reloading$=new p.BehaviorSubject(!1),this.updateSoftware$=new p.Subject,this.softwareUpdated$=new p.Subject,this.baseVersionsUpdated$=new p.Subject,this.software$=p.merge(this.activatedRoute.params.pipe(d.map((function(e){return e.id})),d.switchMap((function(e){return p.from(s.inventoryService.detail(e).then((function(e){return e.data})))}))),this.reload$.pipe(d.tap((function(){return s.reloading$.next(!0)})),d.switchMap((function(){return s.activatedRoute.params})),d.map((function(e){return e.id})),d.switchMap((function(e){return p.from(s.inventoryService.detail(e).then((function(e){return e.data})))})),d.tap((function(){return s.reloading$.next(!1)}))),this.softwareUpdated$).pipe(d.shareReplay(1)),this.baseVersions$=p.merge(this.software$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return s.software$})),d.switchMap((function(e){return s.repositoryService.listBaseVersions(e)})),d.shareReplay(1)),this.isLegacy$=this.software$.pipe(d.map((function(e){return s.repositoryService.isLegacyEntry(e)})),d.shareReplay(1)),this.destroy$=new p.Subject}return e.prototype.ngOnInit=function(){var e=this;this.updateSoftware$.pipe(d.withLatestFrom(this.software$),d.switchMap((function(t){var n=C(t,2),i=n[0],r=n[1];return e.inventoryService.update(Object.assign({id:r.id},i))})),d.map((function(e){return e.data})),d.tap((function(t){return e.softwareUpdated$.next(t)})),d.tap((function(){return e.alertService.success(n.gettext("Saved."))})),d.takeUntil(this.destroy$)).subscribe()},e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.addBaseVersion=function(){var e=this;this.software$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t,description:t.description}}};return e.bsModalService.show(D,n).content.saved}))).subscribe((function(){return e.baseVersionsUpdated$.next()}))},e.prototype.deleteBaseVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete software"),i="\n "+this.translateService.instant(n.gettext("You are about to delete software {{ version }}."),{version:e.c8y_Software.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Software deleted.")),this.baseVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.ngOnDestroy=function(){this.destroy$.next(!0),this.destroy$.unsubscribe()},e}();B.decorators=[{type:t.Component,args:[{selector:"c8y-software-details",template:'<c8y-title>\n {{ (software$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n path="#/software"\n label="{{ \'Software repository\' | translate }}"\n icon="c8y-tools"\n >\n </c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="!(isLegacy$ | async)"\n class="btn btn-link"\n title="{{ \'Add software\' | translate }}"\n (click)="addBaseVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add software\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading$ | async }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card m-b-4">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Name, description and device type filter\n </h4>\n </div>\n <div class="card-block">\n <div class="row">\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Name\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #nameInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.name"\n #nameModel="ngModel"\n placeholder="{{ \'e.g. My software\' | translate }}"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.name?.length || 31 }"\n required\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateSoftware$.next({ name: nameInput.value }); nameModel.reset()"\n [disabled]="nameInput.value.length == 0"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Description\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #descriptionInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.description"\n #descriptionModel="ngModel"\n placeholder="{{ \'e.g. Cloud connectivity software\' | translate }}"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.description?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateSoftware$.next({ description: descriptionInput.value }); descriptionModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Device type filter\' | translate }}\n\n <button\n class="btn-clean"\n popover="{{ \'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\' | translate }}"\n [outsideClick]="true"\n container="body"\n >\n <i c8yIcon="question-circle-o" class="text-info"></i>\n </button>\n </label>\n <div class="input-group input-group-editable">\n <input\n #deviceTypeInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.c8y_Filter?.type"\n #deviceTypeModel="ngModel"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.type?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateSoftware$.next({ c8y_Filter: { type: deviceTypeInput.value } }); deviceTypeModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Versions\n </h4>\n </div>\n\n <div class="card-block p-t-0 p-b-24">\n <div *ngIf="(baseVersions$ | async)?.data.length === 0">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-tools" class="c8y-icon-duocolor"></h1>\n <h3 translate>No versions to display.</h3>\n <p translate>Add a new version by clicking below.</p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add software\' | translate }}"\n (click)="addBaseVersion()"\n >\n {{ \'Add software\' | translate }}\n </button>\n </p>\n </div>\n </div>\n\n <c8y-list-group\n [ngClass]="{ \'dd-low\': (baseVersions$ | async)?.data.length < 10 }"\n *ngIf="(baseVersions$ | async)?.data.length > 0"\n >\n <c8y-li\n *c8yFor="let baseVersion of baseVersions$ | async; let i = index; loadMore: \'auto\'"\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n <p class="text-truncate-wrap" title="{{ baseVersion.c8y_Software.version }}">\n {{ baseVersion.c8y_Software.version }}\n </p>\n </div>\n <div class="col-5">\n <p class="text-truncate-wrap">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <span title=" {{ getBinaryName$(baseVersion.c8y_Software.url) | async }}">\n <c8y-file-download url="{{ baseVersion.c8y_Software.url }}"></c8y-file-download>\n </span>\n </p>\n </div>\n <div class="col-2 flex-row a-i-start">\n <span *ngIf="isLegacy$ | async" class="label label-warning flex-item-right-sm">\n {{ \'Legacy\' | translate }}\n </span>\n\n <div class="fit-h-20" *ngIf="!(isLegacy$ | async)">\n <button\n class="btn btn-danger btn-xs visible-xs flex-item-right m-r-8 m-t-8"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n </div>\n <div *ngIf="!(isLegacy$ | async)" class="flex-item-right fit-h-20 p-r-8 hidden-xs">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n</div>\n'}]}],B.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:c.InventoryService},{type:O},{type:n.AlertService},{type:f.TranslateService},{type:n.ModalService},{type:y.BsModalService}]},b([n.memoize()],B.prototype,"getBinaryName$",null);var P=function(){function t(e,t,n){var i=this;this.repositoryService=e,this.bsModalRef=t,this.alert=n,this.binary={file:void 0,url:void 0},this.pattern="",this.mo={},this.saving=!1,this.uploadChoice="uploadBinary",this.result=new Promise((function(e,t){i._save=e,i._cancel=t}))}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){var t;return S(this,(function(i){switch(i.label){case 0:return t=this,[4,this.repositoryService.listRepositoryEntries(e.RepositoryType.CONFIGURATION)];case 1:return t.configs=i.sent(),this.selected&&(this.uploadChoice=this.binary.file?"uploadBinary":"uploadUrl",this.existingBinary=this.binary.file),this.setPipe(""),this.submitButtonTitle=this.mo.id?n.gettext("Update configuration"):n.gettext("Add configuration"),[2]}}))}))},t.prototype.cancel=function(){this.bsModalRef.hide(),this._cancel()},t.prototype.setPipe=function(e){this.pattern=e,this.filterPipe=p.pipe(d.map((function(e){return l.uniqBy(e,"configurationType")})),d.map((function(t){return t.filter((function(t){return t.configurationType&&t.configurationType.toLowerCase().indexOf(e.toLowerCase())>-1}))})))},t.prototype.onFile=function(e){this.configurationForm.form.markAsDirty(),l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.binary={file:void 0,url:void 0}:this.binary={file:e.droppedFiles[0].file}:this.binary={url:e.url}},t.prototype.save=function(){return w(this,void 0,void 0,(function(){var t,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:return l.trys.push([0,2,3,4]),this.saving=!0,i=(t=this).selected,r=t.version,a=t.description,o=t.binary,s=t.deviceType,this.existingBinary===this.binary.file&&(o.file=void 0),[4,this.repositoryService.save({selected:i,version:r,description:a,binary:o,deviceType:s},e.RepositoryType.CONFIGURATION,this.mo)];case 1:return l.sent(),this.alert.success(this.mo.id?n.gettext("Configuration updated."):n.gettext("Configuration created.")),this.bsModalRef.hide(),this._save(),[3,4];case 2:return c=l.sent(),this.alert.addServerFailure(c),this._cancel(),[3,4];case 3:return this.saving=!1,[7];case 4:return[2]}}))}))},t}();P.decorators=[{type:t.Component,args:[{selector:"c8y-configuration-detail",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'cogs\'"></i>\n <h4 translate *ngIf="mo.id">Update configuration</h4>\n <h4 translate *ngIf="!mo.id">Add configuration</h4>\n </div>\n\n <form class="d-contents" #configurationForm="ngForm" (ngSubmit)="configurationForm.form.valid && save()">\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <c8y-form-group>\n <label translate>Name</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g.\' | translate }} hosts"\n autocomplete="off"\n required\n maxlength="254"\n [(ngModel)]="version"\n name="version"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Device type</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n maxlength="254"\n autocomplete="off"\n [(ngModel)]="deviceType"\n name="deviceType"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Description</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g. Host configuration\' | translate }} c8y_Linux"\n maxlength="254"\n autocomplete="off"\n [(ngModel)]="description"\n name="description"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Configuration type</label>\n <c8y-typeahead\n [(ngModel)]="selected"\n name="confType"\n placeholder="{{ \'e.g.\' | translate }} ssh"\n (onSearch)="setPipe($event)"\n displayProperty="configurationType"\n >\n <c8y-li\n *c8yFor="let config of configs; pipe: filterPipe; notFound: notFoundTemplate"\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="selected = config; setPipe(\'\')"\n [active]="selected === config"\n >\n <c8y-highlight\n [text]="config.configurationType || \'--\'"\n [pattern]="pattern"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="pattern.length > 0">\n <span translate>No match found, add new`configuration`?</span>\n <button title="Create new`configuration`" type="button" class="btn btn-primary btn-xs m-l-16" translate>\n Create new`configuration`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Configuration file</div>\n <c8y-file-picker\n [maxAllowedFiles]="1"\n (onFilesPicked)="onFile($event)"\n [uploadChoice]="uploadChoice"\n [fileUrl]="binary.url"\n [fileBinary]="binary.file"\n >\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n\n <div class="modal-footer">\n <button\n (click)="cancel()"\n type="button"\n class="btn btn-default"\n title="{{ \'Cancel\' | translate }}"\n [disabled]="saving"\n >\n <span translate>Cancel</span>\n </button>\n <button\n class="btn btn-primary"\n type="submit"\n title="{{ submitButtonTitle | translate }}"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !configurationForm.valid ||\n configurationForm.pristine ||\n (!binary?.url && !binary?.file) ||\n saving\n "\n >\n {{ submitButtonTitle | translate }}\n </button>\n </div>\n </form>\n</div>\n'}]}],P.ctorParameters=function(){return[{type:O},{type:y.BsModalRef},{type:n.AlertService}]},P.propDecorators={configurationForm:[{type:t.ViewChild,args:["configurationForm",{static:!0}]}]};var M=function(){function t(e,t,i,r,a,o,s){this.alert=e,this.repositoryService=t,this.bsModalService=i,this.modalService=r,this.translateService=a,this.inventoryBinaryService=o,this.inventoryService=s,this.filterTerm="",this.reloading=!1,this.DELETED_SUCCESS_MSG=n.gettext("Configuration deleted.")}return t.prototype.ngOnInit=function(){this.loadConfigurations()},t.prototype.loadConfigurations=function(){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return this.reloading=!0,t=this,n=p.of,[4,this.repositoryService.listRepositoryEntries(e.RepositoryType.CONFIGURATION)];case 1:return t.configurations$=n.apply(void 0,[i.sent()]),this.reloading=!1,this.reset(),[2]}}))}))},t.prototype.add=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return e.trys.push([0,3,,4]),[4,this.bsModalService.show(P,{class:"modal-sm",ignoreBackdropClick:!0}).content.result];case 1:return e.sent(),[4,this.loadConfigurations()];case 2:return e.sent(),[3,4];case 3:return e.sent(),[3,4];case 4:return[2]}}))}))},t.prototype.edit=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 1:t=i.sent(),i.label=2;case 2:return i.trys.push([2,5,,6]),(n=this.bsModalService.show(P,{class:"modal-sm",ignoreBackdropClick:!0,initialState:{selected:{id:e.id,name:e.configurationType},version:e.name,deviceType:e.deviceType,description:e.description,binary:{file:t,url:e.url}}}).content).mo=e,[4,n.result];case 3:return i.sent(),[4,this.loadConfigurations()];case 4:return i.sent(),[3,6];case 5:return i.sent(),[3,6];case 6:return[2]}}))}))},t.prototype.isBinaryFile=function(e){return!!this.inventoryBinaryService.getIdFromUrl(e.url)},t.prototype.getBinaryName=function(e){return this.repositoryService.getBinaryName$(e.url)},t.prototype.download=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){switch(n.label){case 0:return[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 1:return t=n.sent(),h.saveAs(t),[2]}}))}))},t.prototype.delete=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:return l.trys.push([0,4,,5]),t=n.gettext("Delete configuration snapshot"),i=n.gettext("You are about to delete the configuration snapshot {{ name }}."),r=n.gettext("This operation is irreversible."),a=n.gettext("Do you want to proceed?"),o=[this.translateService.instant(i,{name:e.name}),this.translateService.instant(r),this.translateService.instant(a)].join(" "),s={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,o,n.Status.DANGER,s)];case 1:return l.sent(),[4,this.repositoryService.delete(e)];case 2:return l.sent(),this.alert.success(this.DELETED_SUCCESS_MSG),[4,this.loadConfigurations()];case 3:return l.sent(),[3,5];case 4:return(c=l.sent())&&this.alert.addServerFailure(c),[3,5];case 5:return[2]}}))}))},t.prototype.setPipe=function(e){var t=this;this.filterTerm=e,this.filterPipe=p.pipe(d.map((function(n){return t.data=0===e.trim().length?n:n.filter((function(n){return t.filterContainString(n.name,e)||t.filterContainString(n.configurationType,e)||t.filterContainString(n.deviceType,e)})),t.data})))},t.prototype.shouldShowEmptyState=function(){return!(this.data&&this.data.length>0)},t.prototype.reset=function(){this.filter.filterTerm="",this.setPipe("")},t.prototype.filterContainString=function(e,t){var n=t.toLowerCase().trim();return e&&e.toLowerCase().indexOf(n)>-1},t}();M.decorators=[{type:t.Component,args:[{selector:"c8y-configuration-list",template:'<c8y-title>\n <span translate>\n Configuration snapshots repository\n </span> \n <small\n *ngIf="(configurations$ | async)?.paging.totalPages === 1 && !filterTerm"\n >\n {{ (configurations$ | async).data.length }}\n <span translate>\n snapshots\n </span>\n </small>\n <small\n *ngIf="(configurations$ | async)?.paging.totalPages > 1 && !filterTerm"\n [tooltip]="\'More data available. Scroll to the bottom of the list to load it.\' | translate"\n container="body"\n >\n {{ (configurations$ | async).paging.pageSize }}+\n <span translate>snapshots</span>\n </small>\n <small *ngIf="filterTerm">\n <span translate>\n Search results for\n </span> "\n {{ this.filterTerm }}"\n </small>\n</c8y-title>\n\n<c8y-action-bar-item itemClass="navbar-form">\n <c8y-filter\n [icon]="\'search\'"\n (onSearch)="setPipe($event)"\n ></c8y-filter>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n (click)="add()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add configuration snapshot\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n title="{{ \'Reload\' | translate }}"\n (click)="loadConfigurations()"\n >\n <i [ngClass]="{ \'icon-spin\': reloading }"\n c8yIcon="refresh"\n ></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state --\x3e\n<div class="c8y-empty-state text-center"\n *ngIf="!filterTerm && (configurations$ | async)?.data.length === 0"\n>\n <h1 c8yIcon="gears"></h1>\n <h3 translate>There are no configuration snapshots defined</h3>\n <p translate>Add a configuration snapshot first.</p>\n <div>\n <button (click)="add()" class="btn btn-primary" translate>\n Add configuration snapshot\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href="users-guide/device-management/#configuration-repository">\n User guide`KEEP_ORIGINAL`\n </a>.\n </small>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div class="c8y-empty-state"\n *ngIf="shouldShowEmptyState() && (configurations$ | async)?.data.length > 0"\n>\n <h1 class="c8y-icon-duocolor"\n c8yIcon="search"\n ></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n<c8y-list-group class="m-b-24"\n *ngIf="(configurations$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': data && data.length ? data.length < 10 : (configurations$ | async)?.data.length < 10 }"\n\n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs"\n *ngIf="!shouldShowEmptyState()"\n >\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-2">\n {{ \'Configuration\' | translate }}\n </div>\n <div class="col-3">\n {{ \'Description\' | translate }}\n </div>\n <div class="col-3">\n {{ \'File\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Device type\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Configuration type\' | translate }}\n </div>\n </c8y-li-body>\n </c8y-li>\n\n <c8y-li *c8yFor="let configuration of configurations$; pipe: filterPipe">\n <c8y-li-icon icon="gears"></c8y-li-icon>\n <div class="content-flex-60">\n <button class="btn-clean col-2"\n (click)="edit(configuration)"\n >\n <span class="text-truncate"\n title="{{ configuration.name || \'-\' }}"\n >\n <c8y-highlight\n [text]="configuration.name || \'-\'"\n elementClass="text-info"\n [pattern]="filterTerm"\n ></c8y-highlight>\n </span>\n </button>\n <div class="col-3">\n <div class="text-label-small visible-xs-inline m-r-4">\n {{ \'Description\' | translate }}\n </div>\n <small class="text-truncate"\n *ngIf="configuration.description; else emptyDescription"\n [title]="configuration.description"\n >\n {{ configuration.description }}\n </small>\n </div>\n <div class="col-3">\n <span class="text-truncate">\n <span class="text-label-small m-r-4 visible-xs-inline" translate>\n File\n </span>\n <small\n *ngIf="isBinaryFile(configuration); else noFile"\n title="{{ getBinaryName(configuration) | async }}"\n >\n {{ getBinaryName(configuration) | async }}\n </small>\n <ng-template #noFile>\n <small title="{{ configuration.url }}">\n {{ configuration.url }}\n </small>\n </ng-template>\n </span>\n </div>\n <div class="col-2">\n <div class="text-truncate"\n title="{{ \'Device type\' | translate }}: {{ configuration.deviceType || \'-\' }}"\n >\n <span class="text-label-small visible-xs-inline m-r-4" translate>\n Device type\n </span>\n <span *ngIf="configuration.deviceType; else emptyText">\n <c8y-highlight\n [text]="configuration.deviceType || \'-\'"\n elementClass="text-info"\n [pattern]="filterTerm"\n >\n </c8y-highlight>\n </span>\n </div>\n </div>\n <div class="col-2">\n <div class="text-truncate"\n title="{{ configuration.configurationType }}"\n >\n <span class="label label-primary"\n *ngIf="configuration.configurationType; else emptyText"\n >\n <c8y-highlight\n [text]="configuration.configurationType"\n elementClass="text-info"\n [pattern]="filterTerm"\n >\n </c8y-highlight>\n </span>\n </div>\n </div>\n </div>\n <c8y-li-action\n (click)="edit(configuration)"\n icon="pencil"\n label="{{ \'Edit\' | translate }}"\n >\n </c8y-li-action>\n <c8y-li-action\n (click)="delete(configuration)"\n icon="trash-o"\n label="{{ \'Delete\' | translate }}"\n >\n </c8y-li-action>\n <c8y-li-action\n *ngIf="isBinaryFile(configuration)"\n (click)="download(configuration)"\n icon="download"\n label="{{ \'Download\' | translate }}"\n >\n </c8y-li-action>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </c8y-li>\n</c8y-list-group>\n'}]}],M.ctorParameters=function(){return[{type:n.AlertService},{type:O},{type:y.BsModalService},{type:n.ModalService},{type:f.TranslateService},{type:c.InventoryBinaryService},{type:c.InventoryService}]},M.propDecorators={filter:[{type:t.ViewChild,args:[n.FilterInputComponent,{static:!1}]}]},b([n.memoize(l.property("id"))],M.prototype,"getBinaryName",null);var k=function(){function e(){this.navs=[]}return e.prototype.get=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){return 0===this.navs.length&&(this.navs.push(new n.NavigatorNode({label:n.gettext("Firmware repository"),path:"firmware",icon:"c8y-firmware",parent:n.gettext("Management"),priority:1e3})),this.navs.push(new n.NavigatorNode({label:n.gettext("Software repository"),path:"software",icon:"c8y-tools",parent:n.gettext("Management"),priority:900})),this.navs.push(new n.NavigatorNode({label:n.gettext("Configuration repository"),path:"configuration",icon:"gears",parent:n.gettext("Management"),priority:800}))),[2,this.navs]}))}))},e}();k.decorators=[{type:t.Injectable}];var V=function(){function e(e,i){var r=this;this.repositoryService=e,this.translateService=i,this.repositoryEntriesWithVersions$=void 0,this.badgeTemplates={"=1":n.gettext("{{count}} version"),other:n.gettext("{{count}} versions")},this.title=n.gettext("Select repository entry"),this.load=new p.Subject,this.searchTerm=new p.BehaviorSubject(""),this.deviceTypeQuery={},this.searchQuery={},this.labels={ok:n.gettext("Save")},this.showFilter=!0,this.areMoreEntries=!1,this.resultEmitter=new t.EventEmitter,this.mode=n.ModalSelectionMode.SINGLE,this.disableSelected=!0,this.modalEntries=this.load.pipe(d.switchMap((function(){return r.repositoryEntriesWithVersions$})),d.mergeMap((function(e){return r.aggregate(e)})),d.tap((function(e){r.areMoreEntries=e.length>=r.PAGE_SIZE}))),this.PAGE_SIZE=100,this.queriesUtil=new c.QueriesUtil}return e.prototype.ngOnInit=function(){var e=this;if(!this.repositoryType)throw new Error("Repository type must be defined");this.repositoryEntriesWithVersions$||(this.repositoryEntriesWithVersions$=p.from(this.repositoryService.listRepositoryEntries(this.repositoryType,{query:this.queriesUtil.addOrFilter(this.deviceTypeQuery,this.searchQuery),params:{pageSize:this.PAGE_SIZE}})).pipe(d.map((function(e){return e.data})),d.map((function(t){return e.getAndAssignRepositoryBinaries(t)})),d.shareReplay(1)))},e.prototype.getAndAssignRepositoryBinaries=function(e){var t=this;return e.forEach((function(e){e.versions=t.repositoryService.listAllVersions(e)})),e},e.prototype.search=function(e){this.searchTerm.next(e),this.searchQuery=e?{name:"*"+e+"*"}:{},this.load.next()},e.prototype.result=function(e){this.resultEmitter.emit(e)},e.prototype.aggregate=function(e){return w(this,void 0,void 0,(function(){var t,n,i=this;return S(this,(function(r){return t=this.repositoryType,n=this.selected,[2,Promise.all(e.map((function(e){return w(i,void 0,void 0,(function(){var i,r;return S(this,(function(a){switch(a.label){case 0:return r=this.getSelectModalOptions,[4,this.repositoryService.fetchAllItemsFromList(e.versions)];case 1:return i=r.apply(this,[a.sent(),n,e,t]),[2,this.getSelectModalObject(e,i)]}}))}))})))]}))}))},e.prototype.getSelectModalOptions=function(e,t,i,r){var a=this,o=[];return e.forEach((function(e){var s=a.isBinaryRepositorySelected(t,i,e,r),c=e[""+r].version,p=c||"("+a.translateService.instant(n.gettext("not specified`version`"))+")",d=c?"":"text-muted";o.push({body:[{value:p,class:d}],obj:Object.assign(Object.assign(Object.assign({id:e.id,name:i.name,version:c},l.get(e,"c8y_Patch.dependency")&&{dependency:l.get(e,"c8y_Patch.dependency")}),l.get(e,"c8y_Patch")&&{c8y_Patch:!0}),{url:e[""+r].url}),selected:s})})),o},e.prototype.isBinaryRepositorySelected=function(e,t,n,i){return!!e&&e.filter((function(e){return e.name===t.name&&e.version===n[""+i].version})).length>0},e.prototype.getSelectModalObject=function(e,t){var n=1===t.length?this.translateService.instant(this.badgeTemplates["=1"],{count:t.length}):this.translateService.instant(this.badgeTemplates.other,{count:t.length});return{groupId:e.id,body:[{value:e.name,class:"text-truncate"},{value:e.description,class:"text-truncate text-muted"}],additionalInformation:{value:n,class:"label label-info"},options:t}},e}();V.decorators=[{type:t.Component,args:[{selector:"c8y-repository-select-modal",template:'<c8y-select-modal\n [icon]="icon"\n [title]="title"\n [subTitle]="subTitle"\n [items]="modalEntries | async"\n [mode]="mode"\n [disableSelected]="disableSelected"\n [labels]="labels"\n [showFilter]="showFilter"\n [areMoreEntries]="areMoreEntries"\n (search)="search($event)"\n (result)="result($event)"\n>\n</c8y-select-modal>\n'}]}],V.ctorParameters=function(){return[{type:O},{type:f.TranslateService}]};var N=function(){function t(t,n,i,r){var a=this;this.route=t,this.repository=n,this.inventory=i,this.bsModal=r,this.isEmpty=l.isEmpty,this.reloading=!1,this.device$=new p.BehaviorSubject(this.route.parent.snapshot.data.contextData),this.deviceFirmwareFragment$=this.device$.pipe(d.map((function(e){return e.c8y_Firmware}))),this.firmwareBinary$=this.deviceFirmwareFragment$.pipe(d.filter((function(e){return!l.isEmpty(e)})),d.switchMap((function(t){return p.from(a.repository.getRepositoryBinaryMoByVersion(t,e.RepositoryType.FIRMWARE))})),d.shareReplay(1)),this.repositoryEntry$=this.firmwareBinary$.pipe(d.switchMap((function(e){return a.repository.getRepositoryEntryMO$(e)})),d.shareReplay(1)),this.patches$=p.combineLatest(this.firmwareBinary$,this.repositoryEntry$).pipe(d.switchMap((function(e){var t=C(e,2),n=t[0],i=t[1];if(i&&n){var r=a.repository.getBaseVersionFromMO(n);return p.from(a.repository.listPatchVersions(i,r)).pipe(d.map((function(e){return e.data})))}return p.of([])})),d.shareReplay(1)),this.changesOperation$=new p.BehaviorSubject(null),this.changesInProgress$=this.changesOperation$.pipe(d.map((function(e){return a.isInProgress(e)})))}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),[4,this.loadOperation()];case 2:return e.sent(),[2]}}))}))},t.prototype.installFirmware=function(){var t=this,i={repositoryEntriesWithVersions$:p.of([]),repositoryEntriesWithVersionsFn$:function(e){return t.getRepositoryEntriesWithVersions$(e.content.searchTerm)},repositoryType:e.RepositoryType.FIRMWARE,title:n.gettext("Install firmware"),subTitle:n.gettext("Available firmwares matching the device type"),icon:"c8y-firmware",mode:n.ModalSelectionMode.SINGLE,labels:{ok:n.gettext("Install")},disableSelected:!1};this.deviceFirmwareFragment$.pipe(d.take(1),d.switchMap((function(e){if(e){var n=[{name:e.name,version:e.version}];l.assign(i,{selected:n})}var r=t.bsModal.show(V,{ignoreBackdropClick:!0,initialState:i});return i.repositoryEntriesWithVersionsFn$&&(r.content.repositoryEntriesWithVersions$=i.repositoryEntriesWithVersionsFn$(r)),r.content.load.next(),r.content.resultEmitter}))).subscribe((function(e){var n=C(e,1)[0];t.handleOperation(n)}))},t.prototype.getRepositoryEntriesWithVersions$=function(t){var n=this;return t.pipe(d.distinctUntilChanged(),d.switchMap((function(t){return n.repository.listRepositoryEntries(e.RepositoryType.FIRMWARE,{query:n.repository.getDeviceTypeQuery(e.RepositoryType.FIRMWARE,n.device$.value),partialName:t,params:{pageSize:100}})})),d.map((function(e){return e.data})),d.map((function(e){return n.getAndAssignRepositoryBinaries(e)})),d.shareReplay(1))},t.prototype.getAndAssignRepositoryBinaries=function(e){var t=this;return e.forEach((function(e){e.versions=t.repository.listBaseVersions(e)})),e},t.prototype.addPatch=function(){var t=this,i={repositoryType:e.RepositoryType.FIRMWARE,repositoryEntriesWithVersions$:this.getRepositoryEntryWithPatches$(),title:n.gettext("Install firmware"),subTitle:n.gettext("Available firmwares matching the device type"),icon:"c8y-firmware",mode:n.ModalSelectionMode.SINGLE,labels:{ok:n.gettext("Install")},disableSelected:!1};this.deviceFirmwareFragment$.pipe(d.take(1),d.switchMap((function(e){if(e){var n=[{name:e.name,version:e.version}];l.assign(i,{selected:n})}var r=t.bsModal.show(V,{ignoreBackdropClick:!0,initialState:i});return r.content.load.next(),r.content.resultEmitter}))).subscribe((function(e){t.handleOperation(e)}))},t.prototype.getRepositoryEntryWithPatches$=function(){return p.combineLatest(this.repositoryEntry$,this.patches$).pipe(d.map((function(e){var t=C(e,2),n=t[0],i=t[1];return[Object.assign(Object.assign({},n),{versions:i})]})))},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:return this.reloading=!0,e=this.device$.value.id,[4,this.inventory.detail(e,{withChildren:!1})];case 1:return t=n.sent().data,this.device$.next(t),this.reloading=!1,[2]}}))}))},t.prototype.handleOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){switch(n.label){case 0:return[4,this.repository.createFirmwareUpdateOperation(this.device$.value,e)];case 1:return t=n.sent(),this.trackOperation(t),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:return e=this.device$.value.id,[4,this.repository.getLastFirmwareUpdateOperation(e)];case 1:return t=n.sent(),this.trackOperation(t),[2]}}))}))},t.prototype.trackOperation=function(e){var t=this;this.changesOperation$.next(e),this.isInProgress(e)&&this.repository.observeOperation(e).subscribe((function(e){t.changesOperation$.next(e),e.status===c.OperationStatus.SUCCESSFUL&&t.loadDevice()}),(function(e){t.changesOperation$.next(e)}))},t.prototype.isInProgress=function(e){return e&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(e.status)},t}();N.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-device-tab",template:'<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>Current firmware</h4>\n </div>\n <div class="inner-scroll">\n <fieldset *ngIf="changesOperation$ | async" class="card-block bg-gray-white">\n <c8y-single-operation [operation]="changesOperation$ | async"></c8y-single-operation>\n </fieldset>\n <div class="card-block p-t-0 p-b-0">\n \n \x3c!-- EMPTY STATE --\x3e\n <ng-container *ngIf="isEmpty(deviceFirmwareFragment$ | async); else firmwareBlock">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-firmware" class="c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No firmware installed.</strong> <br />\n <small translate>Click below to install firmware into this device.</small>\n </p>\n </div>\n </ng-container>\n\n \x3c!-- FIRMWARE --\x3e\n <ng-template #firmwareBlock>\n <c8y-list-group class="no-border-last">\n <c8y-li>\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n\n <c8y-li-body *ngIf="deviceFirmwareFragment$ | async as deviceFirmwareFragment">\n \x3c!-- Firmware title --\x3e\n <p class="m-b-16 text-medium">\n {{ deviceFirmwareFragment.name }}\n </p>\n \x3c!-- Firmware description --\x3e\n <div *ngIf="repositoryEntry$ | async as repositoryEntry">\n <p class="text-label-small" translate>\n Description\n </p>\n <p>\n {{ repositoryEntry.description }}\n </p>\n </div>\n\n \x3c!-- BASE/PATCH VERSION --\x3e\n <div class="m-b-16">\n <p class="text-label-small" translate>\n Version\n </p>\n <p *ngIf="deviceFirmwareFragment.version; else versionNotSpecified">\n {{ deviceFirmwareFragment.version }}\n </p>\n <ng-template #versionNotSpecified>\n <p>\n <em class="text-muted"> ({{ \'not specified`version`\' | translate }}) </em>\n </p>\n </ng-template>\n </div>\n\n \x3c!-- ADD PATCH --\x3e\n <button\n *ngIf="(this.patches$ | async)?.length > 0"\n (click)="addPatch()"\n class="btn btn-xs btn-primary"\n [disabled]="changesInProgress$ | async"\n title="{{ \'Patches available\' | translate }}"\n >\n {{ \'Patches available\' | translate }}\n </button>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </ng-template>\n </div>\n </div>\n <div class="card-footer separator-top">\n\n \x3c!-- INSTALL FIRMWARE --\x3e\n <button\n *ngIf="isEmpty(deviceFirmwareFragment$ | async)"\n class="btn btn-primary"\n (click)="installFirmware()"\n title="{{ \'Install firmware\' | translate }}"\n >\n {{ \'Install firmware\' | translate }}\n </button>\n\n \x3c!-- REPLACE FIRMWARE --\x3e\n <button\n *ngIf="!isEmpty(deviceFirmwareFragment$ | async)"\n class="btn btn-primary"\n (click)="installFirmware()"\n [disabled]="changesInProgress$ | async"\n title="{{ \'Replace firmware\' | translate }}"\n >\n {{ \'Replace firmware\' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n'}]}],N.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:O},{type:c.InventoryService},{type:y.BsModalService}]};var L=function(){function e(){}return e.prototype.canActivate=function(e){var t=l.get(e,"data.contextData")||l.get(e,"parent.data.contextData"),n=l.get(t,"c8y_SupportedOperations");return!!n&&l.indexOf(n,"c8y_Firmware")>=0},e}();L.decorators=[{type:t.Injectable}];var U=function(){function t(t,n,i){var r=this;this.route=t,this.repository=n,this.inventory=i,this.deviceId=this.route.snapshot.parent.data.contextData.id,this.device$=new p.BehaviorSubject(this.route.snapshot.parent.data.contextData),this.deviceTypeQuery$=this.device$.pipe(d.map((function(t){return r.repository.getDeviceTypeQuery(e.RepositoryType.SOFTWARE,t)}))),this.list$=this.device$.pipe(d.map((function(e){return r.repository.getDeviceSoftwareList(e)}))),this.changes$=new p.BehaviorSubject([]),this.changesOperation$=new p.BehaviorSubject(null),this.changesInProgress$=this.changesOperation$.pipe(d.map((function(e){return r.isInProgress(e)}))),this.reloading=!1}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),[4,this.loadOperation()];case 2:return e.sent(),[2]}}))}))},t.prototype.addChanges=function(e){var t=this,n=I(this.changes$.value);e.forEach((function(e){n.some((function(n){return t.areSameChanges(n,e)}))||(n=I(n,[e]))})),this.changes$.next(n)},t.prototype.dropChange=function(e){var t=this,n=I(this.changes$.value);n=n.filter((function(n){return!t.areSameChanges(n,e)})),this.changes$.next(n)},t.prototype.areSameChanges=function(e,t){return e.name===t.name&&e.version===t.version&&e.action===t.action},t.prototype.clearChanges=function(){this.changes$.next([])},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return this.reloading=!0,[4,this.inventory.detail(this.deviceId,{withChildren:!1})];case 1:return e=t.sent().data,this.device$.next(e),this.reloading=!1,[2]}}))}))},t.prototype.applyChanges=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repository.createSoftwareUpdateOperation(this.device$.value,this.changes$.value)];case 1:return e=t.sent(),this.trackOperation(e),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repository.getLastSoftwareUpdateOperation(this.deviceId)];case 1:return e=t.sent(),this.trackOperation(e),[2]}}))}))},t.prototype.trackOperation=function(e){var t=this;this.changesOperation$.next(e),this.isInProgress(e)&&(this.displayChangesFromOperation(e),this.repository.observeOperation(e).subscribe((function(e){t.changesOperation$.next(e),e.status===c.OperationStatus.SUCCESSFUL&&(t.clearChanges(),t.loadDevice())}),(function(e){t.changesOperation$.next(e)})))},t.prototype.displayChangesFromOperation=function(e){var t=this.repository.getDeviceSoftwareChangesFromOperation(e,this.device$.value);this.changes$.next(t)},t.prototype.isInProgress=function(e){return e&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(e.status)},t}();U.decorators=[{type:t.Component,args:[{selector:"c8y-software-device-tab",template:'<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="loadDevice()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="card d-grid grid__col--8-4--md m-b-0">\n <c8y-installed-software\n class="card--fullpage bg-white"\n [deviceTypeQuery]="deviceTypeQuery$ | async"\n [softwareList]="list$ | async"\n [deviceSoftwareChanges]="changes$ | async"\n [deviceSoftwareChangesOperation]="changesOperation$ | async"\n [deviceSoftwareChangesInProgress]="changesInProgress$ | async"\n (changes)="addChanges($event)"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class="card--fullpage bg-gray-white"\n [changes]="changes$ | async"\n [changesInProgress]="changesInProgress$ | async"\n (clear)="clearChanges()"\n (drop)="dropChange($event)"\n (apply)="applyChanges()"\n ></c8y-device-software-changes>\n</div>\n'}]}],U.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:O},{type:c.InventoryService}]};var j=function(){function e(){this.operations=["c8y_SoftwareUpdate","c8y_SoftwareList","c8y_Software"]}return e.prototype.canActivate=function(e){return this.isAnyOperationSupported(e)},e.prototype.isAnyOperationSupported=function(e){var t=e.data.contextData||e.parent.data.contextData,n=t&&t.c8y_SupportedOperations||[];return this.operations.some((function(e){return n.indexOf(e)>=0}))},e}();j.decorators=[{type:t.Injectable}];var G=function(){function i(e,n,i){this.repository=e,this.inventory=n,this.bsModal=i,this.changes=new t.EventEmitter}return i.prototype.installSoftware=function(){var e=this;this.displaySoftwareSelectModal({title:n.gettext("Install software"),labels:{ok:n.gettext("Install")},repositoryEntriesWithVersions$:p.of([]),repositoryEntriesWithVersionsFn$:function(t){return e.getInstallableSoftwareListWithVersions$(t.content.searchTerm)}}).subscribe((function(t){e.emitSoftwareInstall(t)}))},i.prototype.updateSoftware=function(e){var t=this;this.displaySoftwareSelectModal({title:n.gettext("Update software"),labels:{ok:n.gettext("Update")},showFilter:!1,repositoryEntriesWithVersions$:this.getSingleSoftwareWithVersions$(e)}).subscribe((function(e){t.emitSoftwareInstall(e)}))},i.prototype.removeSoftware=function(e){this.emitSoftwareRemoval([e])},i.prototype.getInstallableSoftwareListWithVersions$=function(t){var n=this,i=this.softwareList.map((function(e){return e.name}));return t.pipe(d.distinctUntilChanged(),d.switchMap((function(t){return n.repository.listRepositoryEntries(e.RepositoryType.SOFTWARE,{query:n.deviceTypeQuery,partialName:t,params:{pageSize:100}})})),d.map((function(e){return e.data})),d.map((function(e){return e.filter((function(e){return!i.includes(e.name)}))})),d.map((function(e){return n.attachVersions(e)})),d.shareReplay(1))},i.prototype.getSingleSoftwareWithVersions$=function(t){var n=this;return p.from(this.repository.listRepositoryEntries(e.RepositoryType.SOFTWARE,{query:{name:t.name}})).pipe(d.map((function(e){return e.data})),d.map((function(e){return n.attachVersions(e)})),d.shareReplay(1))},i.prototype.attachVersions=function(e){var t=this;return e.forEach((function(e){e.versions=t.repository.listBaseVersions(e)})),e},i.prototype.displaySoftwareSelectModal=function(t){var i=Object.assign({repositoryType:e.RepositoryType.SOFTWARE,subTitle:n.gettext("Available softwares matching the device type"),mode:n.ModalSelectionMode.MULTI,icon:"c8y-tools",disableSelected:!1,selected:this.softwareList},t),r=this.bsModal.show(V,{ignoreBackdropClick:!0,class:"modal-sm",initialState:i});return t.repositoryEntriesWithVersionsFn$&&(r.content.repositoryEntriesWithVersions$=t.repositoryEntriesWithVersionsFn$(r)),r.content.load.next(),r.content.resultEmitter},i.prototype.emitSoftwareInstall=function(e){this.changes.emit(e.map((function(e){return Object.assign(Object.assign({},e),{action:"install"})})))},i.prototype.emitSoftwareRemoval=function(e){this.changes.emit(e.map((function(e){return Object.assign(Object.assign({},e),{action:"delete"})})))},i}();G.decorators=[{type:t.Component,args:[{selector:"c8y-installed-software",template:'<div class="inner-scroll d-flex d-col">\n <div class="card-header large-padding separator sticky-top">\n <h4 class="card-title" translate>Installed software</h4>\n </div>\n <div class="flex-grow">\n <fieldset *ngIf="deviceSoftwareChangesOperation" class="card-block large-padding bg-gray-lighter">\n <c8y-single-operation [operation]="deviceSoftwareChangesOperation"></c8y-single-operation>\n </fieldset>\n\n <fieldset class="d-contents" [disabled]="deviceSoftwareChangesInProgress">\n \x3c!-- EMPTY STATE --\x3e\n <div class="card-block" *ngIf="softwareList.length === 0">\n <div class="c8y-empty-state text-center m-t-16">\n <h1 class="c8y-icon c8y-icon-tools c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No software installed.</strong> <br />\n <small translate>Click below to install software into this device.</small>\n </p>\n </div>\n </div>\n\n \x3c!-- NOT EMPTY STATE --\x3e\n <ng-container *ngIf="softwareList.length > 0">\n <c8y-device-software-list\n [softwareList]="softwareList"\n [deviceSoftwareChanges]="deviceSoftwareChanges"\n (update)="updateSoftware($event)"\n (remove)="removeSoftware($event)"\n class="d-block p-l-16 p-r-16"\n >\n </c8y-device-software-list>\n </ng-container>\n </fieldset>\n </div>\n\x3c!-- INSTALL SOFTWARE--\x3e\n <div class="card-footer large-padding separator sticky-bottom">\n <button\n class="btn btn-default"\n title="{{ \'Install software\' | translate }}"\n (click)="installSoftware()"\n [disabled]="deviceSoftwareChangesInProgress"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Install software\' | translate }}\n </button>\n </div>\n</div>\n'}]}],G.ctorParameters=function(){return[{type:O},{type:c.InventoryService},{type:y.BsModalService}]},G.propDecorators={softwareList:[{type:t.Input}],deviceSoftwareChanges:[{type:t.Input}],deviceSoftwareChangesOperation:[{type:t.Input}],deviceSoftwareChangesInProgress:[{type:t.Input}],deviceTypeQuery:[{type:t.Input}],changes:[{type:t.Output}]};var W=function(){function e(){this.update=new t.EventEmitter,this.remove=new t.EventEmitter}return e.prototype.ngAfterContentInit=function(){this.showUpdate=this.update.observers.length>0,this.showRemove=this.remove.observers.length>0},e.prototype.isSoftwareGoingToBeChanged=function(e){return l.filter(this.deviceSoftwareChanges,e).length>0},e}();W.decorators=[{type:t.Component,args:[{selector:"c8y-device-software-list",template:'<c8y-list-group class="no-border-last">\n <c8y-li\n [ngClass]="{ disabled: isSoftwareGoingToBeChanged(software) }"\n *ngFor="let software of softwareList"\n >\n \x3c!-- SOFTWARE ICON --\x3e\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-20">\n <div title="{{ software.name }}" class="col-8">\n \x3c!-- SOFTWARE NAME --\x3e\n <p class="text-truncate">{{ software.name }}</p>\n \x3c!-- SOFTWARE VERSION --\x3e\n <p class="text-truncate">\n <span class="text-label-small m-r-4" translate>\n Version\n </span>\n <span title="{{ software.version }}">\n {{ software.version }}\n </span>\n </p>\n </div>\n\n <div *ngIf="showUpdate || showRemove" class="col-4 text-right">\n \x3c!-- UPDATE SOFTWARE --\x3e\n <button\n *ngIf="showUpdate && !isSoftwareGoingToBeChanged(software)"\n class="btn btn-default btn-xs showOnHover"\n (click)="update.emit(software)"\n title="{{ \'Update`software,verb`\' | translate }}"\n translate\n >\n Update\n </button>\n\n \x3c!-- REMOVE SOFTWARE --\x3e\n <button\n *ngIf="showRemove && !isSoftwareGoingToBeChanged(software)"\n title="{{ \'Remove`software`\' | translate }}"\n class="showOnHover btn btn-dot pull-right"\n (click)="remove.emit(software)"\n >\n <i c8yIcon="minus-circle" class="text-danger"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n'}]}],W.propDecorators={softwareList:[{type:t.Input}],deviceSoftwareChanges:[{type:t.Input}],update:[{type:t.Output}],remove:[{type:t.Output}]};var q=function(){function e(){this.clear=new t.EventEmitter,this.drop=new t.EventEmitter,this.apply=new t.EventEmitter,this.changes$=new p.BehaviorSubject([]),this.installations$=this.changes$.pipe(d.map((function(e){return e.filter((function(e){return"install"===e.action}))}))),this.removals$=this.changes$.pipe(d.map((function(e){return e.filter((function(e){return"delete"===e.action}))})))}return e.prototype.ngOnChanges=function(e){e.changes&&this.changes$.next(e.changes.currentValue)},e}();q.decorators=[{type:t.Component,args:[{selector:"c8y-device-software-changes",template:'<div class="inner-scroll d-flex d-col">\n <div class="card-header separator large-padding sticky-top">\n <h4 class="card-title" translate>Software changes</h4>\n </div>\n <div class="flex-grow">\n <div class="card-block large-padding"\n *ngIf="(changes$ | async).length === 0; else changesList"\n >\n <div class="c8y-empty-state text-center">\n <h1 class="c8y-icon c8y-icon-device-control c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No software changes.</strong> <br />\n <small translate>Selected actions will be displayed here.</small>\n </p>\n </div>\n </div>\n\n <ng-template #changesList>\n <fieldset class="card-block p-t-0 p-b-0"\n *ngIf="(installations$ | async).length > 0"\n [disabled]="changesInProgress"\n >\n <div class="form-block legend" translate>Installations`software`</div>\n <c8y-device-software-list\n [softwareList]="installations$ | async"\n (remove)="drop.emit($event)"\n ></c8y-device-software-list>\n </fieldset>\n\n <fieldset class="card-block p-t-0 p-b-0"\n *ngIf="(removals$ | async).length > 0"\n [disabled]="changesInProgress"\n >\n <div class="form-block legend" translate>Removals`software`</div>\n <c8y-device-software-list\n [softwareList]="removals$ | async"\n (remove)="drop.emit($event)"\n ></c8y-device-software-list>\n </fieldset>\n </ng-template>\n </div>\n <div\n class="card-footer separator large-padding sticky-bottom"\n *ngIf="(changes$ | async).length > 0"\n >\n <button\n class="btn btn-default"\n (click)="clear.emit()"\n title="{{ \'Clear changes\' | translate }}"\n [disabled]="changesInProgress"\n translate\n >\n Clear`changes`\n </button>\n <button\n class="btn btn-primary"\n [ngClass]="{ \'btn-pending\': changesInProgress }"\n [disabled]="changesInProgress"\n (click)="apply.emit()"\n title="{{ \'Apply changes\' | translate }}"\n translate\n >\n Apply changes\n </button>\n </div>\n</div>\n'}]}],q.propDecorators={changes:[{type:t.Input}],changesInProgress:[{type:t.Input}],clear:[{type:t.Output}],drop:[{type:t.Output}],apply:[{type:t.Output}]};var z=function(){function e(){this.configurationsUpdated=new t.EventEmitter}return e.prototype.updateConfigurations=function(e){this.configurationsUpdated.emit(e)},e.prototype.hasAnySupportedOperation=function(e,t){var n=e.c8y_SupportedOperations;return!!n&&(Array.isArray(t)||(t=[t]),n.some((function(e){return t.includes(e)})))},e}();z.decorators=[{type:t.Injectable}];var Y=function(){function t(e,t,n,i,r){this.route=e,this.alertService=t,this.repositoryService=n,this.deviceConfigurationService=i,this.inventoryService=r,this.reloadingConfig=!1}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.load()];case 1:return e.sent(),[2]}}))}))},t.prototype.load=function(){return w(this,void 0,void 0,(function(){return S(this,(function(t){switch(t.label){case 0:return this.device=this.route.snapshot.parent.data.contextData,[4,this.loadDevice()];case 1:return t.sent(),[4,this.loadOperation()];case 2:return t.sent(),this.showTextBasedConfigReload=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.SEND_CONFIG]),this.showTextBasedConfigSave=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.CONFIG]),this.device.c8y_Configuration&&this.device.c8y_Configuration.config&&(this.config=this.device.c8y_Configuration.config),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e,t=this;return S(this,(function(n){switch(n.label){case 0:return[4,this.repositoryService.getLastConfigUpdateOperation(this.device.id)];case 1:return null!==(e=n.sent())&&this.repositoryService.observeOperation(e).subscribe((function(e){t.latestOperation=e})),[2]}}))}))},Object.defineProperty(t.prototype,"savingConfig",{get:function(){return!!this.latestOperation&&(this.latestOperation.status===c.OperationStatus.PENDING||this.latestOperation.status===c.OperationStatus.EXECUTING)},enumerable:!1,configurable:!0}),t.prototype.reloadConfiguration=function(){return w(this,void 0,void 0,(function(){var e,t=this;return S(this,(function(n){switch(n.label){case 0:return this.reloadingConfig=!0,[4,this.repositoryService.createTextBasedConfigurationReloadOperation(this.device)];case 1:e=n.sent();try{this.repositoryService.createObservedOperation(e).subscribe((function(e){return t.onOperationReloadSuccess(e)}),(function(e){return t.onOperationReloadError(e)}),(function(){return t.onOperationReloadComplete()}))}catch(e){this.alertService.addServerFailure(e)}return[2]}}))}))},t.prototype.updateConfiguration=function(e){return w(this,void 0,void 0,(function(){var t,n=this;return S(this,(function(i){switch(i.label){case 0:return[4,this.repositoryService.createTextBasedConfigurationUpdateOperation(this.device,e)];case 1:t=i.sent();try{this.repositoryService.createObservedOperation(t).subscribe((function(e){return n.onOperationUpdateSuccess(e)}),(function(e){return n.onOperationUpdateError(e)}),(function(){return n.onOperationUpdateComplete()}))}catch(e){this.alertService.addServerFailure(e)}return[2]}}))}))},t.prototype.onOperationReloadSuccess=function(e){this.latestOperation=e,e.status===c.OperationStatus.PENDING&&this.alertService.success(n.gettext("Configuration will be reloaded."))},t.prototype.onOperationReloadError=function(e){this.latestOperation=e,this.reloadingConfig=!1},t.prototype.onOperationReloadComplete=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),this.config=this.device.c8y_Configuration.config,this.reloadingConfig=!1,[2]}}))}))},t.prototype.onOperationUpdateSuccess=function(e){this.latestOperation=e,e.status===c.OperationStatus.PENDING&&this.alertService.success(n.gettext("Configuration will be updated."))},t.prototype.onOperationUpdateError=function(e){this.latestOperation=e},t.prototype.onOperationUpdateComplete=function(){this.device.c8y_Configuration.config=this.config},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return e=this,[4,this.inventoryService.detail(this.device.id,{withChildren:!1})];case 1:return e.device=t.sent().data,[2]}}))}))},t}();Y.decorators=[{type:t.Component,args:[{selector:"c8y-text-based-configuration",template:'<div class="d-flex d-col fit-h">\n <fieldset *ngIf="latestOperation !== undefined" class="card-block bg-gray-white fit-w">\n <div class="content-flex-50">\n <c8y-single-operation [operation]="latestOperation" class="flex-grow"></c8y-single-operation>\n <div class="flex-item-right d-flex">\n <button\n title="{{ \'Get snapshot from device\' | translate }}"\n type="button"\n class="btn btn-default btn-sm flex-item-v-center m-t-8 m-b-8"\n *ngIf="showTextBasedConfigReload"\n (click)="reloadConfiguration()"\n [disabled]="reloadingConfig || savingConfig"\n >\n <i\n c8yIcon="refresh"\n *ngIf="reloadingConfig"\n class="m-r-4"\n [ngClass]="{ \'icon-spin\': reloadingConfig }"\n ></i>\n <i c8yIcon="download" *ngIf="!reloadingConfig" class="m-r-4"></i>\n\n {{ \'Get snapshot from device\' | translate }}\n </button>\n </div>\n </div>\n </fieldset>\n <div class="flex-grow">\n <textarea\n [(ngModel)]="config"\n class="form-control fit-h p-r-16 p-l-16"\n [disabled]="reloadingConfig || savingConfig"\n c8y-spellcheck="false"\n ></textarea>\n </div>\n <div class="card-footer fit-w separator" *ngIf="showTextBasedConfigSave">\n <button\n type="button"\n (click)="updateConfiguration(config)"\n [disabled]="reloadingConfig || savingConfig"\n class="btn btn-primary"\n [ngClass]="{ \'btn-pending\': savingConfig }"\n >\n <span title="{{ \'Send\' | translate }}" *ngIf="!savingConfig">\n {{ \'Send configuration to device\' | translate }}\n </span>\n <span title="{{ \'Sending…\' | translate }}" *ngIf="savingConfig">\n {{ \'Sending…\' | translate }}\n </span>\n </button>\n </div>\n</div>\n'}]}],Y.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:n.AlertService},{type:O},{type:z},{type:c.InventoryService}]};var Q=function(){function t(e,t,n,i){var r=this;this.route=e,this.deviceConfigurationService=t,this.realtime=n,this.repositoryService=i,this.supportedConfigurations=[],this.showBinaryBasedConfig=!1,this.configSnapshot={},this.reloading=!1,this.deviceConfigurationService.configurationsUpdated.subscribe((function(e){r.updateSnapshots(e)}))}return t.prototype.ngOnInit=function(){this.device=this.route.snapshot.parent.data.contextData,this.device.c8y_SupportedConfigurations&&(this.supportedConfigurations=this.device.c8y_SupportedConfigurations.map((function(e){return{name:e}}))),this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.DOWNLOAD_CONFIG,e.DeviceConfigurationOperation.UPLOAD_CONFIG])&&this.supportedConfigurations.push({name:n.gettext("Legacy configuration snapshot"),isLegacy:!0}),this.supportedConfigurations.length>0&&(this.showBinaryBasedConfig=!0),this.repositorySnapshotsEmptyState={icon:"gears",title:n.gettext("No configurations available."),text:n.gettext("Add configuration to configuration repository")},this.showTextBasedConfig=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.CONFIG,e.DeviceConfigurationOperation.SEND_CONFIG])},t.prototype.onConfigTypeSelected=function(e){return w(this,void 0,void 0,(function(){return S(this,(function(t){return this.configurationType=e.name,this.isLegacy=e.isLegacy,this.updateSnapshots(),[2]}))}))},t.prototype.onRepositoryConfigSelected=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:if(this.repositorySnapshot={id:e.id,time:e.creationTime,name:e.name,binaryUrl:e.url,deviceType:e.deviceType,configurationType:e.configurationType},!e.url)return[3,6];i.label=1;case 1:return i.trys.push([1,5,,6]),[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 2:return(t=i.sent())?(n=this.repositorySnapshot,[4,t.text()]):[3,4];case 3:n.binary=i.sent(),i.label=4;case 4:return[3,6];case 5:return i.sent(),[3,6];case 6:return[2]}}))}))},t.prototype.updateSnapshots=function(e){return w(this,void 0,void 0,(function(){var t,n,i;return S(this,(function(r){switch(r.label){case 0:return this.reloading=!0,this.repositorySnapshot=void 0,t=this,[4,this.repositoryService.getSnapshotsFromRepository(this.device,this.configurationType)];case 1:return t.repositorySnapshots=r.sent(),e?[3,6]:(n=this,this.isLegacy?[4,this.repositoryService.getLegacyConfigSnapshot(this.device)]:[3,3]);case 2:return i=r.sent(),[3,5];case 3:return[4,this.repositoryService.getConfigSnapshot(this.device,this.configurationType)];case 4:i=r.sent(),r.label=5;case 5:n.configSnapshot=i,r.label=6;case 6:return this.showTextBasedConfig?[4,this.textBasedConfigurationComponent.load()]:[3,8];case 7:r.sent(),r.label=8;case 8:return this.reloading=!1,[2]}}))}))},t}();Q.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration",template:'<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="updateSnapshots()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="card content-fullpage card-has-tabs">\n <tabset>\n <div class="card-header separator" *ngIf="showBinaryBasedConfig && !showTextBasedConfig">\n <h4 class="card-title">{{ \'Configurations\' | translate }}</h4>\n </div>\n <div class="card-header separator" *ngIf="!showBinaryBasedConfig && showTextBasedConfig">\n <h4 class="card-title">{{ \'Text-based configuration\' | translate }}</h4>\n </div>\n <tab heading="{{ \'Configurations\' | translate }}" *ngIf="showBinaryBasedConfig">\n <div class="card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0">\n \x3c!-- DEVICE SUPPORTED CONFIGURATIONS --\x3e\n <div class="card--grid__inner-scroll bg-gray-white">\n <div class="p-l-16 p-r-16">\n <h5 class="legend form-block">\n <span translate>Device-supported configurations</span>\n </h5>\n </div>\n <c8y-device-configuration-list\n [items]="supportedConfigurations"\n [itemIcon]="\'gears\'"\n (configSelected)="onConfigTypeSelected($event)"\n ></c8y-device-configuration-list>\n </div>\n\n \x3c!-- CONFIGURATION PREVIEW --\x3e\n <div class="card--grid__inner-scroll d-flex d-col flex-grow">\n <div class="card-block d-flex d-col flex-grow">\n <h5 class="legend form-block"><span translate>Preview</span></h5>\n\n \x3c!-- EMPTY STATE --\x3e\n <div class="c8y-empty-state text-left" *ngIf="!configurationType">\n <h1 [c8yIcon]="\'file-text\'"></h1>\n <p>\n <strong translate>No configuration selected.</strong><br />\n <small translate>Select a configuration to preview</small>\n </p>\n </div>\n\n \x3c!-- PREVIEW AVAILABLE STATE --\x3e\n <c8y-device-configuration-preview\n *ngIf="configurationType"\n [device]="device"\n [configurationType]="configurationType"\n [configSnapshot]="configSnapshot"\n [canSaveSnapshot]="true"\n [operationToTrigger]="\'c8y_UploadConfigFile\'"\n [actionButtonText]="\'Get snapshot from device\' | translate"\n [actionButtonIcon]="\'download\'"\n [isLegacy]="isLegacy"\n class="d-flex d-col flex-grow"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n\n \x3c!-- AVAILABLE SUPPORTED CONFIGURATIONS --\x3e\n <div class="card--grid__inner-scroll bg-gray-white">\n <div class="p-l-16 p-r-16">\n <h5 class="legend form-block" translate>Available supported configurations</h5>\n </div>\n\n \x3c!-- EMPTY STATE --\x3e\n <div class="c8y-empty-state text-left" *ngIf="!configurationType">\n <h1 [c8yIcon]="\'gears\'"></h1>\n <p>\n <strong translate>No selection</strong><br />\n <small translate\n >Select a configuration from the device-supported configuration list</small\n >\n </p>\n </div>\n <div class="p-r-16" *ngIf="configurationType">\n <c8y-device-configuration-list\n [items]="repositorySnapshots"\n [itemIcon]="\'file-text\'"\n [emptyState]="repositorySnapshotsEmptyState"\n [isFilterEnabled]="true"\n (configSelected)="onRepositoryConfigSelected($event)"\n ></c8y-device-configuration-list>\n </div>\n </div>\n\n \x3c!-- CONFIGURATION PREVIEW --\x3e\n <div class="card--grid__inner-scroll d-flex d-col flex-grow">\n <div class="card-block flex-grow d-flex d-col">\n <h5 class="legend form-block" translate>Preview</h5>\n\n \x3c!-- EMPTY STATE --\x3e\n\n <div class="c8y-empty-state text-left" *ngIf="!repositorySnapshot">\n <h1 [c8yIcon]="\'file-text\'"></h1>\n <p>\n <strong translate>No configuration selected.</strong><br />\n <small *ngIf="!configurationType; else noSnapshot" translate\n >Select a configuration to preview</small\n >\n <ng-template #noSnapshot>\n <small translate>Select the configuration you want to preview</small>\n </ng-template>\n </p>\n </div>\n\n \x3c!-- CONFIGURATION SELECTED STATE --\x3e\n <c8y-device-configuration-preview\n *ngIf="repositorySnapshot"\n [device]="device"\n [configurationType]="configurationType"\n [configSnapshot]="repositorySnapshot"\n [operationToTrigger]="\'c8y_DownloadConfigFile\'"\n [actionButtonText]="\'Send configuration to device\' | translate"\n [actionButtonIcon]="\'upload\'"\n [isLegacy]="isLegacy"\n class="d-flex d-col flex-grow"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n </div>\n </tab>\n <tab heading="{{ \'Text-based configuration\' | translate }}" *ngIf="showTextBasedConfig">\n <c8y-text-based-configuration></c8y-text-based-configuration>\n </tab>\n </tabset>\n</div>\n'}]}],Q.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:z},{type:c.Realtime},{type:O}]},Q.propDecorators={textBasedConfigurationComponent:[{type:t.ViewChild,args:[Y]}]};var K=function(){};K.decorators=[{type:t.Component,args:[{selector:"c8y-source-code-preview",template:'<textarea [disabled]="isDisabled" class="text-monospace form-control no-resize flex-grow" rows="8">{{ text }}</textarea>\n'}]}],K.propDecorators={isDisabled:[{type:t.Input}],text:[{type:t.Input}]};var H=function(){function t(e,t,n){var i=this;this.modal=e,this.alertService=t,this.repositoryService=n,this.result=new Promise((function(e,t){i._save=e,i._cancel=t}))}return t.prototype.save=function(){return w(this,void 0,void 0,(function(){var t,i;return S(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),t={selected:{configurationType:this.configSnapshot.configurationType},version:this.configSnapshot.name,deviceType:this.configSnapshot.deviceType,description:this.configSnapshot.description,binary:{file:new File([this.configSnapshot.binary],this.configSnapshot.name)}},[4,this.repositoryService.save(t,e.RepositoryType.CONFIGURATION)];case 1:return r.sent(),this.alertService.success(n.gettext("Configuration saved.")),this._save(),[3,3];case 2:return i=r.sent(),this.alertService.addServerFailure(i),[3,3];case 3:return[2]}}))}))},t.prototype.close=function(){this._cancel(),this.modal.hide()},t}();H.decorators=[{type:t.Component,args:[{selector:"c8y-save-config-to-configuration-repository",template:'<div class="modal-header bg-primary text-center text-white">\n <div style="font-size: 62px;">\n <span c8yIcon="gears"></span>\n </div>\n <h4 class="text-uppercase" translate>\n Save configuration\n </h4>\n</div>\n<div class="modal-body">\n <form #saveConfigurationSnapshot="ngForm" class="p-t-24">\n <c8y-form-group>\n <label translate for="name">Name</label>\n <input\n id="name"\n type="text"\n class="form-control"\n autocomplete="off"\n name="name"\n [(ngModel)]="configSnapshot.name"\n required\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="deviceType">Device type</label>\n <input\n id="deviceType"\n class="form-control"\n rows="6"\n name="deviceType"\n [(ngModel)]="configSnapshot.deviceType"\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="description">Description</label>\n <input\n type="text"\n id="description"\n class="form-control"\n maxlength="254"\n autocomplete="off"\n name="description"\n [(ngModel)]="configSnapshot.description"\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="configurationType">Configuration type</label>\n <input\n id="configurationType"\n class="form-control"\n rows="6"\n name="configurationType"\n [(ngModel)]="configSnapshot.configurationType"\n />\n </c8y-form-group>\n </form>\n</div>\n<div class="modal-footer">\n <button title="{{ \'Cancel\' | translate }}" class="btn btn-default" (click)="close()" translate>\n Cancel\n </button>\n\n <button\n title="{{ \'Save configuration to repository\' | translate }}"\n class="btn btn-primary"\n (click)="save()"\n [disabled]="saveConfigurationSnapshot.form.invalid"\n translate\n >\n Save\n </button>\n</div>\n'}]}],H.ctorParameters=function(){return[{type:y.BsModalRef},{type:n.AlertService},{type:O}]};var X=function(){function t(t,n,i,r,a,o,s,c,l){this.deviceConfigurationService=t,this.realtime=n,this.operationRealtime=i,this.bsModal=r,this.user=a,this.appState=o,this.repositoryService=s,this.operationService=c,this.alertService=l,this.isLegacy=!1,this.canCallAction=!0,this.deviceConfigurationOperation=e.DeviceConfigurationOperation}return Object.defineProperty(t.prototype,"configurationType",{get:function(){return this._configurationType},set:function(e){this._configurationType=e,this.setOperation(e)},enumerable:!1,configurable:!0}),t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){var e=this;return S(this,(function(t){return this.setOperation(this._configurationType),this.operationsSubscription=this.operationRealtime.onAll$(this.device.id).pipe(d.map((function(e){return e.data}))).subscribe((function(t){e.updatePreview(t)})),this.isLegacy&&(this.canCallAction=this.deviceConfigurationService.hasAnySupportedOperation(this.device,this.operationToTrigger)),[2]}))}))},t.prototype.setOperation=function(e){return w(this,void 0,void 0,(function(){var t,n,i=this;return S(this,(function(r){switch(r.label){case 0:return[4,this.repositoryService.getConfigFileOperationList(this.device.id,this.operationToTrigger)];case 1:return t=r.sent(),n=this.isLegacy?t.find((function(e){return e[i.operationToTrigger]&&!e[i.operationToTrigger].type})):t.find((function(t){return t[i.operationToTrigger].type===e})),this.operation=n&&n.status!==c.OperationStatus.SUCCESSFUL?n:void 0,[2]}}))}))},t.prototype.createDeviceOperation=function(){return w(this,void 0,void 0,(function(){var t,n,i;return S(this,(function(r){switch(r.label){case 0:this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG&&(t=this.repositoryService.getDownloadConfigurationFileOperation(this.device,this._configurationType,this.configSnapshot,this.isLegacy)),this.operationToTrigger===e.DeviceConfigurationOperation.UPLOAD_CONFIG&&(t=this.repositoryService.getUploadConfigurationFileOperation(this.device,this._configurationType,this.isLegacy)),r.label=1;case 1:return r.trys.push([1,3,,4]),n=this,[4,this.operationService.create(t)];case 2:return n.operation=r.sent().data,[3,4];case 3:return i=r.sent(),this.alertService.addServerFailure(i),[3,4];case 4:return[2]}}))}))},t.prototype.showOperation=function(){return this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG?!!this.operation:this.operation&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING,c.OperationStatus.FAILED].includes(this.operation.status)},t.prototype.showBinary=function(){return this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG||!this.showOperation()},t.prototype.isCreateOperationDisabled=function(){return this.operation&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(this.operation.status)},t.prototype.updatePreview=function(e){e&&e[this.operationToTrigger]&&(this.isLegacy||e[this.operationToTrigger].type&&e[this.operationToTrigger].type===this.configurationType)&&(this.operation=e,this.updateSnapshotsOnConfigUpload(e))},t.prototype.download=function(){var e=new Blob([this.configSnapshot.binary],{type:this.configSnapshot.binaryType}),t=this.configSnapshot.name;switch(this.configSnapshot.binaryType){case"text/csv":case"application/csv":t=t.concat(".csv");break;case"text/yaml":case"application/x-yaml":t=t.concat(".yaml");break;case"application/json":t=t.concat(".json")}g.saveAs(e,t)},t.prototype.saveToRepository=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:e={configSnapshot:l.cloneDeep(this.configSnapshot)},t=this.bsModal.show(H,{class:"modal-sm",initialState:e,ignoreBackdropClick:!0}).content,n.label=1;case 1:return n.trys.push([1,3,,4]),[4,t.result];case 2:return n.sent(),this.deviceConfigurationService.updateConfigurations(!0),t.close(),[3,4];case 3:return n.sent(),[3,4];case 4:return[2]}}))}))},t.prototype.hasPermission=function(){return this.user.hasAnyRole(this.appState.currentUser.value,["ROLE_INVENTORY_ADMIN","ROLE_INVENTORY_CREATE"])},t.prototype.ngOnDestroy=function(){this.operationsSubscription&&this.operationsSubscription.unsubscribe()},t.prototype.updateSnapshotsOnConfigUpload=function(t){return w(this,void 0,void 0,(function(){return S(this,(function(n){return t[e.DeviceConfigurationOperation.UPLOAD_CONFIG]&&t.status===c.OperationStatus.SUCCESSFUL&&this.deviceConfigurationService.updateConfigurations(),[2]}))}))},t}();X.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration-preview",template:'<div class="content-flex-55 p-b-16">\n <div class="col-7 p-t-4">\n <p>\n <span class="text-label-small text-uppercase m-r-4" translate>Configuration</span>\n <span *ngIf="configSnapshot?.name; else emptyText">\n <strong>{{ configSnapshot.name }}</strong>\n </span>\n <ng-template #emptyText> --- </ng-template>\n </p>\n <p>\n <span class="text-label-small text-uppercase m-r-4" translate>Last updated</span>\n <small *ngIf="configSnapshot?.time; else emptyDate">\n {{ configSnapshot.time | c8yDate }}\n </small>\n <ng-template #emptyDate> --- </ng-template>\n </p>\n </div>\n <div class="col-5">\n <button\n class="btn btn-default btn-sm pull-right"\n type="button"\n title="{{ actionButtonText | translate }}"\n (click)="createDeviceOperation()"\n [disabled]="isCreateOperationDisabled()"\n *ngIf="canCallAction"\n >\n <i [c8yIcon]="actionButtonIcon"></i> {{ actionButtonText | translate }}\n </button>\n </div>\n</div>\n<div class="c8y-empty-state text-left" *ngIf="!configSnapshot?.binary && showBinary()">\n <h1 [c8yIcon]="\'file-image-o\'"></h1>\n <p>\n <strong translate>No preview available.</strong><br />\n <small *ngIf="configSnapshot?.binary !== \'\'; else emptyFile" translate\n >The file is not available.</small\n >\n <ng-template #emptyFile>\n <small translate>The file is empty.</small>\n </ng-template>\n </p>\n</div>\n<div *ngIf="configSnapshot?.binary && showBinary()" class="flex-grow d-flex d-col">\n <c8y-source-code-preview\n [text]="configSnapshot.binary"\n [isDisabled]="true"\n class="d-contents"\n ></c8y-source-code-preview>\n <div *ngIf="canSaveSnapshot" class="p-t-16">\n <button\n type="button"\n class="btn btn-primary btn-sm pull-right m-l-8"\n (click)="download()"\n translate\n >\n Download\n </button>\n <button\n *ngIf="hasPermission()"\n type="button"\n class="btn btn-default btn-sm pull-right"\n (click)="saveToRepository()"\n translate\n >\n Save to repository\n </button>\n </div>\n</div>\n<div *ngIf="showOperation()">\n <c8y-single-operation [operation]="operation"></c8y-single-operation>\n</div>\n'}]}],X.ctorParameters=function(){return[{type:z},{type:c.Realtime},{type:n.OperationRealtimeService},{type:y.BsModalService},{type:c.UserService},{type:n.AppStateService},{type:O},{type:c.OperationService},{type:n.AlertService}]},X.propDecorators={device:[{type:t.Input}],configurationType:[{type:t.Input}],configSnapshot:[{type:t.Input}],canSaveSnapshot:[{type:t.Input}],actionButtonText:[{type:t.Input}],actionButtonIcon:[{type:t.Input}],isLegacy:[{type:t.Input}],operationToTrigger:[{type:t.Input}]};var Z=function(){function e(){}return e.prototype.transform=function(e,t){var n=this;return 0===t.trim().length?e:e.filter((function(e){return n.filterContainString(e.name,t)||n.filterContainString(e.deviceType,t)}))},e.prototype.filterContainString=function(e,t){var n=t.toLowerCase().trim();return e&&e.toLowerCase().indexOf(n)>-1},e}();Z.decorators=[{type:t.Pipe,args:[{name:"configurationFilterPipe"}]}];var J=function(){function t(e){this.deviceConfigurationService=e}return t.prototype.canActivate=function(t,n){var i=t.data.contextData||t.parent.data.contextData;return!!i&&(i.c8y_SupportedConfigurations&&i.c8y_SupportedConfigurations.length>0||this.deviceConfigurationService.hasAnySupportedOperation(i,[e.DeviceConfigurationOperation.DOWNLOAD_CONFIG,e.DeviceConfigurationOperation.UPLOAD_CONFIG,e.DeviceConfigurationOperation.CONFIG,e.DeviceConfigurationOperation.SEND_CONFIG]))},t}();J.decorators=[{type:t.Injectable}],J.ctorParameters=function(){return[{type:z}]};var ee,te=function(){function e(){this.configSelected=new t.EventEmitter,this.filterTerm=""}return e.prototype.showConfigurationTypePreview=function(e){this.selectedConfig=e,this.configSelected.emit(e)},e.prototype.updatePipe=function(e){this.filterTerm=e},e}();te.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration-list",template:'<div class="p-l-16 m-b-8" *ngIf="isFilterEnabled">\n <c8y-filter [icon]="\'search\'" (onSearch)="updatePipe($event)"></c8y-filter>\n</div>\n\n\x3c!-- EMPTY STATE --\x3e\n<div class="c8y-empty-state text-left" *ngIf="items?.length === 0">\n <h1 [c8yIcon]="emptyState.icon"></h1>\n <p>\n <strong>{{ emptyState.title | translate }}</strong\n ><br />\n <small>{{ emptyState.text | translate }}</small>\n </p>\n</div>\n\n\x3c!-- CONFIGURATIONS AVAILABLE --\x3e\n<div class="c8y-nav-stacked">\n <div\n class="c8y-stacked-item flex-row"\n [class.active]="config === selectedConfig"\n *ngFor="let config of items | configurationFilterPipe: filterTerm"\n (click)="showConfigurationTypePreview(config)"\n >\n <div class="list-item-icon">\n <i [c8yIcon]="itemIcon"></i>\n </div>\n <div class="list-item-body text-truncate">\n <div class="d-flex">\n <span class="text-truncate" title="{{ config.name }}">{{ config.name }}</span>\n <span class="text-label-small flex-item-right flex-item-middle">{{ config.deviceType }}</span>\n </div>\n </div>\n </div>\n</div>\n\n\x3c!-- for Carlos: config.configurationType to differentiate whether a config matches configuration type. --\x3e\n'}]}],te.propDecorators={items:[{type:t.Input}],itemIcon:[{type:t.Input}],emptyState:[{type:t.Input}],isFilterEnabled:[{type:t.Input}],configSelected:[{type:t.Output}]},function(e){e[e.DOWNLOAD=0]="DOWNLOAD",e[e.LINK=1]="LINK",e[e.TEXTONLY=2]="TEXTONLY"}(ee||(ee={}));var ne=function(){function e(e,t){this.repositoryService=e,this.inventoryBinaryService=t,this.linkRenderType=ee}return e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.determineBehavior=function(){return this.inventoryBinaryService.getIdFromUrl(this.url)?ee.DOWNLOAD:this.url.match(/\/\//g)?ee.LINK:ee.TEXTONLY},e.prototype.downloadFile=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repositoryService.getBinaryFile(this.url,{allowExternal:!1})];case 1:return e=t.sent(),h.saveAs(e),[2]}}))}))},e}();ne.decorators=[{type:t.Component,args:[{selector:"c8y-file-download",template:'<a\n *ngIf="determineBehavior() === linkRenderType.LINK"\n href="{{ url }}"\n class="pointer"\n target="_blank"\n rel="noopener noreferrer"\n>\n {{ getBinaryName$(url) | async }}\n</a>\n\n<span *ngIf="determineBehavior() === linkRenderType.TEXTONLY">{{ getBinaryName$(url) | async }}</span>\n\n<a *ngIf="determineBehavior() === linkRenderType.DOWNLOAD" class="pointer" (click)="downloadFile()">\n {{getBinaryName$(url) | async}}\n</a>\n'}]}],ne.ctorParameters=function(){return[{type:O},{type:c.InventoryBinaryService}]},ne.propDecorators={url:[{type:t.Input}]},b([n.memoize()],ne.prototype,"getBinaryName$",null),b([n.memoize()],ne.prototype,"determineBehavior",null);var ie=[{path:"firmware",component:R},{path:"firmware/:id",component:_},{context:n.ViewContext.Device,path:"firmware",component:N,label:n.gettext("Firmware"),icon:"c8y-firmware",priority:500,canActivate:[L]},{path:"software",component:A},{path:"software/:id",component:B},{context:n.ViewContext.Device,path:"software",component:U,label:n.gettext("Software"),icon:"c8y-tools",priority:499,canActivate:[j]},{path:"configuration",component:M},{context:n.ViewContext.Device,path:"device-configuration",component:Q,label:n.gettext("Configuration"),icon:"gears",priority:600,canActivate:[J]}],re=function(){};re.decorators=[{type:t.NgModule,args:[{imports:[n.CoreModule,n.FormsModule,s.SingleOperationDetailsModule,i.BsDropdownModule.forRoot(),a.TooltipModule,o.PopoverModule,r.TabsModule.forRoot()],exports:[],declarations:[R,_,$,E,A,B,D,N,U,G,V,W,q,M,P,Q,te,K,X,Z,H,Y,ne],entryComponents:[R,_,$,E,A,B,D,N,U,W,V,q,M,P,Q,H,Y],providers:[O,n.OperationRealtimeService,z,L,j,J,{provide:n.HOOK_NAVIGATOR_NODES,useClass:k,multi:!0},{provide:n.HOOK_ONCE_ROUTE,useValue:ie,multi:!0}]}]}],e.AddFirmwareModalComponent=$,e.AddFirmwarePatchModalComponent=E,e.AddSoftwareModalComponent=D,e.ConfigurationDetailComponent=P,e.ConfigurationFilterPipe=Z,e.ConfigurationListComponent=M,e.ConfigurationPreviewComponent=X,e.DeviceConfigurationComponent=Q,e.DeviceConfigurationGuard=J,e.DeviceConfigurationListComponent=te,e.DeviceConfigurationService=z,e.DeviceSoftwareChangesComponent=q,e.DeviceSoftwareListComponent=W,e.FirmwareDetailsComponent=_,e.FirmwareDeviceTabComponent=N,e.FirmwareDeviceTabGuard=L,e.FirmwareListComponent=R,e.InstalledSoftwareComponent=G,e.REPOSITORY_BINARY_TYPES=T,e.RepositoryModule=re,e.RepositoryNavigationFactory=k,e.RepositorySelectModalComponent=V,e.RepositoryService=O,e.SaveToRepositoryComponent=H,e.SoftwareDetailsComponent=B,e.SoftwareDeviceTabComponent=U,e.SoftwareDeviceTabGuard=j,e.SoftwareListComponent=A,e.SourceCodePreviewComponent=K,e.TextBasedConfigurationComponent=Y,e.ɵ0=ie,e.ɵa=ne,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
15
|
+
***************************************************************************** */var v,m;function b(e,t,n,i){var r,a=arguments.length,o=a<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,i);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(o=(a<3?r(o):a>3?r(t,n,o):r(t,n))||o);return a>3&&o&&Object.defineProperty(t,n,o),o}function w(e,t,n,i){return new(n||(n=Promise))((function(r,a){function o(e){try{c(i.next(e))}catch(e){a(e)}}function s(e){try{c(i.throw(e))}catch(e){a(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,s)}c((i=i.apply(e,t||[])).next())}))}function S(e,t){var n,i,r,a,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(a){return function(s){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;o;)try{if(n=1,i&&(r=2&a[0]?i.return:a[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,a[1])).done)return r;switch(i=0,r&&(a=[2&a[0],r.value]),a[0]){case 0:case 1:r=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,i=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(r=o.trys,(r=r.length>0&&r[r.length-1])||6!==a[0]&&2!==a[0])){o=0;continue}if(3===a[0]&&(!r||a[1]>r[0]&&a[1]<r[3])){o.label=a[1];break}if(6===a[0]&&o.label<r[1]){o.label=r[1],r=a;break}if(r&&o.label<r[2]){o.label=r[2],o.ops.push(a);break}r[2]&&o.ops.pop(),o.trys.pop();continue}a=t.call(e,o)}catch(e){a=[6,e],i=0}finally{n=r=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,s])}}}function x(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],i=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&i>=e.length&&(e=void 0),{value:e&&e[i++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var i,r,a=n.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(i=a.next()).done;)o.push(i.value)}catch(e){r={error:e}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(r)throw r.error}}return o}function I(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(C(arguments[t]));return e}e.RepositoryType=void 0,(m=e.RepositoryType||(e.RepositoryType={})).FIRMWARE="c8y_Firmware",m.SOFTWARE="c8y_Software",m.CONFIGURATION="c8y_ConfigurationDump";var F,T=((v={})[e.RepositoryType.SOFTWARE]="c8y_SoftwareBinary",v[e.RepositoryType.FIRMWARE]="c8y_FirmwareBinary",v[e.RepositoryType.CONFIGURATION]="c8y_ConfigurationDumpBinary",v);e.DeviceConfigurationOperation=void 0,(F=e.DeviceConfigurationOperation||(e.DeviceConfigurationOperation={})).UPLOAD_CONFIG="c8y_UploadConfigFile",F.DOWNLOAD_CONFIG="c8y_DownloadConfigFile",F.CONFIG="c8y_Configuration",F.SEND_CONFIG="c8y_SendConfiguration";var O=function(){function t(e,t,n,i,r,a,o){this.inventory=e,this.inventoryBinary=t,this.operation=n,this.alert=i,this.event=r,this.operationRealtime=a,this.eventBinary=o,this.dateFrom=new Date(0),this.dateTo=new Date(Date.now()+864e5),this.queriesUtil=new c.QueriesUtil}return t.prototype.listRepositoryEntries=function(e,t){var n,i={type:e},r=t&&t.query||{};if(r=this.queriesUtil.addOrderbys(r,[{name:1}],"prepend"),r=this.queriesUtil.addAndFilter(r,i),t&&t.partialTextFilter){var a=t.partialTextFilter,o=a.partialText,s={__or:a.properties.map((function(e){var t;return(t={})[e]="*"+o+"*",t}))};r=this.queriesUtil.addAndFilter(r,s)}return t&&t.partialName&&(r=this.queriesUtil.addAndFilter(r,{name:"*"+t.partialName+"*"})),t&&t.skipLegacy&&(r=this.queriesUtil.addAndFilter(r,{__not:{__has:"url"}})),n=Object.assign({query:this.queriesUtil.buildQuery(r),pageSize:50,withTotalPages:!0},t&&t.params||{}),this.inventory.list(n)},t.prototype.save=function(t,n,i){return void 0===i&&(i={}),w(this,void 0,void 0,(function(){var r,a;return S(this,(function(o){switch(o.label){case 0:switch(n){case e.RepositoryType.CONFIGURATION:Object.assign(i,{type:e.RepositoryType.CONFIGURATION,configurationType:t.selected?t.selected.configurationType:void 0,name:t.version,description:t.description,deviceType:t.deviceType,c8y_Global:{}}),!t.deviceType&&i.id&&(i.deviceType=null),!t.selected&&i.id&&(i.configurationType=null)}return r=i.url,t.binary.url?(i.url=t.binary.url,[3,3]):[3,1];case 1:return t.binary.file?[4,this.inventoryBinary.create(t.binary.file,{c8y_Global:{}})]:[3,3];case 2:a=o.sent(),i.url=a.data.self,o.label=3;case 3:return i.id?[2,this.updateEntry(i,r)]:[2,this.createEntry(i)]}}))}))},t.prototype.create=function(t,n){return w(this,void 0,void 0,(function(){return S(this,(function(i){switch(n){case e.RepositoryType.FIRMWARE:case e.RepositoryType.SOFTWARE:return[2,this.createFirmwareOrSoftware(t,n)]}return[2]}))}))},t.prototype.createFirmwareOrSoftware=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r,a,o,s,c,p,d,u;return S(this,(function(y){switch(y.label){case 0:o=[],s=e.selected.id,c=e.binary,p=c.file,d=c.url,y.label=1;case 1:return y.trys.push([1,9,,10]),p?[4,this.saveBinary(p)]:[3,3];case 2:return n=y.sent().data,i=n.self,o.push(n),[3,4];case 3:i=d,y.label=4;case 4:return[4,this.createOrUpdateRepositoryEntry(e,t)];case 5:return r=y.sent().data,l.isNil(s)&&o.push(r),[4,this.createRepositoryBinary(e,i,t,r)];case 6:return a=y.sent().data,o.push(a),p?[4,this.linkBinary(a,n)]:[3,8];case 7:y.sent(),y.label=8;case 8:return[2,r];case 9:throw u=y.sent(),this.cleanUp(o),this.errorMsg(),u;case 10:return[2]}}))}))},t.prototype.saveBinary=function(e){return this.inventoryBinary.create(e,{c8y_Global:{}})},t.prototype.createOrUpdateRepositoryEntry=function(e,t){var n=e.selected,i=n.id,r=n.name,a=e.description,o=e.deviceType,s={id:i,name:i?void 0:r,description:a,type:i?void 0:t,c8y_Global:{}};return o&&l.set(s,"c8y_Filter.type",o),i?this.inventory.update(s):this.inventory.create(s)},t.prototype.createRepositoryBinary=function(e,t,n,i){var r=this.prepareRepositoryBinaryMO(e,t,n);return this.inventory.childAdditionsCreate(r,i)},t.prototype.prepareRepositoryBinaryMO=function(e,t,n){var i,r=e.version,a=e.patchVersion,o=e.dependency,s=((i={type:T[n]})[n]={url:t},i.c8y_Global={},i);return o?(l.set(s,[n,"version"],a),l.assign(s,{c8y_Patch:{dependency:o.c8y_Firmware.version}})):l.set(s,[n,"version"],r),s},t.prototype.linkBinary=function(e,t){return w(this,void 0,void 0,(function(){var n,i;return S(this,(function(r){return n=e.id,t?(i=t.id,[2,this.inventory.childAdditionsAdd(i,n)]):[2]}))}))},t.prototype.cleanUp=function(e){var t=this;e.forEach((function(e){var n=e.c8y_IsBinary;l.isUndefined(n)?t.delete(e):t.inventoryBinary.delete(e)}))},t.prototype.delete=function(e){return this.inventory.delete(e,{forceCascade:!0})},t.prototype.errorMsg=function(){var e=n.gettext("Failed to save");this.alert.danger(e)},t.prototype.getBaseVersionsCount$=function(e){return this.isLegacyEntry(e)?p.of(1):p.from(this.listBaseVersions(e,{pageSize:1,withTotalPages:!0})).pipe(d.map((function(e){return e.paging.totalPages})))},t.prototype.getBaseVersionFromMO=function(e){return this.isPatch(e)?l.get(e,"c8y_Patch.dependency"):l.get(e,"c8y_Firmware.version")},t.prototype.isPatch=function(e){return!!l.get(e,"c8y_Patch.dependency")},t.prototype.getPatchVersionsCount$=function(e,t){return this.isLegacyEntry(t)?p.of(0):p.from(this.listPatchVersions(e,t,{pageSize:1,withTotalPages:!0})).pipe(d.map((function(e){return e.paging.totalPages})))},t.prototype.isLegacyEntry=function(e){return Boolean(e.url)},t.prototype.listAllVersions=function(e,t){if(void 0===t&&(t={}),this.isLegacyEntry(e))return this.getBaseVersionResultListForLegacyEntry(e);return this.listChildren(e,{__filter:{},__orderby:[{"creationTime.date":-1},{creationTime:-1}]},t)},t.prototype.listBaseVersions=function(e,t){if(void 0===t&&(t={}),this.isLegacyEntry(e))return this.getBaseVersionResultListForLegacyEntry(e);return this.listChildren(e,{__filter:{__not:{__has:"c8y_Patch"}},__orderby:[{"creationTime.date":-1},{creationTime:-1}]},t)},t.prototype.listPatchVersions=function(e,t,n){void 0===n&&(n={});var i={__filter:{"c8y_Patch.dependency":l.isString(t)?t:l.get(t,"c8y_Firmware.version")},__orderby:[{"creationTime.date":-1},{creationTime:-1}]};return this.listChildren(e,i,n)},t.prototype.listBaseVersionAndPatches=function(e,t,n){if(void 0===n&&(n={}),this.isLegacyEntry(e))return Promise.resolve({data:[Object.assign({c8y_Firmware:{version:e.version,url:e.url}},e)]});var i={__filter:{__or:{"c8y_Patch.dependency":t.c8y_Firmware.version,"c8y_Firmware.version":t.c8y_Firmware.version}},__orderby:[{"c8y_Patch.dependency":1},{"c8y_Firmware.version":1}]};return this.listChildren(e,i,n)},t.prototype.listChildren=function(e,t,n){void 0===t&&(t={}),void 0===n&&(n={});var i={__bygroupid:e.id},r=this.queriesUtil.addAndFilter(t,i);return n.withTotalPages=!0,this.inventory.listQuery(r,n)},t.prototype.fetchAllItemsFromList=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a;return S(this,(function(o){switch(o.label){case 0:return e.then?[3,1]:(t=I(e),[3,5]);case 1:return[4,e];case 2:n=o.sent(),i=n.paging,r=n.data,t=I(r),o.label=3;case 3:return i&&i.nextPage?[4,i.next()]:[3,5];case 4:return a=o.sent(),i=a.paging,r=a.data,t=I(t,r),[3,3];case 5:return[2,t]}}))}))},t.prototype.getRepositoryEntryMO$=function(e){if(!e)return p.of(void 0);var t=C(l.get(e,"additionParents.references"),1)[0],n=l.get(t,"managedObject.id");return n?p.from(this.inventory.detail(n,{withChildren:!1})).pipe(d.map((function(e){return e.data}))):p.of(void 0)},t.prototype.getRepositoryBinaryMoByVersion=function(e,t,n){var i,r,a=void 0===n?{}:n,o=a.skipLegacy,s=void 0!==o&&o,c=a.filters,p=void 0===c?{}:c,d=e.version,u=e.url,y=e.name,f=T[t],h=((i={})[t+".version"]=d,i[t+".url"]=u,i.type=f,i),g={url:u,type:t,name:y};return p=Object.assign({withChildren:!1,withParents:!0},p),r=s?{__and:Object.assign({},h)}:{__or:[{__and:Object.assign({},h)},{__and:Object.assign({},g)}]},this.inventory.listQuery(r,p).then((function(e){var t=e.data;return l.head(t)}))},t.prototype.getBinaryName$=function(e){var t=this;if(!e)return p.of("---");var n=this.inventoryBinary.getIdFromUrl(e);return n?p.defer((function(){return t.inventory.detail(n).then((function(e){return e.data}))})).pipe(d.map((function(e){return e.name}))):p.of(e)},t.prototype.getDeviceTypeQuery=function(t,n){var i={type:t};return t===e.RepositoryType.CONFIGURATION?n.type&&(i=this.queriesUtil.addAndFilter(i,{__or:[{deviceType:n.type},{__not:{__has:"deviceType"}}]})):i=this.queriesUtil.addAndFilter(i,{__or:[{"c8y_Filter.type":n.type},{"c8y_Filter.type":""},{__not:{__has:"c8y_Filter.type"}}]}),i},t.prototype.getConfigurationTypeQuery=function(t,n){var i=this.getDeviceTypeQuery(e.RepositoryType.CONFIGURATION,t);return this.queriesUtil.addAndFilter(i,{__or:[{configurationType:n},{configurationType:""},{__not:{__has:"configurationType"}}]})},t.prototype.getDeviceSoftwareList=function(e){return e.c8y_SoftwareList?l.cloneDeep(e.c8y_SoftwareList):e.c8y_Software?l.map(e.c8y_Software,(function(e,t){return{name:t,version:e}})):[]},t.prototype.createSoftwareUpdateOperation=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n=this.getSoftwareUpdateOperation(e,t),[4,this.operation.create(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getSoftwareUpdateOperation=function(e,t){var n={deviceId:e.id,description:"Apply software changes: "+t.map((function(e){return e.action+' "'+e.name+'"'+(e.version?" (version: "+e.version+")":"")})).join(", ")};return e.c8y_SupportedOperations.includes("c8y_SoftwareUpdate")?n.c8y_SoftwareUpdate=l.cloneDeep(t):e.c8y_SupportedOperations.includes("c8y_SoftwareList")?(n.c8y_SoftwareList=l.cloneDeep(e.c8y_SoftwareList)||[],t.forEach((function(e){var t=l.pick(e,["name","version","url"]);"delete"===e.action&&l.remove(n.c8y_SoftwareList,t),"install"===e.action&&n.c8y_SoftwareList.push(t)}))):e.c8y_SupportedOperations.includes("c8y_Software")&&(n.c8y_Software=l.cloneDeep(e.c8y_Software)||{},t.forEach((function(e){"delete"===e.action&&delete n.c8y_Software[e.name],"install"===e.action&&(n.c8y_Software[e.name]=e.version)}))),n},t.prototype.getDeviceSoftwareChangesFromOperation=function(e,t){return e.c8y_SoftwareUpdate?l.cloneDeep(e.c8y_SoftwareUpdate):e.c8y_SoftwareList?this.getDeviceSoftwareChangesFromSoftwareListOperation(e,t):e.c8y_Software?this.getDeviceSoftwareChangesFromSoftwareOperation(e,t):[]},t.prototype.createFirmwareUpdateOperation=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n=this.getFirmwareUpdateOperation(e,t),[4,this.operation.create(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getFirmwareUpdateOperation=function(e,t){return delete t.id,{deviceId:e.id,description:'Update firmware to: "'+t.name+'"'+(t.version?" (version: "+t.version+")":""),c8y_Firmware:Object.assign({},t)}},t.prototype.getUploadConfigurationFileOperation=function(e,t,n){return void 0===n&&(n=!1),n?{deviceId:e.id,description:"Retrieve configuration snapshot from device "+e.name,c8y_UploadConfigFile:{}}:{deviceId:e.id,description:"Retrieve "+t+" configuration snapshot from device "+e.name,c8y_UploadConfigFile:{type:t}}},t.prototype.getDownloadConfigurationFileOperation=function(e,t,n,i){return void 0===i&&(i=!1),i?{deviceId:e.id,description:"Send configuration snapshot "+n.name+" to device "+e.name,c8y_DownloadConfigFile:{url:n.binaryUrl,c8y_ConfigurationDump:{id:n.id}}}:{deviceId:e.id,description:"Send configuration snapshot "+n.name+" of configuration type "+t+" to device "+e.name,c8y_DownloadConfigFile:{url:n.binaryUrl,type:t}}},t.prototype.getLastFirmwareUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_Firmware"})])]}))}))},t.prototype.getLastSoftwareUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_SoftwareUpdate"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_SoftwareList"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_Software"})])]}))}))},t.prototype.getFirstMatchingOperation=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:t=null,l.label=1;case 1:l.trys.push([1,6,7,8]),n=x(e),i=n.next(),l.label=2;case 2:return i.done?[3,5]:(r=i.value,[4,this.operation.list(r)]);case 3:if((a=l.sent().data).length)return t=a[0],[3,5];l.label=4;case 4:return i=n.next(),[3,2];case 5:return[3,8];case 6:return o=l.sent(),s={error:o},[3,8];case 7:try{i&&!i.done&&(c=n.return)&&c.call(n)}finally{if(s)throw s.error}return[7];case 8:return[2,t]}}))}))},t.prototype.createObservedOperation=function(e){var t=this;return p.from(this.operation.create(e)).pipe(d.map((function(e){return e.data})),d.take(1),d.switchMap((function(e){return t.observeOperation(e)})))},t.prototype.observeOperation=function(e){var t=this,n=p.of(e),i=n.pipe(d.switchMap((function(e){return t.operationRealtime.onAll$(e.deviceId)})),d.map((function(e){return e.data})),d.withLatestFrom(n),d.filter((function(e){var t=C(e,2),n=t[0],i=t[1];return n.id===i.id})),d.switchMap((function(e){var t=C(e,1)[0];return t.status===c.OperationStatus.FAILED?p.throwError(t):p.of(t)})),d.takeWhile((function(e){return e.status!==c.OperationStatus.SUCCESSFUL}),!0));return p.merge(n,i)},t.prototype.getLatestConfigurationEvent=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n={source:e,type:t,dateFrom:this.dateFrom.toISOString(),dateTo:this.dateTo.toISOString(),pageSize:1},[4,this.event.list(n)];case 1:return[2,i.sent().data[0]]}}))}))},t.prototype.getConfigFileOperationList=function(e,t){return w(this,void 0,void 0,(function(){var n;return S(this,(function(i){switch(i.label){case 0:return n={deviceId:e,fragmentType:t,dateFrom:this.dateFrom.toISOString(),dateTo:this.dateTo.toISOString(),revert:!0,pageSize:2e3},[4,this.operation.list(n)];case 1:return[2,i.sent().data]}}))}))},t.prototype.getConfigSnapshot=function(e,t){return w(this,void 0,void 0,(function(){var i,r,a,o;return S(this,(function(s){switch(s.label){case 0:return[4,this.getLatestConfigurationEvent(e.id,t)];case 1:if(!(i=s.sent()))return[3,6];r={time:i.time,name:i.text,deviceType:e.type,configurationType:t},s.label=2;case 2:return s.trys.push([2,5,,6]),a=r,[4,this.eventBinary.download(i)];case 3:return[4,s.sent().text()];case 4:return a.binary=s.sent(),i.c8y_IsBinary&&(r.binaryType=i.c8y_IsBinary.type),[3,6];case 5:return s.sent(),o=n.gettext("Could not get the binary."),this.alert.danger(o),[3,6];case 6:return[2,r]}}))}))},t.prototype.getLegacyConfigSnapshot=function(e){return w(this,void 0,void 0,(function(){var t,n,i,r,a;return S(this,(function(o){switch(o.label){case 0:return[4,this.inventory.detail(e,{withChildren:!1})];case 1:if(i=o.sent().data,!(r=i.c8y_ConfigurationDump&&i.c8y_ConfigurationDump.id))return[2];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,this.inventory.detail(r)];case 3:return n=o.sent().data,[3,5];case 4:return o.sent(),[3,5];case 5:return n?(t={time:n.creationTime,name:n.name},a=t,[4,this.getBinaryText(n.url,{allowExternal:!1})]):[3,7];case 6:a.binary=o.sent(),o.label=7;case 7:return[2,t]}}))}))},t.prototype.getBinaryText=function(e,t){return w(this,void 0,void 0,(function(){var n,i;return S(this,(function(r){switch(r.label){case 0:return(n=this.inventoryBinary.getIdFromUrl(e))||!t.allowExternal?[3,2]:[4,this.getExternalBinaryResponse(e,t)];case 1:return i=r.sent(),[3,4];case 2:return[4,this.getInternalBinaryResponse(n,t)];case 3:i=r.sent(),r.label=4;case 4:return i?[2,i.text()]:[2,null]}}))}))},t.prototype.getBinaryFile=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r,a,o,s;return S(this,(function(c){switch(c.label){case 0:return(n=this.inventoryBinary.getIdFromUrl(e))||t.allowExternal?[4,this.inventory.detail(n)]:[2,null];case 1:return i=c.sent().data,r=i.name,a=i.contentType,n?[4,this.getInternalBinaryResponse(n)]:[3,3];case 2:return o=c.sent(),[3,5];case 3:return[4,this.getExternalBinaryResponse(e)];case 4:o=c.sent(),c.label=5;case 5:return[4,o.arrayBuffer()];case 6:return s=c.sent(),[2,new File([s],r,{type:a})]}}))}))},t.prototype.getLastConfigUpdateOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){return t={deviceId:e,dateFrom:new Date(0).toISOString(),dateTo:new Date(Date.now()).toISOString(),revert:!0,pageSize:1},[2,this.getFirstMatchingOperation([Object.assign(Object.assign({},t),{fragmentType:"c8y_Configuration"}),Object.assign(Object.assign({},t),{fragmentType:"c8y_SendConfiguration"})])]}))}))},t.prototype.createTextBasedConfigurationReloadOperation=function(e){return{deviceId:e.id,description:n.gettext("Requested current configuration"),c8y_SendConfiguration:{}}},t.prototype.createTextBasedConfigurationUpdateOperation=function(e,t){return{deviceId:e.id,description:n.gettext("Configuration update"),c8y_Configuration:{config:t}}},t.prototype.getBinary=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(i){switch(i.label){case 0:return i.trys.push([0,2,,3]),[4,this.inventoryBinary.download(e)];case 1:return[2,i.sent()];case 2:return i.sent(),t=n.gettext("Could not get the binary."),this.alert.danger(t),[3,3];case 3:return[2]}}))}))},t.prototype.getSnapshotsFromRepository=function(t,n){return w(this,void 0,void 0,(function(){var i;return S(this,(function(r){switch(r.label){case 0:return i=this.getConfigurationTypeQuery(t,n),[4,this.listRepositoryEntries(e.RepositoryType.CONFIGURATION,{query:i,params:{pageSize:100}})];case 1:return[2,r.sent().data]}}))}))},t.prototype.getInternalBinaryResponse=function(e,t){return void 0===t&&(t={}),w(this,void 0,void 0,(function(){var i,r;return S(this,(function(a){switch(a.label){case 0:return a.trys.push([0,2,,3]),[4,this.inventoryBinary.download(e)];case 1:return i=a.sent(),[3,3];case 2:return a.sent(),t.noAlerts||(r=n.gettext("Could not get the binary."),this.alert.danger(r)),[3,3];case 3:return[2,i]}}))}))},t.prototype.getExternalBinaryResponse=function(e,t){return void 0===t&&(t={}),w(this,void 0,void 0,(function(){var i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,2,,3]),[4,fetch(e)];case 1:if((r=o.sent()).status>=400)throw i;return i=r,[3,3];case 2:return o.sent(),t.noAlerts||(a=n.gettext("Could not get the external binary"),this.alert.danger(a)),[3,3];case 3:return[2,i]}}))}))},t.prototype.createEntry=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return[4,this.inventoryBinary.getIdFromUrl(e.url)];case 1:return t=i.sent(),[4,this.inventory.create(e)];case 2:return n=i.sent(),t?[4,this.inventory.childAdditionsAdd(t,n.data)]:[3,4];case 3:i.sent(),i.label=4;case 4:return[2,n]}}))}))},t.prototype.updateEntry=function(e,t){return w(this,void 0,void 0,(function(){var n,i,r;return S(this,(function(a){switch(a.label){case 0:return[4,this.inventoryBinary.getIdFromUrl(t)];case 1:return n=a.sent(),[4,this.inventoryBinary.getIdFromUrl(e.url)];case 2:return i=a.sent(),n&&n!==i?(r=this.inventoryBinary.getIdFromUrl(t),[4,this.inventoryBinary.delete(r)]):[3,4];case 3:a.sent(),a.label=4;case 4:return i?[4,this.inventory.childAdditionsAdd(i,e)]:[3,6];case 5:a.sent(),a.label=6;case 6:return[2,this.inventory.update(e)]}}))}))},t.prototype.getBaseVersionResultListForLegacyEntry=function(e){var t;return Promise.resolve({res:{},data:[Object.assign(Object.assign({},e),(t={},t[e.type]={version:e.version,url:e.url},t))]})},t.prototype.getDeviceSoftwareChangesFromSoftwareListOperation=function(e,t){var n=[];return l.forEach(t.c8y_SoftwareList,(function(t){var i=l.find(e.c8y_SoftwareList,{name:t.name});(i&&i.version)!==(t&&t.version)&&n.push(Object.assign(Object.assign({},t),{action:"delete"}))})),l.forEach(e.c8y_SoftwareList,(function(e){var i=l.find(t.c8y_SoftwareList,{name:e.name});(e&&e.version)!==(i&&i.version)&&n.push(Object.assign(Object.assign({},e),{action:"install"}))})),n},t.prototype.getDeviceSoftwareChangesFromSoftwareOperation=function(e,t){var n=[];return l.forEach(t.c8y_Software,(function(t,i){e.c8y_Software[i]!==t&&n.push({name:i,version:t,action:"delete"})})),l.forEach(e.c8y_Software,(function(e,i){(t.c8y_Software&&t.c8y_Software[i])!==e&&n.push({name:i,version:e,action:"install"})})),n},t}();O.decorators=[{type:t.Injectable}],O.ctorParameters=function(){return[{type:c.InventoryService},{type:c.InventoryBinaryService},{type:c.OperationService},{type:n.AlertService},{type:c.EventService},{type:n.OperationRealtimeService},{type:c.EventBinaryService}]};var $=function(){function i(e,i,r){this.modal=e,this.repositoryService=i,this.alert=r,this.saved=new t.EventEmitter,this.onInput=new p.BehaviorSubject(""),this.model={selected:void 0,version:void 0,description:void 0,deviceType:void 0,binary:{file:void 0,url:void 0}},this.saving=!1,this.firmwarePreselected=!1,this.textForFirmwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /firmware/binaries/firmware1.bin\n https://firmware/binary/123\n ftp://firmware/binary/123.tar.gz\n ")}return i.prototype.ngOnInit=function(){this.setInitialState(),this.loadFirmwares()},i.prototype.setInitialState=function(){this.model.selected&&(this.firmwarePreselected=!0)},i.prototype.loadFirmwares=function(){var e=this;this.inputSubscription$=this.onInput.pipe(d.tap((function(){e.firmwarePreselected||(e.model.description=null,e.form&&e.form.form.get("description").reset())})),d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return e.getFirmwareResult(t)}))).subscribe((function(t){e.firmwaresResult=t}))},i.prototype.getFirmwareResult=function(t){return p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialName:t,skipLegacy:!0}))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repositoryService.create(this.model,e.RepositoryType.FIRMWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Firmware added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.ngOnDestroy=function(){this.inputSubscription$.unsubscribe()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i.prototype.onFirmwareSelect=function(e){l.assign(this.model,{selected:e,description:e.description,deviceType:l.get(e,"c8y_Filter.type")})},i}();$.decorators=[{type:t.Component,args:[{selector:"c8y-add-firmware-software-modal",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-firmware\'"></i>\n <h4 translate>\n Add firmware\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom" *ngIf="!firmwarePreselected">\n <p class="lead m-0" translate>\n Select or create new firmware\n </p>\n </div>\n <form\n class="d-contents"\n autocomplete="off"\n #firmwareForm="ngForm"\n (ngSubmit)="firmwareForm.form.valid && save()"\n >\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="firmwarePreselected">\n <c8y-form-group>\n <label for="firmwareName" translate>Firmware</label>\n <c8y-typeahead\n [(ngModel)]="model.selected"\n name="firmwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="onInput.next($event)"\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let firmware of firmwaresResult;\n loadMore: \'auto\';\n notFound: notFoundTemplate\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="onFirmwareSelect(firmware)"\n [active]="model.selected === firmware"\n >\n <c8y-highlight\n [text]="firmware.name || \'--\'"\n [pattern]="onInput | async"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="(onInput | async)?.length > 0">\n <span translate>No match found, add new`firmware`? </span>\n <button\n title="{{ \'Create new`firmware`\' | translate }}"\n type="button"\n class="btn btn-primary btn-xs m-l-16"\n translate\n >\n Create new`firmware`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="firmwareDescription" translate>Description</label>\n <input\n id="firmwareDescription"\n class="form-control"\n autocomplete="off"\n name="description"\n [(ngModel)]="model.description"\n placeholder="{{ \'e.g. Firmware for hardware revision b\' | translate }}"\n [disabled]="model.selected?.id"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label class="control-label" for="firmwareDeviceTypeFilter">\n {{ \'Device type filter\' | translate }}\n <button\n class="btn btn-clean text-primary"\n popover="{{\n \'If the filter is set, the firmware will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\'\n | translate\n }}"\n triggers="focus"\n container="body"\n placement="right"\n >\n <i [c8yIcon]="\'question-circle-o\'"></i>\n </button>\n </label>\n <input\n id="firmwareDeviceTypeFilter"\n class="form-control"\n name="firmwareDeviceTypeFilter"\n [(ngModel)]="model.deviceType"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [disabled]="model.selected?.id"\n />\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="firmwareVersion" translate>Version</label>\n <input\n id="firmwareVersion"\n class="form-control"\n autocomplete="off"\n name="version"\n [(ngModel)]="model.version"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Firmware file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForFirmwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n\n <button\n title="{{ \'Add firmware\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !firmwareForm.form.valid ||\n firmwareForm.form.pristine ||\n saving ||\n (!model.binary?.url && !model.binary?.file)\n "\n translate\n >\n Add firmware\n </button>\n </div>\n </form>\n</div>\n'}]}],$.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},$.propDecorators={form:[{type:t.ViewChild,args:["firmwareForm",{static:!1}]}],saved:[{type:t.Output}]};var E=function(){function i(i,r,a){var o=this;this.modal=i,this.repository=r,this.alert=a,this.saved=new t.EventEmitter,this.textForFirmwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /firmware/binaries/firmware1.bin\n https://firmware/binary/123\n ftp://firmware/binary/123.tar.gz\n "),this.model={selected:void 0,dependency:null,patchVersion:void 0,binary:{file:void 0,url:void 0}},this.firmwareInput$=new p.BehaviorSubject(""),this.firmwares$=this.firmwareInput$.pipe(d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return p.from(o.repository.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialName:t,skipLegacy:!0}))})),d.shareReplay(1)),this.firmwareSelected$=new p.BehaviorSubject(null),this.patchDependencyInput$=new p.BehaviorSubject(""),this.saving=!1,this.firmwarePreselected=!1,this.baseVersions$=p.merge(this.firmwareInput$.pipe(d.tap((function(){o.model.dependency=null,o.form&&o.form.form.get("patchDependency").reset()})),d.switchMap((function(){return p.of(null)}))),this.firmwareSelected$).pipe(d.switchMap((function(e){return e?o.repository.listBaseVersions(e):p.of(null)})),d.shareReplay(1)),this.baseVersionsFilterPipe=p.pipe(d.switchMap((function(e){return o.patchDependencyInput$.pipe(d.map((function(t){return e.filter((function(e){var n=e.c8y_Firmware.version.toLowerCase();return 0===t.length||n.indexOf(t.toLowerCase())>-1}))})))})))}return i.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){return this.setInitialState(),[2]}))}))},i.prototype.setInitialState=function(){this.model.selected&&(this.firmwarePreselected=!0,this.firmwareSelected$.next(this.model.selected))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repository.create(this.model,e.RepositoryType.FIRMWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Firmware patch added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i}();E.decorators=[{type:t.Component,args:[{selector:"c8y-add-firmware-patch-modal.component",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-firmware\'"></i>\n <h4 translate>\n Add firmware patch\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom">\n <p class="lead m-0" translate>\n Select a firmware version\n </p>\n </div>\n\n <form\n class="d-contents"\n autocomplete="off"\n #firmwarePatchForm="ngForm"\n (ngSubmit)="firmwarePatchForm.form.valid && save()">\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="firmwarePreselected">\n <c8y-form-group>\n <label for="firmwareName" translate>Firmware</label>\n <c8y-typeahead\n [ngModel]="model.selected"\n name="firmwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="firmwareInput$.next($event)"\n [allowFreeEntries]="false"\n [required]="true"\n >\n <c8y-li\n *c8yFor="let firmware of firmwares$ | async; loadMore: \'auto\'"\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="model.selected = firmware; firmwareSelected$.next(firmware)"\n [active]="model.selected === firmware"\n >\n <c8y-highlight\n [text]="firmware.name || \'--\'"\n [pattern]="firmwareInput$ | async"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages\n ><c8y-message\n name="notExisting"\n [text]="\'Select one of the existing firmwares.\' | translate"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="patchDependency" class="m-r-8" translate>Version</label>\n <c8y-typeahead\n [ngModel]="model.dependency"\n name="patchDependency"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="patchDependencyInput$.next($event)"\n [displayProperty]="\'c8y_Firmware.version\'"\n [allowFreeEntries]="false"\n [disabled]="\n (baseVersions$ | async) === null || (baseVersions$ | async)?.data.length === 0\n "\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let baseVersion of baseVersions$;\n loadMore: \'auto\';\n pipe: baseVersionsFilterPipe\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="model.dependency = baseVersion"\n [active]="model.dependency === baseVersion"\n >\n <c8y-highlight\n [text]="baseVersion.c8y_Firmware.version || \'--\'"\n [pattern]="patchDependencyInput$ | async"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages\n ><c8y-message\n name="notExisting"\n [text]="\'Select one of the existing versions.\' | translate"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="patchVersion" translate>Patch</label>\n <input\n id="patchVersion"\n class="form-control"\n autocomplete="off"\n name="patchVersion"\n [(ngModel)]="model.patchVersion"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n required\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Patch file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForFirmwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n <button\n title="{{ \'Add firmware patch\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !firmwarePatchForm.form.valid ||\n firmwarePatchForm.form.pristine ||\n (!model.binary?.url && !model.binary?.file) ||\n saving\n "\n translate\n >\n Add firmware patch\n </button>\n </div>\n </form>\n</div>\n'}]}],E.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},E.propDecorators={saved:[{type:t.Output}],dropdown:[{type:t.ViewChild,args:["dropdown",{static:!1}]}],form:[{type:t.ViewChild,args:["firmwarePatchForm",{static:!1}]}]};var R=function(){function t(t,i,r,a,o,s,c){var l=this;this.repositoryService=t,this.modalService=i,this.bsModalService=r,this.translateService=a,this.alertService=o,this.router=s,this.activatedRoute=c,this.textFilter$=new p.BehaviorSubject(""),this.reload$=new p.BehaviorSubject(null),this.reloading=!1,this.firmwares$=p.combineLatest(this.textFilter$.pipe(d.debounceTime(400),d.distinctUntilChanged()),this.reload$).pipe(d.tap((function(){l.reloading=!0})),d.switchMap((function(e){var t=C(e,1)[0];return l.getFirmwares(t)})),d.tap((function(){l.reloading=!1})),d.shareReplay(1)),this.canAddFirmwarePatch$=p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{skipLegacy:!0})).pipe(d.map((function(e){return e.data.length>0}))),this.isLegacy=this.repositoryService.isLegacyEntry.bind(this.repositoryService),this.DEVICE_TYPE_NOT_AVAILABLE=n.gettext("No device type available")}return t.prototype.getFirmwares=function(t){var n={partialText:t,properties:["name","description","c8y_Filter.type"]};return this.repositoryService.listRepositoryEntries(e.RepositoryType.FIRMWARE,{partialTextFilter:n})},t.prototype.addFirmware=function(){var e=this;this.bsModalService.show($,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editFirmware(t)}))},t.prototype.addFirmwarePatch=function(){var e=this;this.bsModalService.show(E,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editFirmware(t)}))},t.prototype.editFirmware=function(e){this.router.navigate([e.id],{relativeTo:this.activatedRoute})},t.prototype.deleteFirmware=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware"),i="\n "+this.translateService.instant(n.gettext('You are about to delete firmware "{{ name }}" with all its versions and patches.'),{name:e.name})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware deleted.")),this.reload$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},t.prototype.getBaseVersionsCount$=function(e){var t=this;return this.firmwares$.pipe(d.switchMap((function(){return t.repositoryService.getBaseVersionsCount$(e)})),d.shareReplay(1))},t.prototype.getDeviceTypeTitle=function(e){return l.get(e,"c8y_Filter.type",this.translateService.instant(this.DEVICE_TYPE_NOT_AVAILABLE))},t}();R.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-list",template:'<c8y-title>\n {{ \'Firmware repository\' | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]="\'left\'" itemClass="navbar-form">\n <div class="input-group input-group-search">\n <input class="form-control"\n type="search"\n title="{{ \'Filter firmware…\' | translate }}"\n placeholder="{{ \'Filter firmware…\' | translate }}"\n [ngModel]="textFilter$ | async"\n (ngModelChange)="textFilter$.next($event)"\n />\n <span class="input-group-addon">\n <i\n c8yIcon="search"\n *ngIf="(textFilter$ | async).length === 0"\n ></i>\n <i class="text-muted"\n c8yIcon="times"\n *ngIf="(textFilter$ | async).length > 0"\n (click)="textFilter$.next(\'\')"\n ></i>\n </span>\n </div>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" \n title="{{ \'Add firmware\' | translate }}"\n (click)="addFirmware()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n *ngIf="canAddFirmwarePatch$ | async"\n title="{{ \'Add firmware patch\' | translate }}"\n (click)="addFirmwarePatch()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware patch\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n title="{{ \'Reload\' | translate }}"\n (click)="reload$.next()"\n >\n <i c8yIcon="refresh"\n [ngClass]="{ \'icon-spin\': reloading }"\n ></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state--\x3e\n<div class="c8y-empty-state text-center"\n *ngIf="(firmwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length === 0"\n>\n <h1 class="c8y-icon-duocolor"\n c8yIcon="c8y-firmware"\n ></h1>\n <h3 translate>\n No firmwares to display.\n </h3>\n <p translate>\n Add a new firmware by clicking below.\n </p>\n <p>\n <button class="btn btn-primary"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addFirmware()"\n translate\n >\n Add firmware\n </button>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div class="c8y-empty-state"\n *ngIf="(firmwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length > 0"\n >\n <h1 class="c8y-icon-duocolor"\n c8yIcon="search"></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n<c8y-list-group class="m-b-24"\n *ngIf="(firmwares$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': (firmwares$ | async)?.data.length < 10 }"\n \n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs">\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-3">\n {{\'Firmware\' | translate}}\n </div>\n <div class="col-4">\n {{\'Description\' | translate}}\n </div>\n <div class="col-3">\n {{\'Device type\' | translate}}\n </div>\n <div class="col-2">\n {{\'Versions\' | translate}}\n </div>\n </c8y-li-body>\n </c8y-li>\n\n <c8y-li *c8yFor="let firmware of firmwares$ | async; let i = index; loadMore: \'auto\'">\n <c8y-li-icon icon="c8y-firmware"></c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <button class="btn-clean col-3"\n (click)="editFirmware(firmware)"\n >\n <span class="text-truncate"\n title="{{ firmware.name }}"\n >\n {{ firmware.name }}\n </span>\n </button>\n <div class="col-4">\n <p class="text-truncate"\n title="{{ firmware.description }}"\n >\n <span class="text-label-small m-r-4 visible-xs-inline">\n {{\'Description\' | translate }}\n </span>\n <span *ngIf="firmware.description; else emptyDescription">\n {{ firmware.description }}\n </span>\n </p>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n <div class="col-3">\n <div class="text-truncate">\n <span class="text-label-small m-r-4 visible-xs-inline" translate>\n Device type\n </span>\n <span\n *ngIf="firmware.c8y_Filter?.type; else emptyText"\n title="{{ firmware.c8y_Filter?.type }}"\n >\n {{ firmware.c8y_Filter?.type }}\n </span>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n </div>\n <div class="col-2">\n <span class="label label-warning flex-item-right-sm"\n *ngIf="isLegacy(firmware)"\n >\n <span translate>\n Legacy\n </span>\n </span>\n\n <span *ngIf="!isLegacy(firmware)">\n <span *ngIf="(getBaseVersionsCount$(firmware) | async) === null">\n <span class="label label-info flex-item-right-sm">\n <i c8yIcon="circle-o-notch" class="icon-spin"></i>\n </span>\n </span>\n <span *ngIf="(getBaseVersionsCount$(firmware) | async) !== null">\n <span [ngPlural]="getBaseVersionsCount$(firmware) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>\n No versions\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info flex-item-right-sm">\n <span translate>\n 1 version\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info flex-item-right-sm">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getBaseVersionsCount$(firmware) | async }"\n >\n {{ count }} versions\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n\n <c8y-li-action\n (click)="editFirmware(firmware)"\n icon="pencil"\n >\n {{ \'Edit\' | translate }}\n </c8y-li-action>\n\n <c8y-li-action\n (click)="deleteFirmware(firmware)"\n icon="trash"\n >\n {{ \'Delete\' | translate }}\n </c8y-li-action>\n </c8y-li>\n</c8y-list-group>\n'}]}],R.ctorParameters=function(){return[{type:O},{type:n.ModalService},{type:y.BsModalService},{type:f.TranslateService},{type:n.AlertService},{type:u.Router},{type:u.ActivatedRoute}]},b([n.memoize(l.property("id"))],R.prototype,"getBaseVersionsCount$",null);var _=function(){function e(e,t,n,i,r,a,o){var s=this;this.activatedRoute=e,this.inventoryService=t,this.repositoryService=n,this.alertService=i,this.translateService=r,this.modalService=a,this.bsModalService=o,this.reload$=new p.Subject,this.reloading$=new p.BehaviorSubject(!1),this.updateFirmware$=new p.Subject,this.firmwareUpdated$=new p.Subject,this.baseVersionsUpdated$=new p.Subject,this.patchVersionsUpdated$=new p.Subject,this.firmware$=p.merge(this.activatedRoute.params.pipe(d.map((function(e){return e.id})),d.switchMap((function(e){return p.defer((function(){return s.inventoryService.detail(e).then((function(e){return e.data}))}))}))),this.reload$.pipe(d.tap((function(){return s.reloading$.next(!0)})),d.switchMap((function(){return s.activatedRoute.params})),d.map((function(e){return e.id})),d.switchMap((function(e){return p.defer((function(){return s.inventoryService.detail(e).then((function(e){return e.data}))}))})),d.tap((function(){return s.reloading$.next(!1)}))),this.firmwareUpdated$).pipe(d.shareReplay(1)),this.baseVersions$=p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return s.firmware$})),d.switchMap((function(e){return s.repositoryService.listBaseVersions(e)})),d.shareReplay(1)),this.isLegacy$=this.firmware$.pipe(d.map((function(e){return s.repositoryService.isLegacyEntry(e)})),d.shareReplay(1)),this.canAddPatchVersions$=p.combineLatest(this.isLegacy$,this.baseVersions$.pipe(d.map((function(e){return e.data.length>0})))).pipe(d.map((function(e){var t=C(e,2),n=t[0],i=t[1];return!n&&i}))),this.expanded={},this.destroy$=new p.Subject}return e.prototype.ngOnInit=function(){var e=this;this.updateFirmware$.pipe(d.withLatestFrom(this.firmware$),d.switchMap((function(t){var n=C(t,2),i=n[0],r=n[1];return e.inventoryService.update(Object.assign({id:r.id},i))})),d.map((function(e){return e.data})),d.tap((function(t){return e.firmwareUpdated$.next(t)})),d.tap((function(){return e.alertService.success(n.gettext("Saved."))})),d.takeUntil(this.destroy$)).subscribe()},e.prototype.getPatchVersionsCount$=function(e){var t=this;return p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return t.firmware$})),d.switchMap((function(n){return t.repositoryService.getPatchVersionsCount$(n,e)})),d.shareReplay(1))},e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.getPatchVersions$=function(e){var t=this;return p.merge(this.firmware$.pipe(d.distinctUntilKeyChanged("id")),this.patchVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return t.firmware$})),d.switchMap((function(n){return t.repositoryService.listPatchVersions(n,e)})),d.shareReplay(1))},e.prototype.addBaseVersion=function(){var e=this;this.firmware$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t,description:t.description}}};return e.bsModalService.show($,n).content.saved}))).subscribe((function(){return e.baseVersionsUpdated$.next()}))},e.prototype.addPatchVersion=function(){var e=this;this.firmware$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t}}};return e.bsModalService.show(E,n).content.saved}))).subscribe((function(){return e.patchVersionsUpdated$.next()}))},e.prototype.deleteBaseVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware"),i="\n "+this.translateService.instant(n.gettext("You are about to delete firmware {{ version }} with all its patches."),{version:e.c8y_Firmware.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware deleted.")),this.baseVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.deletePatchVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete firmware patch"),i="\n "+this.translateService.instant(n.gettext("You are about to delete firmware patch {{ version }}."),{version:e.c8y_Firmware.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Firmware patch deleted.")),this.patchVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.ngOnDestroy=function(){this.destroy$.next(!0),this.destroy$.unsubscribe()},e}();_.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-details",template:'<c8y-title>\n {{ (firmware$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n path="#/firmware"\n label="{{ \'Firmware repository\' | translate }}"\n icon="c8y-firmware"\n >\n </c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="!(isLegacy$ | async)"\n class="btn btn-link"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addBaseVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="canAddPatchVersions$ | async"\n class="btn btn-link"\n title="{{ \'Add firmware patch\' | translate }}"\n (click)="addPatchVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add firmware patch\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading$ | async }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card m-b-4">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Name, description and device type filter\n </h4>\n </div>\n <div class="card-block">\n <div class="row">\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Name\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #nameInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.name"\n #nameModel="ngModel"\n placeholder="{{ \'e.g. My firmware\' | translate }}"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.name?.length || 31 }"\n required\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateFirmware$.next({ name: nameInput.value }); nameModel.reset()"\n [disabled]="nameInput.value.length == 0"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Description\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #descriptionInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.description"\n #descriptionModel="ngModel"\n placeholder="{{ \'e.g. Firmware for hardware revision b\' | translate }}"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.description?.length || 31 }"\n\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateFirmware$.next({ description: descriptionInput.value }); descriptionModel.reset() "\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Device type filter\' | translate }}\n\n <button\n class="btn-clean"\n popover="{{ \'If the filter is set, the firmware will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\' | translate }}"\n [outsideClick]="true"\n container="body"\n >\n <i c8yIcon="question-circle-o" class="text-info"></i>\n </button>\n </label>\n <div class="input-group input-group-editable">\n <input\n #deviceTypeInput\n type="text"\n class="form-control"\n [ngModel]="(firmware$ | async)?.c8y_Filter?.type"\n #deviceTypeModel="ngModel"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [ngStyle]="{ \'width.ch\': (firmware$ | async)?.type?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateFirmware$.next({ c8y_Filter: { type: deviceTypeInput.value } }); deviceTypeModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Versions and patches\n </h4>\n </div>\n\n <div class="card-block p-t-0 p-b-24">\n <div *ngIf="(baseVersions$ | async)?.data.length === 0">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-firmware" class="c8y-icon-duocolor"></h1>\n <h3 translate>No versions to display.</h3>\n <p translate>Add a new version by clicking below.</p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add firmware\' | translate }}"\n (click)="addBaseVersion()"\n >\n {{ \'Add firmware\' | translate }}\n </button>\n </p>\n </div>\n </div>\n\n <c8y-list-group\n [ngClass]="{ \'dd-low\': (baseVersions$ | async)?.data.length < 10 }"\n *ngIf="(baseVersions$ | async)?.data.length > 0"\n >\n <c8y-li\n *c8yFor="let baseVersion of baseVersions$ | async; let i = index; loadMore: \'auto\'"\n [ngClass]="{ \'c8y-list__item--empty-actions\': !(getPatchVersions$(baseVersion) | async)?.data.length }"\n [collapsed]="!expanded[baseVersion.id]"\n (collapsedChange)="expanded[baseVersion.id] = !$event"\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n <p class="text-truncate-wrap" title="{{ baseVersion.c8y_Firmware.version }}">\n {{ baseVersion.c8y_Firmware.version }}\n </p>\n </div>\n <div class="col-5">\n <p class="text-truncate-wrap">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <span title="{{ getBinaryName$(baseVersion.c8y_Firmware.url) | async }}">\n <c8y-file-download url="{{ baseVersion.c8y_Firmware.url }}"></c8y-file-download>\n </span>\n </p>\n </div>\n <div class="col-2 flex-row a-i-start">\n <span *ngIf="isLegacy$ | async" class="label label-warning flex-item-right-sm">\n {{ \'Legacy\' | translate }}\n </span>\n\n <span *ngIf="!(isLegacy$ | async)">\n <span *ngIf="(getPatchVersionsCount$(baseVersion) | async) === null">\n <span class="label label-info">\n <i c8yIcon="circle-o-notch" class="icon-spin"></i>\n </span>\n </span>\n <span *ngIf="(getPatchVersionsCount$(baseVersion) | async) !== null">\n <span [ngPlural]="getPatchVersionsCount$(baseVersion) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>No patches</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info">\n <span translate>1 patch</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getPatchVersionsCount$(baseVersion) | async }"\n >\n {{ count }} patches\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n <div class="fit-h-20 visible-xs" *ngIf="!(isLegacy$ | async)">\n <button\n class="btn btn-danger btn-xs m-t-8 "\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n <div *ngIf="!(isLegacy$ | async)" class="flex-item-right fit-h-20 p-r-8 hidden-xs">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n <c8y-li-collapse *ngIf="(getPatchVersions$(baseVersion) | async)?.data.length">\n <c8y-list-group class="separator-top">\n <c8y-li\n *c8yFor=" let patchVersion of getPatchVersions$(baseVersion) | async; let i = index; loadMore: \'auto\' "\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n {{ patchVersion.c8y_Firmware.version }}\n </div>\n <div class="col-5">\n <div class="text-truncate">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <c8y-file-download\n url="{{ patchVersion.c8y_Firmware.url }}"\n ></c8y-file-download>\n </div>\n </div>\n <div class="visible-xs m-t-8">\n <button\n class="btn btn-danger btn-xs"\n (click)="deletePatchVersion(patchVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n <div class="flex-item-right p-r-8 hidden-xs fit-h-20">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deletePatchVersion(patchVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n</div>\n'}]}],_.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:c.InventoryService},{type:O},{type:n.AlertService},{type:f.TranslateService},{type:n.ModalService},{type:y.BsModalService}]},b([n.memoize(l.property("id"))],_.prototype,"getPatchVersionsCount$",null),b([n.memoize()],_.prototype,"getBinaryName$",null),b([n.memoize(l.property("id"))],_.prototype,"getPatchVersions$",null);var D=function(){function i(e,i,r){this.modal=e,this.repositoryService=i,this.alert=r,this.saved=new t.EventEmitter,this.onInput=new p.BehaviorSubject(""),this.model={selected:void 0,version:void 0,description:void 0,deviceType:void 0,binary:{file:void 0,url:void 0}},this.saving=!1,this.softwarePreselected=!1,this.textForSoftwareUrlPopover=n.gettext("Path for binaries can vary depending on device agent implementation, e.g.:\n /software/binaries/software1.bin\n https://software/binary/123\n ftp://software/binary/123.tar.gz\n ")}return i.prototype.ngOnInit=function(){this.setInitialState(),this.loadSoftwares()},i.prototype.setInitialState=function(){this.model.selected&&(this.softwarePreselected=!0)},i.prototype.loadSoftwares=function(){var e=this;this.inputSubscription$=this.onInput.pipe(d.tap((function(){e.softwarePreselected||(e.model.description=null,e.form&&e.form.form.get("description").reset())})),d.debounceTime(300),d.distinctUntilChanged(),d.switchMap((function(t){return e.getSoftwareResult(t)}))).subscribe((function(t){e.softwaresResult=t}))},i.prototype.getSoftwareResult=function(t){return p.from(this.repositoryService.listRepositoryEntries(e.RepositoryType.SOFTWARE,{partialName:t,skipLegacy:!0}))},i.prototype.save=function(){return w(this,void 0,void 0,(function(){var t=this;return S(this,(function(n){return this.saving=!0,this.repositoryService.create(this.model,e.RepositoryType.SOFTWARE).then((function(e){t.successMsg(),t.saving=!1,t.saved.next(e),t.cancel()})).catch((function(e){t.saving=!1,t.saved.error(e),t.cancel()})),[2]}))}))},i.prototype.successMsg=function(){var e=n.gettext("Software added.");this.alert.success(e)},i.prototype.cancel=function(){this.modal.hide(),this.saved.complete()},i.prototype.ngOnDestroy=function(){this.inputSubscription$.unsubscribe()},i.prototype.onFile=function(e){l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.model.binary={file:void 0,url:void 0}:this.model.binary={file:e.droppedFiles[0].file}:this.model.binary={url:e.url}},i.prototype.onSoftwareSelect=function(e){l.assign(this.model,{selected:e,description:e.description,deviceType:l.get(e,"c8y_Filter.type")})},i}();D.decorators=[{type:t.Component,args:[{selector:"c8y-add-software-software-modal",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'c8y-tools\'"></i>\n <h4 translate>\n Add software\n </h4>\n </div>\n <div class="p-16 text-center separator-bottom" *ngIf="!softwarePreselected">\n <p class="lead m-0" translate>\n Select or create new software\n </p>\n </div>\n <form\n class="d-contents"\n autocomplete="off"\n #softwareForm="ngForm"\n (ngSubmit)="softwareForm.form.valid && save()"\n >\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <div [hidden]="softwarePreselected">\n <c8y-form-group>\n <label for="softwareName" translate>Software</label>\n <c8y-typeahead\n [(ngModel)]="model.selected"\n name="softwareName"\n placeholder="{{ \'Select or enter\' | translate }}"\n (onSearch)="onInput.next($event)"\n [required]="true"\n >\n <c8y-li\n *c8yFor="\n let software of softwaresResult;\n loadMore: \'auto\';\n notFound: notFoundTemplate\n "\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="onSoftwareSelect(software)"\n [active]="model.selected === software"\n >\n <c8y-highlight\n [text]="software.name || \'--\'"\n [pattern]="onInput | async"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="(onInput | async)?.length > 0">\n <span translate>No match found, add new`software`? </span>\n <button\n title="{{ \'Create new`software`\' | translate }}"\n type="button"\n class="btn btn-primary btn-xs m-l-16"\n translate\n >\n Create new`software`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <label for="softwareDescription" translate>Description</label>\n <input\n id="softwareDescription"\n class="form-control"\n autocomplete="off"\n name="description"\n [(ngModel)]="model.description"\n placeholder="{{ \'e.g. Cloud connectivity software\' | translate }}"\n [disabled]="model.selected?.id"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label class="control-label" for="softwareDeviceTypeFilter">\n {{ \'Device type filter\' | translate }}\n <button\n class="btn btn-clean text-primary"\n popover="{{\n \'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\'\n | translate\n }}"\n triggers="focus"\n container="body"\n placement="right"\n >\n <i [c8yIcon]="\'question-circle-o\'"></i>\n </button>\n </label>\n <input\n id="softwareDeviceTypeFilter"\n class="form-control"\n name="softwareDeviceTypeFilter"\n [(ngModel)]="model.deviceType"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [disabled]="model.selected?.id"\n />\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label for="softwareVersion" translate>Version</label>\n <input\n id="softwareVersion"\n class="form-control"\n autocomplete="off"\n name="version"\n [(ngModel)]="model.version"\n placeholder="{{ \'e.g.\' | translate }} 1.0.0"\n [required]="true"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Software file</div>\n <c8y-file-picker [maxAllowedFiles]="1" (onFilesPicked)="onFile($event)" [fileUrlPopover]="textForSoftwareUrlPopover">\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n <div class="modal-footer">\n <button\n title="{{ \'Cancel\' | translate }}"\n class="btn btn-default"\n type="button"\n (click)="cancel()"\n [disabled]="saving"\n translate\n >\n Cancel\n </button>\n\n <button\n title="{{ \'Add software\' | translate }}"\n class="btn btn-primary"\n type="submit"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !softwareForm.form.valid ||\n softwareForm.form.pristine ||\n saving ||\n (!model.binary?.url && !model.binary?.file)\n "\n translate\n >\n Add software\n </button>\n </div>\n </form>\n</div>\n'}]}],D.ctorParameters=function(){return[{type:y.BsModalRef},{type:O},{type:n.AlertService}]},D.propDecorators={form:[{type:t.ViewChild,args:["softwareForm",{static:!1}]}],saved:[{type:t.Output}]};var A=function(){function t(e,t,i,r,a,o,s){var c=this;this.repositoryService=e,this.modalService=t,this.bsModalService=i,this.translateService=r,this.alertService=a,this.router=o,this.activatedRoute=s,this.textFilter$=new p.BehaviorSubject(""),this.reload$=new p.BehaviorSubject(null),this.reloading=!1,this.softwares$=p.combineLatest(this.textFilter$.pipe(d.debounceTime(400),d.distinctUntilChanged()),this.reload$).pipe(d.tap((function(){c.reloading=!0})),d.switchMap((function(e){var t=C(e,1)[0];return c.getSoftwares(t)})),d.tap((function(){c.reloading=!1})),d.shareReplay(1)),this.isLegacy=this.repositoryService.isLegacyEntry.bind(this.repositoryService),this.DEVICE_TYPE_NOT_AVAILABLE=n.gettext("No device type available")}return t.prototype.getSoftwares=function(t){var n={partialText:t,properties:["name","description","c8y_Filter.type"]};return this.repositoryService.listRepositoryEntries(e.RepositoryType.SOFTWARE,{partialTextFilter:n})},t.prototype.addSoftware=function(){var e=this;this.bsModalService.show(D,{class:"modal-sm",ignoreBackdropClick:!0}).content.saved.subscribe((function(t){return e.editSoftware(t)}))},t.prototype.editSoftware=function(e){this.router.navigate([e.id],{relativeTo:this.activatedRoute})},t.prototype.deleteSoftware=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete software"),i="\n "+this.translateService.instant(n.gettext('You are about to delete software "{{ name }}" with all its versions.'),{name:e.name})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Software deleted.")),this.reload$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},t.prototype.getBaseVersionsCount$=function(e){var t=this;return this.softwares$.pipe(d.switchMap((function(){return t.repositoryService.getBaseVersionsCount$(e)})),d.shareReplay(1))},t.prototype.getDeviceTypeTitle=function(e){return l.get(e,"c8y_Filter.type",this.translateService.instant(this.DEVICE_TYPE_NOT_AVAILABLE))},t}();A.decorators=[{type:t.Component,args:[{selector:"c8y-software-list",template:'<c8y-title>\n {{ \'Software repository\' | translate }}\n</c8y-title>\n\n<c8y-action-bar-item [placement]="\'left\'" itemClass="navbar-form">\n <div class="input-group input-group-search">\n <input\n class="form-control"\n type="search"\n title="{{ \'Filter software…\' | translate }}"\n placeholder="{{ \'Filter software…\' | translate }}"\n [ngModel]="textFilter$ | async"\n (ngModelChange)="textFilter$.next($event)"\n />\n <span class="input-group-addon">\n <i c8yIcon="search" *ngIf="(textFilter$ | async).length === 0"></i>\n <i\n class="text-muted"\n c8yIcon="times"\n *ngIf="(textFilter$ | async).length > 0"\n (click)="textFilter$.next(\'\')"\n ></i>\n </span>\n </div>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Add software\' | translate }}" (click)="addSoftware()">\n <i c8yIcon="plus-circle"></i>\n {{ \'Add software\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i [ngClass]="{ \'icon-spin\': reloading }" c8yIcon="refresh"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state--\x3e\n<div\n class="c8y-empty-state text-center"\n *ngIf="(softwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length === 0"\n>\n <h1 class="c8y-icon-duocolor" c8yIcon="c8y-tools"></h1>\n <h3 translate>\n No software to display.\n </h3>\n <p translate>\n Add a new software by clicking below.\n </p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add software\' | translate }}"\n (click)="addSoftware()"\n translate\n >\n Add software\n </button>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div\n class="c8y-empty-state"\n *ngIf="(softwares$ | async)?.data.length === 0 && (textFilter$ | async)?.length > 0"\n>\n <h1 class="c8y-icon-duocolor" c8yIcon="search"></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n\x3c!-- apply the class \'dd-low\' when the list contains less than 10 records--\x3e\n<c8y-list-group\n class="m-b-24"\n *ngIf="(softwares$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': (softwares$ | async)?.data.length < 10 }"\n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs">\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-3">\n {{ \'Software\' | translate }}\n </div>\n <div class="col-4">\n {{ \'Description\' | translate }}\n </div>\n <div class="col-3">\n {{ \'Device type\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Versions\' | translate }}\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-li *c8yFor="let software of softwares$ | async; let i = index; loadMore: \'auto\'">\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-60">\n <button class="btn-clean col-3" (click)="editSoftware(software)">\n <span class="text-truncate" title="{{ software.name }}">\n {{ software.name }}\n </span>\n </button>\n\n <div class="col-4">\n <p class="text-truncate" title="{{ software.description }}">\n <span class="text-label-small m-r-4 visible-xs-inline">\n {{ \'Description\' | translate }}\n </span>\n <span *ngIf="software.description; else emptyDescription">\n {{ software.description }}\n </span>\n </p>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n\n <div class="col-3">\n <div\n class="text-truncate"\n title="{{ \'Device type\' | translate }}: {{ software.c8y_Filter?.type || \'-\' }}"\n >\n <span class="text-label-small m-r-8 visible-xs-inline" translate>\n Device type\n </span>\n <span *ngIf="software.c8y_Filter?.type; else emptyText">\n {{ software.c8y_Filter?.type }}\n </span>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n </div>\n </div>\n\n <div class="col-2">\n <span class="label label-warning flex-item-right-sm" *ngIf="isLegacy(software)">\n <span translate>\n Legacy\n </span>\n </span>\n <span *ngIf="!isLegacy(software)">\n <span *ngIf="(getBaseVersionsCount$(software) | async) === null">\n <span class="label label-info flex-item-right-sm">\n <i class="icon-spin" c8yIcon="circle-o-notch"></i>\n </span>\n </span>\n <span *ngIf="(getBaseVersionsCount$(software) | async) !== null">\n <span [ngPlural]="getBaseVersionsCount$(software) | async">\n <ng-template ngPluralCase="=0">\n <span class="label label-default flex-item-right-sm">\n <span translate>\n No versions\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="=1">\n <span class="label label-info flex-item-right-sm">\n <span translate>\n 1 version\n </span>\n </span>\n </ng-template>\n <ng-template ngPluralCase="other">\n <span class="label label-info flex-item-right-sm">\n <span\n ngNonBindable\n translate\n [translateParams]="{ count: getBaseVersionsCount$(software) | async }"\n >\n {{ count }} versions\n </span>\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n\n <c8y-li-action (click)="editSoftware(software)" icon="pencil">\n {{ \'Edit\' | translate }}\n </c8y-li-action>\n <c8y-li-action (click)="deleteSoftware(software)" icon="trash">\n {{ \'Delete\' | translate }}\n </c8y-li-action>\n </c8y-li>\n</c8y-list-group>\n'}]}],A.ctorParameters=function(){return[{type:O},{type:n.ModalService},{type:y.BsModalService},{type:f.TranslateService},{type:n.AlertService},{type:u.Router},{type:u.ActivatedRoute}]},b([n.memoize(l.property("id"))],A.prototype,"getBaseVersionsCount$",null);var B=function(){function e(e,t,n,i,r,a,o){var s=this;this.activatedRoute=e,this.inventoryService=t,this.repositoryService=n,this.alertService=i,this.translateService=r,this.modalService=a,this.bsModalService=o,this.reload$=new p.Subject,this.reloading$=new p.BehaviorSubject(!1),this.updateSoftware$=new p.Subject,this.softwareUpdated$=new p.Subject,this.baseVersionsUpdated$=new p.Subject,this.software$=p.merge(this.activatedRoute.params.pipe(d.map((function(e){return e.id})),d.switchMap((function(e){return p.from(s.inventoryService.detail(e).then((function(e){return e.data})))}))),this.reload$.pipe(d.tap((function(){return s.reloading$.next(!0)})),d.switchMap((function(){return s.activatedRoute.params})),d.map((function(e){return e.id})),d.switchMap((function(e){return p.from(s.inventoryService.detail(e).then((function(e){return e.data})))})),d.tap((function(){return s.reloading$.next(!1)}))),this.softwareUpdated$).pipe(d.shareReplay(1)),this.baseVersions$=p.merge(this.software$.pipe(d.distinctUntilKeyChanged("id")),this.baseVersionsUpdated$,this.reload$).pipe(d.switchMap((function(){return s.software$})),d.switchMap((function(e){return s.repositoryService.listBaseVersions(e)})),d.shareReplay(1)),this.isLegacy$=this.software$.pipe(d.map((function(e){return s.repositoryService.isLegacyEntry(e)})),d.shareReplay(1)),this.destroy$=new p.Subject}return e.prototype.ngOnInit=function(){var e=this;this.updateSoftware$.pipe(d.withLatestFrom(this.software$),d.switchMap((function(t){var n=C(t,2),i=n[0],r=n[1];return e.inventoryService.update(Object.assign({id:r.id},i))})),d.map((function(e){return e.data})),d.tap((function(t){return e.softwareUpdated$.next(t)})),d.tap((function(){return e.alertService.success(n.gettext("Saved."))})),d.takeUntil(this.destroy$)).subscribe()},e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.addBaseVersion=function(){var e=this;this.software$.pipe(d.take(1),d.switchMap((function(t){var n={class:"modal-sm",ignoreBackdropClick:!0,initialState:{model:{selected:t,description:t.description}}};return e.bsModalService.show(D,n).content.saved}))).subscribe((function(){return e.baseVersionsUpdated$.next()}))},e.prototype.deleteBaseVersion=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a;return S(this,(function(o){switch(o.label){case 0:return o.trys.push([0,3,,4]),t=n.gettext("Delete software"),i="\n "+this.translateService.instant(n.gettext("You are about to delete software {{ version }}."),{version:e.c8y_Software.version})+"\n "+this.translateService.instant(n.gettext("This operation is irreversible."))+"\n "+this.translateService.instant(n.gettext("Do you want to proceed?"))+"\n ",r={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,i,n.Status.DANGER,r)];case 1:return o.sent(),[4,this.repositoryService.delete(e)];case 2:return o.sent(),this.alertService.success(n.gettext("Software deleted.")),this.baseVersionsUpdated$.next(),[3,4];case 3:return(a=o.sent())&&this.alertService.addServerFailure(a),[3,4];case 4:return[2]}}))}))},e.prototype.ngOnDestroy=function(){this.destroy$.next(!0),this.destroy$.unsubscribe()},e}();B.decorators=[{type:t.Component,args:[{selector:"c8y-software-details",template:'<c8y-title>\n {{ (software$ | async)?.name }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n path="#/software"\n label="{{ \'Software repository\' | translate }}"\n icon="c8y-tools"\n >\n </c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button\n *ngIf="!(isLegacy$ | async)"\n class="btn btn-link"\n title="{{ \'Add software\' | translate }}"\n (click)="addBaseVersion()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add software\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="reload$.next()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading$ | async }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card m-b-4">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Name, description and device type filter\n </h4>\n </div>\n <div class="card-block">\n <div class="row">\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Name\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #nameInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.name"\n #nameModel="ngModel"\n placeholder="{{ \'e.g. My software\' | translate }}"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.name?.length || 31 }"\n required\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateSoftware$.next({ name: nameInput.value }); nameModel.reset()"\n [disabled]="nameInput.value.length == 0"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Description\' | translate }}\n </label>\n <div class="input-group input-group-editable">\n <input\n #descriptionInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.description"\n #descriptionModel="ngModel"\n placeholder="{{ \'e.g. Cloud connectivity software\' | translate }}"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.description?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)=" updateSoftware$.next({ description: descriptionInput.value }); descriptionModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n <div class="col-md-4">\n <c8y-form-group>\n <label class="control-label">\n {{ \'Device type filter\' | translate }}\n\n <button\n class="btn-clean"\n popover="{{ \'If the filter is set, the software will show up for installation only for devices of that type. If no filter is set, it will be available for all devices.\' | translate }}"\n [outsideClick]="true"\n container="body"\n >\n <i c8yIcon="question-circle-o" class="text-info"></i>\n </button>\n </label>\n <div class="input-group input-group-editable">\n <input\n #deviceTypeInput\n type="text"\n class="form-control"\n [ngModel]="(software$ | async)?.c8y_Filter?.type"\n #deviceTypeModel="ngModel"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n [ngStyle]="{ \'width.ch\': (software$ | async)?.type?.length || 31 }"\n />\n <span></span>\n <div class="input-group-btn">\n <button\n class="btn btn-primary"\n title="{{ \'Save\' | translate }}"\n (click)="updateSoftware$.next({ c8y_Filter: { type: deviceTypeInput.value } }); deviceTypeModel.reset()"\n >\n {{ \'Save\' | translate }}\n </button>\n </div>\n </div>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>\n Versions\n </h4>\n </div>\n\n <div class="card-block p-t-0 p-b-24">\n <div *ngIf="(baseVersions$ | async)?.data.length === 0">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-tools" class="c8y-icon-duocolor"></h1>\n <h3 translate>No versions to display.</h3>\n <p translate>Add a new version by clicking below.</p>\n <p>\n <button\n class="btn btn-primary"\n title="{{ \'Add software\' | translate }}"\n (click)="addBaseVersion()"\n >\n {{ \'Add software\' | translate }}\n </button>\n </p>\n </div>\n </div>\n\n <c8y-list-group\n [ngClass]="{ \'dd-low\': (baseVersions$ | async)?.data.length < 10 }"\n *ngIf="(baseVersions$ | async)?.data.length > 0"\n >\n <c8y-li\n *c8yFor="let baseVersion of baseVersions$ | async; let i = index; loadMore: \'auto\'"\n >\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-50">\n <div class="col-4">\n <p class="text-truncate-wrap" title="{{ baseVersion.c8y_Software.version }}">\n {{ baseVersion.c8y_Software.version }}\n </p>\n </div>\n <div class="col-5">\n <p class="text-truncate-wrap">\n <span class="text-label-small m-r-8" translate>\n File\n </span>\n <span title=" {{ getBinaryName$(baseVersion.c8y_Software.url) | async }}">\n <c8y-file-download url="{{ baseVersion.c8y_Software.url }}"></c8y-file-download>\n </span>\n </p>\n </div>\n <div class="col-2 flex-row a-i-start">\n <span *ngIf="isLegacy$ | async" class="label label-warning flex-item-right-sm">\n {{ \'Legacy\' | translate }}\n </span>\n\n <div class="fit-h-20" *ngIf="!(isLegacy$ | async)">\n <button\n class="btn btn-danger btn-xs visible-xs flex-item-right m-r-8 m-t-8"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n {{ \'Delete\' | translate }}\n </button>\n </div>\n </div>\n <div *ngIf="!(isLegacy$ | async)" class="flex-item-right fit-h-20 p-r-8 hidden-xs">\n <button\n class="btn btn-dot text-danger showOnHover"\n (click)="deleteBaseVersion(baseVersion)"\n title="{{ \'Delete\' | translate }}"\n >\n <i c8yIcon="minus-circle"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </div>\n </div>\n </div>\n</div>\n'}]}],B.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:c.InventoryService},{type:O},{type:n.AlertService},{type:f.TranslateService},{type:n.ModalService},{type:y.BsModalService}]},b([n.memoize()],B.prototype,"getBinaryName$",null);var P=function(){function t(e,t,n){var i=this;this.repositoryService=e,this.bsModalRef=t,this.alert=n,this.binary={file:void 0,url:void 0},this.pattern="",this.mo={},this.saving=!1,this.uploadChoice="uploadBinary",this.result=new Promise((function(e,t){i._save=e,i._cancel=t}))}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){var t;return S(this,(function(i){switch(i.label){case 0:return t=this,[4,this.repositoryService.listRepositoryEntries(e.RepositoryType.CONFIGURATION)];case 1:return t.configs=i.sent(),this.selected&&(this.uploadChoice=this.binary.file?"uploadBinary":"uploadUrl",this.existingBinary=this.binary.file),this.setPipe(""),this.submitButtonTitle=this.mo.id?n.gettext("Update configuration"):n.gettext("Add configuration"),[2]}}))}))},t.prototype.cancel=function(){this.bsModalRef.hide(),this._cancel()},t.prototype.setPipe=function(e){this.pattern=e,this.filterPipe=p.pipe(d.map((function(e){return l.uniqBy(e,"configurationType")})),d.map((function(t){return t.filter((function(t){return t.configurationType&&t.configurationType.toLowerCase().indexOf(e.toLowerCase())>-1}))})))},t.prototype.onFile=function(e){this.configurationForm.form.markAsDirty(),l.isUndefined(e.url)?l.isUndefined(e.droppedFiles)?this.binary={file:void 0,url:void 0}:this.binary={file:e.droppedFiles[0].file}:this.binary={url:e.url}},t.prototype.save=function(){return w(this,void 0,void 0,(function(){var t,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:return l.trys.push([0,2,3,4]),this.saving=!0,i=(t=this).selected,r=t.version,a=t.description,o=t.binary,s=t.deviceType,this.existingBinary===this.binary.file&&(o.file=void 0),[4,this.repositoryService.save({selected:i,version:r,description:a,binary:o,deviceType:s},e.RepositoryType.CONFIGURATION,this.mo)];case 1:return l.sent(),this.alert.success(this.mo.id?n.gettext("Configuration updated."):n.gettext("Configuration created.")),this.bsModalRef.hide(),this._save(),[3,4];case 2:return c=l.sent(),this.alert.addServerFailure(c),this._cancel(),[3,4];case 3:return this.saving=!1,[7];case 4:return[2]}}))}))},t}();P.decorators=[{type:t.Component,args:[{selector:"c8y-configuration-detail",template:'<div class="viewport-modal">\n <div class="modal-header dialog-header">\n <i [c8yIcon]="\'cogs\'"></i>\n <h4 translate *ngIf="mo.id">Update configuration</h4>\n <h4 translate *ngIf="!mo.id">Add configuration</h4>\n </div>\n\n <form class="d-contents" #configurationForm="ngForm" (ngSubmit)="configurationForm.form.valid && save()">\n <div class="modal-inner-scroll">\n <div class="modal-body">\n <c8y-form-group>\n <label translate>Name</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g.\' | translate }} hosts"\n autocomplete="off"\n required\n maxlength="254"\n [(ngModel)]="version"\n name="version"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Device type</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g.\' | translate }} c8y_Linux"\n maxlength="254"\n autocomplete="off"\n [(ngModel)]="deviceType"\n name="deviceType"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Description</label>\n <input\n type="text"\n class="form-control"\n placeholder="{{ \'e.g. Host configuration\' | translate }} c8y_Linux"\n maxlength="254"\n autocomplete="off"\n [(ngModel)]="description"\n name="description"\n />\n </c8y-form-group>\n\n <c8y-form-group>\n <label translate>Configuration type</label>\n <c8y-typeahead\n [(ngModel)]="selected"\n name="confType"\n placeholder="{{ \'e.g.\' | translate }} ssh"\n (onSearch)="setPipe($event)"\n displayProperty="configurationType"\n >\n <c8y-li\n *c8yFor="let config of configs; pipe: filterPipe; notFound: notFoundTemplate"\n class="p-l-8 p-r-8 c8y-list__item--link"\n (click)="selected = config; setPipe(\'\')"\n [active]="selected === config"\n >\n <c8y-highlight\n [text]="config.configurationType || \'--\'"\n [pattern]="pattern"\n ></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class="bg-gray-lighter p-8" *ngIf="pattern.length > 0">\n <span translate>No match found, add new`configuration`?</span>\n <button title="Create new`configuration`" type="button" class="btn btn-primary btn-xs m-l-16" translate>\n Create new`configuration`\n </button>\n </c8y-li>\n </ng-template>\n </c8y-typeahead>\n </c8y-form-group>\n\n <c8y-form-group>\n <div class="legend form-block m-t-40" translate>Configuration file</div>\n <c8y-file-picker\n [maxAllowedFiles]="1"\n (onFilesPicked)="onFile($event)"\n [uploadChoice]="uploadChoice"\n [fileUrl]="binary.url"\n [fileBinary]="binary.file"\n >\n </c8y-file-picker>\n </c8y-form-group>\n </div>\n </div>\n\n <div class="modal-footer">\n <button\n (click)="cancel()"\n type="button"\n class="btn btn-default"\n title="{{ \'Cancel\' | translate }}"\n [disabled]="saving"\n >\n <span translate>Cancel</span>\n </button>\n <button\n class="btn btn-primary"\n type="submit"\n title="{{ submitButtonTitle | translate }}"\n [ngClass]="{ \'btn-pending\': saving }"\n [disabled]="\n !configurationForm.valid ||\n configurationForm.pristine ||\n (!binary?.url && !binary?.file) ||\n saving\n "\n >\n {{ submitButtonTitle | translate }}\n </button>\n </div>\n </form>\n</div>\n'}]}],P.ctorParameters=function(){return[{type:O},{type:y.BsModalRef},{type:n.AlertService}]},P.propDecorators={configurationForm:[{type:t.ViewChild,args:["configurationForm",{static:!0}]}]};var M=function(){function t(e,t,i,r,a,o,s){this.alert=e,this.repositoryService=t,this.bsModalService=i,this.modalService=r,this.translateService=a,this.inventoryBinaryService=o,this.inventoryService=s,this.filterTerm="",this.reloading=!1,this.DELETED_SUCCESS_MSG=n.gettext("Configuration deleted.")}return t.prototype.ngOnInit=function(){this.loadConfigurations()},t.prototype.loadConfigurations=function(){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return this.reloading=!0,t=this,n=p.of,[4,this.repositoryService.listRepositoryEntries(e.RepositoryType.CONFIGURATION)];case 1:return t.configurations$=n.apply(void 0,[i.sent()]),this.reloading=!1,this.reset(),[2]}}))}))},t.prototype.add=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return e.trys.push([0,3,,4]),[4,this.bsModalService.show(P,{class:"modal-sm",ignoreBackdropClick:!0}).content.result];case 1:return e.sent(),[4,this.loadConfigurations()];case 2:return e.sent(),[3,4];case 3:return e.sent(),[3,4];case 4:return[2]}}))}))},t.prototype.edit=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:return[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 1:t=i.sent(),i.label=2;case 2:return i.trys.push([2,5,,6]),(n=this.bsModalService.show(P,{class:"modal-sm",ignoreBackdropClick:!0,initialState:{selected:{id:e.id,name:e.configurationType},version:e.name,deviceType:e.deviceType,description:e.description,binary:{file:t,url:e.url}}}).content).mo=e,[4,n.result];case 3:return i.sent(),[4,this.loadConfigurations()];case 4:return i.sent(),[3,6];case 5:return i.sent(),[3,6];case 6:return[2]}}))}))},t.prototype.isBinaryFile=function(e){return!!this.inventoryBinaryService.getIdFromUrl(e.url)},t.prototype.getBinaryName=function(e){return this.repositoryService.getBinaryName$(e.url)},t.prototype.download=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){switch(n.label){case 0:return[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 1:return t=n.sent(),h.saveAs(t),[2]}}))}))},t.prototype.delete=function(e){return w(this,void 0,void 0,(function(){var t,i,r,a,o,s,c;return S(this,(function(l){switch(l.label){case 0:return l.trys.push([0,4,,5]),t=n.gettext("Delete configuration snapshot"),i=n.gettext("You are about to delete the configuration snapshot {{ name }}."),r=n.gettext("This operation is irreversible."),a=n.gettext("Do you want to proceed?"),o=[this.translateService.instant(i,{name:e.name}),this.translateService.instant(r),this.translateService.instant(a)].join(" "),s={ok:n.gettext("Delete")},[4,this.modalService.confirm(t,o,n.Status.DANGER,s)];case 1:return l.sent(),[4,this.repositoryService.delete(e)];case 2:return l.sent(),this.alert.success(this.DELETED_SUCCESS_MSG),[4,this.loadConfigurations()];case 3:return l.sent(),[3,5];case 4:return(c=l.sent())&&this.alert.addServerFailure(c),[3,5];case 5:return[2]}}))}))},t.prototype.setPipe=function(e){var t=this;this.filterTerm=e,this.filterPipe=p.pipe(d.map((function(n){return t.data=0===e.trim().length?n:n.filter((function(n){return t.filterContainString(n.name,e)||t.filterContainString(n.configurationType,e)||t.filterContainString(n.deviceType,e)})),t.data})))},t.prototype.shouldShowEmptyState=function(){return!(this.data&&this.data.length>0)},t.prototype.reset=function(){this.filter.filterTerm="",this.setPipe("")},t.prototype.filterContainString=function(e,t){var n=t.toLowerCase().trim();return e&&e.toLowerCase().indexOf(n)>-1},t}();M.decorators=[{type:t.Component,args:[{selector:"c8y-configuration-list",template:'<c8y-title>\n <span translate>\n Configuration snapshots repository\n </span> \n <small\n *ngIf="(configurations$ | async)?.paging.totalPages === 1 && !filterTerm"\n >\n {{ (configurations$ | async).data.length }}\n <span translate>\n snapshots\n </span>\n </small>\n <small\n *ngIf="(configurations$ | async)?.paging.totalPages > 1 && !filterTerm"\n [tooltip]="\'More data available. Scroll to the bottom of the list to load it.\' | translate"\n container="body"\n >\n {{ (configurations$ | async).paging.pageSize }}+\n <span translate>snapshots</span>\n </small>\n <small *ngIf="filterTerm">\n <span translate>\n Search results for\n </span> "\n {{ this.filterTerm }}"\n </small>\n</c8y-title>\n\n<c8y-action-bar-item itemClass="navbar-form">\n <c8y-filter\n [icon]="\'search\'"\n (onSearch)="setPipe($event)"\n ></c8y-filter>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n (click)="add()"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Add configuration snapshot\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link"\n title="{{ \'Reload\' | translate }}"\n (click)="loadConfigurations()"\n >\n <i [ngClass]="{ \'icon-spin\': reloading }"\n c8yIcon="refresh"\n ></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n\x3c!-- empty state --\x3e\n<div class="c8y-empty-state text-center"\n *ngIf="!filterTerm && (configurations$ | async)?.data.length === 0"\n>\n <h1 c8yIcon="gears"></h1>\n <h3 translate>There are no configuration snapshots defined</h3>\n <p translate>Add a configuration snapshot first.</p>\n <div>\n <button (click)="add()" class="btn btn-primary" translate>\n Add configuration snapshot\n </button>\n </div>\n <p c8y-guide-docs>\n <small translate ngNonBindable>\n Find out more in the\n <a c8y-guide-href="users-guide/device-management/#configuration-repository">\n User guide`KEEP_ORIGINAL`\n </a>.\n </small>\n </p>\n</div>\n\n\x3c!-- no results empty state --\x3e\n<div class="c8y-empty-state"\n *ngIf="shouldShowEmptyState() && (configurations$ | async)?.data.length > 0"\n>\n <h1 class="c8y-icon-duocolor"\n c8yIcon="search"\n ></h1>\n <h3 translate>\n No results to display.\n </h3>\n <p translate>\n Refine your search terms or check your spelling.\n </p>\n</div>\n\n<c8y-list-group class="m-b-24"\n *ngIf="(configurations$ | async)?.data.length > 0"\n [ngClass]="{ \'dd-low\': data && data.length ? data.length < 10 : (configurations$ | async)?.data.length < 10 }"\n\n>\n <c8y-li class="page-sticky-header c8y-list__item--empty-actions hidden-xs"\n *ngIf="!shouldShowEmptyState()"\n >\n <c8y-li-icon>\n <i class="p-l-24"></i>\n </c8y-li-icon>\n <c8y-li-body class="content-flex-60">\n <div class="col-2">\n {{ \'Configuration\' | translate }}\n </div>\n <div class="col-3">\n {{ \'Description\' | translate }}\n </div>\n <div class="col-3">\n {{ \'File\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Device type\' | translate }}\n </div>\n <div class="col-2">\n {{ \'Configuration type\' | translate }}\n </div>\n </c8y-li-body>\n </c8y-li>\n\n <c8y-li *c8yFor="let configuration of configurations$; pipe: filterPipe">\n <c8y-li-icon icon="gears"></c8y-li-icon>\n <div class="content-flex-60">\n <button class="btn-clean col-2"\n (click)="edit(configuration)"\n >\n <span class="text-truncate"\n title="{{ configuration.name || \'-\' }}"\n >\n <c8y-highlight\n [text]="configuration.name || \'-\'"\n elementClass="text-info"\n [pattern]="filterTerm"\n ></c8y-highlight>\n </span>\n </button>\n <div class="col-3">\n <div class="text-label-small visible-xs-inline m-r-4">\n {{ \'Description\' | translate }}\n </div>\n <small class="text-truncate"\n *ngIf="configuration.description; else emptyDescription"\n [title]="configuration.description"\n >\n {{ configuration.description }}\n </small>\n </div>\n <div class="col-3">\n <span class="text-truncate">\n <span class="text-label-small m-r-4 visible-xs-inline" translate>\n File\n </span>\n <small\n *ngIf="isBinaryFile(configuration); else noFile"\n title="{{ getBinaryName(configuration) | async }}"\n >\n {{ getBinaryName(configuration) | async }}\n </small>\n <ng-template #noFile>\n <small title="{{ configuration.url }}">\n {{ configuration.url }}\n </small>\n </ng-template>\n </span>\n </div>\n <div class="col-2">\n <div class="text-truncate"\n title="{{ \'Device type\' | translate }}: {{ configuration.deviceType || \'-\' }}"\n >\n <span class="text-label-small visible-xs-inline m-r-4" translate>\n Device type\n </span>\n <span *ngIf="configuration.deviceType; else emptyText">\n <c8y-highlight\n [text]="configuration.deviceType || \'-\'"\n elementClass="text-info"\n [pattern]="filterTerm"\n >\n </c8y-highlight>\n </span>\n </div>\n </div>\n <div class="col-2">\n <div class="text-truncate"\n title="{{ configuration.configurationType }}"\n >\n <span class="label label-primary"\n *ngIf="configuration.configurationType; else emptyText"\n >\n <c8y-highlight\n [text]="configuration.configurationType"\n elementClass="text-info"\n [pattern]="filterTerm"\n >\n </c8y-highlight>\n </span>\n </div>\n </div>\n </div>\n <c8y-li-action\n (click)="edit(configuration)"\n icon="pencil"\n label="{{ \'Edit\' | translate }}"\n >\n </c8y-li-action>\n <c8y-li-action\n (click)="delete(configuration)"\n icon="trash-o"\n label="{{ \'Delete\' | translate }}"\n >\n </c8y-li-action>\n <c8y-li-action\n *ngIf="isBinaryFile(configuration)"\n (click)="download(configuration)"\n icon="download"\n label="{{ \'Download\' | translate }}"\n >\n </c8y-li-action>\n <ng-template #emptyText>\n <small class="text-muted">\n <em>{{ \'Undefined\' | translate }}</em>\n </small>\n </ng-template>\n <ng-template #emptyDescription>\n <small class="text-muted">\n <em>{{ \'No description\' | translate }}</em>\n </small>\n </ng-template>\n </c8y-li>\n</c8y-list-group>\n'}]}],M.ctorParameters=function(){return[{type:n.AlertService},{type:O},{type:y.BsModalService},{type:n.ModalService},{type:f.TranslateService},{type:c.InventoryBinaryService},{type:c.InventoryService}]},M.propDecorators={filter:[{type:t.ViewChild,args:[n.FilterInputComponent,{static:!1}]}]},b([n.memoize(l.property("id"))],M.prototype,"getBinaryName",null);var k=function(){function e(){this.navs=[]}return e.prototype.get=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){return 0===this.navs.length&&(this.navs.push(new n.NavigatorNode({label:n.gettext("Firmware repository"),path:"firmware",icon:"c8y-firmware",parent:n.gettext("Management"),priority:1e3})),this.navs.push(new n.NavigatorNode({label:n.gettext("Software repository"),path:"software",icon:"c8y-tools",parent:n.gettext("Management"),priority:900})),this.navs.push(new n.NavigatorNode({label:n.gettext("Configuration repository"),path:"configuration",icon:"gears",parent:n.gettext("Management"),priority:800}))),[2,this.navs]}))}))},e}();k.decorators=[{type:t.Injectable}];var V=function(){function e(e,i){var r=this;this.repositoryService=e,this.translateService=i,this.repositoryEntriesWithVersions$=void 0,this.badgeTemplates={"=1":n.gettext("{{count}} version"),other:n.gettext("{{count}} versions")},this.title=n.gettext("Select repository entry"),this.load=new p.Subject,this.searchTerm=new p.BehaviorSubject(""),this.deviceTypeQuery={},this.searchQuery={},this.labels={ok:n.gettext("Save")},this.showFilter=!0,this.areMoreEntries=!1,this.resultEmitter=new t.EventEmitter,this.mode=n.ModalSelectionMode.SINGLE,this.disableSelected=!0,this.modalEntries=this.load.pipe(d.switchMap((function(){return r.repositoryEntriesWithVersions$})),d.mergeMap((function(e){return r.aggregate(e)})),d.tap((function(e){r.areMoreEntries=e.length>=r.PAGE_SIZE}))),this.PAGE_SIZE=100,this.queriesUtil=new c.QueriesUtil}return e.prototype.ngOnInit=function(){var e=this;if(!this.repositoryType)throw new Error("Repository type must be defined");this.repositoryEntriesWithVersions$||(this.repositoryEntriesWithVersions$=p.from(this.repositoryService.listRepositoryEntries(this.repositoryType,{query:this.queriesUtil.addOrFilter(this.deviceTypeQuery,this.searchQuery),params:{pageSize:this.PAGE_SIZE}})).pipe(d.map((function(e){return e.data})),d.map((function(t){return e.getAndAssignRepositoryBinaries(t)})),d.shareReplay(1)))},e.prototype.getAndAssignRepositoryBinaries=function(e){var t=this;return e.forEach((function(e){e.versions=t.repositoryService.listAllVersions(e)})),e},e.prototype.search=function(e){this.searchTerm.next(e),this.searchQuery=e?{name:"*"+e+"*"}:{},this.load.next()},e.prototype.result=function(e){this.resultEmitter.emit(e)},e.prototype.aggregate=function(e){return w(this,void 0,void 0,(function(){var t,n,i=this;return S(this,(function(r){return t=this.repositoryType,n=this.selected,[2,Promise.all(e.map((function(e){return w(i,void 0,void 0,(function(){var i,r;return S(this,(function(a){switch(a.label){case 0:return r=this.getSelectModalOptions,[4,this.repositoryService.fetchAllItemsFromList(e.versions)];case 1:return i=r.apply(this,[a.sent(),n,e,t]),[2,this.getSelectModalObject(e,i)]}}))}))})))]}))}))},e.prototype.getSelectModalOptions=function(e,t,i,r){var a=this,o=[];return e.forEach((function(e){var s=a.isBinaryRepositorySelected(t,i,e,r),c=e[""+r].version,p=c||"("+a.translateService.instant(n.gettext("not specified`version`"))+")",d=c?"":"text-muted";o.push({body:[{value:p,class:d}],obj:Object.assign(Object.assign(Object.assign({id:e.id,name:i.name,version:c},l.get(e,"c8y_Patch.dependency")&&{dependency:l.get(e,"c8y_Patch.dependency")}),l.get(e,"c8y_Patch")&&{c8y_Patch:!0}),{url:e[""+r].url}),selected:s})})),o},e.prototype.isBinaryRepositorySelected=function(e,t,n,i){return!!e&&e.filter((function(e){return e.name===t.name&&e.version===n[""+i].version})).length>0},e.prototype.getSelectModalObject=function(e,t){var n=1===t.length?this.translateService.instant(this.badgeTemplates["=1"],{count:t.length}):this.translateService.instant(this.badgeTemplates.other,{count:t.length});return{groupId:e.id,body:[{value:e.name,class:"text-truncate"},{value:e.description,class:"text-truncate text-muted"}],additionalInformation:{value:n,class:"label label-info"},options:t}},e}();V.decorators=[{type:t.Component,args:[{selector:"c8y-repository-select-modal",template:'<c8y-select-modal\n [icon]="icon"\n [title]="title"\n [subTitle]="subTitle"\n [items]="modalEntries | async"\n [mode]="mode"\n [disableSelected]="disableSelected"\n [labels]="labels"\n [showFilter]="showFilter"\n [areMoreEntries]="areMoreEntries"\n (search)="search($event)"\n (result)="result($event)"\n>\n</c8y-select-modal>\n'}]}],V.ctorParameters=function(){return[{type:O},{type:f.TranslateService}]};var N=function(){function t(t,n,i,r){var a=this;this.route=t,this.repository=n,this.inventory=i,this.bsModal=r,this.isEmpty=l.isEmpty,this.reloading=!1,this.device$=new p.BehaviorSubject(this.route.parent.snapshot.data.contextData),this.deviceFirmwareFragment$=this.device$.pipe(d.map((function(e){return e.c8y_Firmware}))),this.firmwareBinary$=this.deviceFirmwareFragment$.pipe(d.filter((function(e){return!l.isEmpty(e)})),d.switchMap((function(t){return p.from(a.repository.getRepositoryBinaryMoByVersion(t,e.RepositoryType.FIRMWARE))})),d.shareReplay(1)),this.repositoryEntry$=this.firmwareBinary$.pipe(d.switchMap((function(e){return a.repository.getRepositoryEntryMO$(e)})),d.shareReplay(1)),this.patches$=p.combineLatest(this.firmwareBinary$,this.repositoryEntry$).pipe(d.switchMap((function(e){var t=C(e,2),n=t[0],i=t[1];if(i&&n){var r=a.repository.getBaseVersionFromMO(n);return p.from(a.repository.listPatchVersions(i,r)).pipe(d.map((function(e){return e.data})))}return p.of([])})),d.shareReplay(1)),this.changesOperation$=new p.BehaviorSubject(null),this.changesInProgress$=this.changesOperation$.pipe(d.map((function(e){return a.isInProgress(e)})))}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),[4,this.loadOperation()];case 2:return e.sent(),[2]}}))}))},t.prototype.installFirmware=function(){var t=this,i={repositoryEntriesWithVersions$:p.of([]),repositoryEntriesWithVersionsFn$:function(e){return t.getRepositoryEntriesWithVersions$(e.content.searchTerm)},repositoryType:e.RepositoryType.FIRMWARE,title:n.gettext("Install firmware"),subTitle:n.gettext("Available firmwares matching the device type"),icon:"c8y-firmware",mode:n.ModalSelectionMode.SINGLE,labels:{ok:n.gettext("Install")},disableSelected:!1};this.deviceFirmwareFragment$.pipe(d.take(1),d.switchMap((function(e){if(e){var n=[{name:e.name,version:e.version}];l.assign(i,{selected:n})}var r=t.bsModal.show(V,{ignoreBackdropClick:!0,initialState:i});return i.repositoryEntriesWithVersionsFn$&&(r.content.repositoryEntriesWithVersions$=i.repositoryEntriesWithVersionsFn$(r)),r.content.load.next(),r.content.resultEmitter}))).subscribe((function(e){var n=C(e,1)[0];t.handleOperation(n)}))},t.prototype.getRepositoryEntriesWithVersions$=function(t){var n=this;return t.pipe(d.distinctUntilChanged(),d.switchMap((function(t){return n.repository.listRepositoryEntries(e.RepositoryType.FIRMWARE,{query:n.repository.getDeviceTypeQuery(e.RepositoryType.FIRMWARE,n.device$.value),partialName:t,params:{pageSize:100}})})),d.map((function(e){return e.data})),d.map((function(e){return n.getAndAssignRepositoryBinaries(e)})),d.shareReplay(1))},t.prototype.getAndAssignRepositoryBinaries=function(e){var t=this;return e.forEach((function(e){e.versions=t.repository.listBaseVersions(e)})),e},t.prototype.addPatch=function(){var t=this,i={repositoryType:e.RepositoryType.FIRMWARE,repositoryEntriesWithVersions$:this.getRepositoryEntryWithPatches$(),title:n.gettext("Install firmware"),subTitle:n.gettext("Available firmwares matching the device type"),icon:"c8y-firmware",mode:n.ModalSelectionMode.SINGLE,labels:{ok:n.gettext("Install")},disableSelected:!1};this.deviceFirmwareFragment$.pipe(d.take(1),d.switchMap((function(e){if(e){var n=[{name:e.name,version:e.version}];l.assign(i,{selected:n})}var r=t.bsModal.show(V,{ignoreBackdropClick:!0,initialState:i});return r.content.load.next(),r.content.resultEmitter}))).subscribe((function(e){t.handleOperation(e)}))},t.prototype.getRepositoryEntryWithPatches$=function(){return p.combineLatest(this.repositoryEntry$,this.patches$).pipe(d.map((function(e){var t=C(e,2),n=t[0],i=t[1];return[Object.assign(Object.assign({},n),{versions:i})]})))},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:return this.reloading=!0,e=this.device$.value.id,[4,this.inventory.detail(e,{withChildren:!1})];case 1:return t=n.sent().data,this.device$.next(t),this.reloading=!1,[2]}}))}))},t.prototype.handleOperation=function(e){return w(this,void 0,void 0,(function(){var t;return S(this,(function(n){switch(n.label){case 0:return[4,this.repository.createFirmwareUpdateOperation(this.device$.value,e)];case 1:return t=n.sent(),this.trackOperation(t),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:return e=this.device$.value.id,[4,this.repository.getLastFirmwareUpdateOperation(e)];case 1:return t=n.sent(),this.trackOperation(t),[2]}}))}))},t.prototype.trackOperation=function(e){var t=this;this.changesOperation$.next(e),this.isInProgress(e)&&this.repository.observeOperation(e).subscribe((function(e){t.changesOperation$.next(e),e.status===c.OperationStatus.SUCCESSFUL&&t.loadDevice()}),(function(e){t.changesOperation$.next(e)}))},t.prototype.isInProgress=function(e){return e&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(e.status)},t}();N.decorators=[{type:t.Component,args:[{selector:"c8y-firmware-device-tab",template:'<div class="row">\n <div class="col-lg-12 col-lg-max">\n <div class="card">\n <div class="card-header separator">\n <h4 class="card-title" translate>Current firmware</h4>\n </div>\n <div class="inner-scroll">\n <fieldset *ngIf="changesOperation$ | async" class="card-block bg-gray-white">\n <c8y-single-operation [operation]="changesOperation$ | async"></c8y-single-operation>\n </fieldset>\n <div class="card-block p-t-0 p-b-0">\n \n \x3c!-- EMPTY STATE --\x3e\n <ng-container *ngIf="isEmpty(deviceFirmwareFragment$ | async); else firmwareBlock">\n <div class="c8y-empty-state text-center">\n <h1 c8yIcon="c8y-firmware" class="c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No firmware installed.</strong> <br />\n <small translate>Click below to install firmware into this device.</small>\n </p>\n </div>\n </ng-container>\n\n \x3c!-- FIRMWARE --\x3e\n <ng-template #firmwareBlock>\n <c8y-list-group class="no-border-last">\n <c8y-li>\n <c8y-li-icon>\n <i c8yIcon="c8y-firmware"></i>\n </c8y-li-icon>\n\n <c8y-li-body *ngIf="deviceFirmwareFragment$ | async as deviceFirmwareFragment">\n \x3c!-- Firmware title --\x3e\n <p class="m-b-16 text-medium">\n {{ deviceFirmwareFragment.name }}\n </p>\n \x3c!-- Firmware description --\x3e\n <div *ngIf="repositoryEntry$ | async as repositoryEntry">\n <p class="text-label-small" translate>\n Description\n </p>\n <p>\n {{ repositoryEntry.description }}\n </p>\n </div>\n\n \x3c!-- BASE/PATCH VERSION --\x3e\n <div class="m-b-16">\n <p class="text-label-small" translate>\n Version\n </p>\n <p *ngIf="deviceFirmwareFragment.version; else versionNotSpecified">\n {{ deviceFirmwareFragment.version }}\n </p>\n <ng-template #versionNotSpecified>\n <p>\n <em class="text-muted"> ({{ \'not specified`version`\' | translate }}) </em>\n </p>\n </ng-template>\n </div>\n\n \x3c!-- ADD PATCH --\x3e\n <button\n *ngIf="(this.patches$ | async)?.length > 0"\n (click)="addPatch()"\n class="btn btn-xs btn-primary"\n [disabled]="changesInProgress$ | async"\n title="{{ \'Patches available\' | translate }}"\n >\n {{ \'Patches available\' | translate }}\n </button>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </ng-template>\n </div>\n </div>\n <div class="card-footer separator-top">\n\n \x3c!-- INSTALL FIRMWARE --\x3e\n <button\n *ngIf="isEmpty(deviceFirmwareFragment$ | async)"\n class="btn btn-primary"\n (click)="installFirmware()"\n title="{{ \'Install firmware\' | translate }}"\n >\n {{ \'Install firmware\' | translate }}\n </button>\n\n \x3c!-- REPLACE FIRMWARE --\x3e\n <button\n *ngIf="!isEmpty(deviceFirmwareFragment$ | async)"\n class="btn btn-primary"\n (click)="installFirmware()"\n [disabled]="changesInProgress$ | async"\n title="{{ \'Replace firmware\' | translate }}"\n >\n {{ \'Replace firmware\' | translate }}\n </button>\n </div>\n </div>\n </div>\n</div>\n'}]}],N.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:O},{type:c.InventoryService},{type:y.BsModalService}]};var L=function(){function e(){}return e.prototype.canActivate=function(e){var t=l.get(e,"data.contextData")||l.get(e,"parent.data.contextData"),n=l.get(t,"c8y_SupportedOperations");return!!n&&l.indexOf(n,"c8y_Firmware")>=0},e}();L.decorators=[{type:t.Injectable}];var U=function(){function t(t,n,i){var r=this;this.route=t,this.repository=n,this.inventory=i,this.deviceId=this.route.snapshot.parent.data.contextData.id,this.device$=new p.BehaviorSubject(this.route.snapshot.parent.data.contextData),this.deviceTypeQuery$=this.device$.pipe(d.map((function(t){return r.repository.getDeviceTypeQuery(e.RepositoryType.SOFTWARE,t)}))),this.list$=this.device$.pipe(d.map((function(e){return r.repository.getDeviceSoftwareList(e)}))),this.changes$=new p.BehaviorSubject([]),this.changesOperation$=new p.BehaviorSubject(null),this.changesInProgress$=this.changesOperation$.pipe(d.map((function(e){return r.isInProgress(e)}))),this.reloading=!1}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),[4,this.loadOperation()];case 2:return e.sent(),[2]}}))}))},t.prototype.addChanges=function(e){var t=this,n=I(this.changes$.value);e.forEach((function(e){n.some((function(n){return t.areSameChanges(n,e)}))||(n=I(n,[e]))})),this.changes$.next(n)},t.prototype.dropChange=function(e){var t=this,n=I(this.changes$.value);n=n.filter((function(n){return!t.areSameChanges(n,e)})),this.changes$.next(n)},t.prototype.areSameChanges=function(e,t){return e.name===t.name&&e.version===t.version&&e.action===t.action},t.prototype.clearChanges=function(){this.changes$.next([])},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return this.reloading=!0,[4,this.inventory.detail(this.deviceId,{withChildren:!1})];case 1:return e=t.sent().data,this.device$.next(e),this.reloading=!1,[2]}}))}))},t.prototype.applyChanges=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repository.createSoftwareUpdateOperation(this.device$.value,this.changes$.value)];case 1:return e=t.sent(),this.trackOperation(e),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repository.getLastSoftwareUpdateOperation(this.deviceId)];case 1:return e=t.sent(),this.trackOperation(e),[2]}}))}))},t.prototype.trackOperation=function(e){var t=this;this.changesOperation$.next(e),this.isInProgress(e)&&(this.displayChangesFromOperation(e),this.repository.observeOperation(e).subscribe((function(e){t.changesOperation$.next(e),e.status===c.OperationStatus.SUCCESSFUL&&(t.clearChanges(),t.loadDevice())}),(function(e){t.changesOperation$.next(e)})))},t.prototype.displayChangesFromOperation=function(e){var t=this.repository.getDeviceSoftwareChangesFromOperation(e,this.device$.value);this.changes$.next(t)},t.prototype.isInProgress=function(e){return e&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(e.status)},t}();U.decorators=[{type:t.Component,args:[{selector:"c8y-software-device-tab",template:'<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="loadDevice()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="card d-grid grid__col--8-4--md m-b-0">\n <c8y-installed-software\n class="card--fullpage bg-white"\n [deviceTypeQuery]="deviceTypeQuery$ | async"\n [softwareList]="list$ | async"\n [deviceSoftwareChanges]="changes$ | async"\n [deviceSoftwareChangesOperation]="changesOperation$ | async"\n [deviceSoftwareChangesInProgress]="changesInProgress$ | async"\n (changes)="addChanges($event)"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class="card--fullpage bg-gray-white"\n [changes]="changes$ | async"\n [changesInProgress]="changesInProgress$ | async"\n (clear)="clearChanges()"\n (drop)="dropChange($event)"\n (apply)="applyChanges()"\n ></c8y-device-software-changes>\n</div>\n'}]}],U.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:O},{type:c.InventoryService}]};var j=function(){function e(){this.operations=["c8y_SoftwareUpdate","c8y_SoftwareList","c8y_Software"]}return e.prototype.canActivate=function(e){return this.isAnyOperationSupported(e)},e.prototype.isAnyOperationSupported=function(e){var t=e.data.contextData||e.parent.data.contextData,n=t&&t.c8y_SupportedOperations||[];return this.operations.some((function(e){return n.indexOf(e)>=0}))},e}();j.decorators=[{type:t.Injectable}];var G=function(){function i(e,n,i){this.repository=e,this.inventory=n,this.bsModal=i,this.changes=new t.EventEmitter}return i.prototype.installSoftware=function(){var e=this;this.displaySoftwareSelectModal({title:n.gettext("Install software"),labels:{ok:n.gettext("Install")},repositoryEntriesWithVersions$:p.of([]),repositoryEntriesWithVersionsFn$:function(t){return e.getInstallableSoftwareListWithVersions$(t.content.searchTerm)}}).subscribe((function(t){e.emitSoftwareInstall(t)}))},i.prototype.updateSoftware=function(e){var t=this;this.displaySoftwareSelectModal({title:n.gettext("Update software"),labels:{ok:n.gettext("Update")},showFilter:!1,repositoryEntriesWithVersions$:this.getSingleSoftwareWithVersions$(e)}).subscribe((function(e){t.emitSoftwareInstall(e)}))},i.prototype.removeSoftware=function(e){this.emitSoftwareRemoval([e])},i.prototype.getInstallableSoftwareListWithVersions$=function(t){var n=this,i=this.softwareList.map((function(e){return e.name}));return t.pipe(d.distinctUntilChanged(),d.switchMap((function(t){return n.repository.listRepositoryEntries(e.RepositoryType.SOFTWARE,{query:n.deviceTypeQuery,partialName:t,params:{pageSize:100}})})),d.map((function(e){return e.data})),d.map((function(e){return e.filter((function(e){return!i.includes(e.name)}))})),d.map((function(e){return n.attachVersions(e)})),d.shareReplay(1))},i.prototype.getSingleSoftwareWithVersions$=function(t){var n=this;return p.from(this.repository.listRepositoryEntries(e.RepositoryType.SOFTWARE,{query:{name:t.name}})).pipe(d.map((function(e){return e.data})),d.map((function(e){return n.attachVersions(e)})),d.shareReplay(1))},i.prototype.attachVersions=function(e){var t=this;return e.forEach((function(e){e.versions=t.repository.listBaseVersions(e)})),e},i.prototype.displaySoftwareSelectModal=function(t){var i=Object.assign({repositoryType:e.RepositoryType.SOFTWARE,subTitle:n.gettext("Available softwares matching the device type"),mode:n.ModalSelectionMode.MULTI,icon:"c8y-tools",disableSelected:!1,selected:this.softwareList},t),r=this.bsModal.show(V,{ignoreBackdropClick:!0,class:"modal-sm",initialState:i});return t.repositoryEntriesWithVersionsFn$&&(r.content.repositoryEntriesWithVersions$=t.repositoryEntriesWithVersionsFn$(r)),r.content.load.next(),r.content.resultEmitter},i.prototype.emitSoftwareInstall=function(e){this.changes.emit(e.map((function(e){return Object.assign(Object.assign({},e),{action:"install"})})))},i.prototype.emitSoftwareRemoval=function(e){this.changes.emit(e.map((function(e){return Object.assign(Object.assign({},e),{action:"delete"})})))},i}();G.decorators=[{type:t.Component,args:[{selector:"c8y-installed-software",template:'<div class="inner-scroll d-flex d-col">\n <div class="card-header large-padding separator sticky-top">\n <h4 class="card-title" translate>Installed software</h4>\n </div>\n <div class="flex-grow">\n <fieldset *ngIf="deviceSoftwareChangesOperation" class="card-block large-padding bg-gray-lighter">\n <c8y-single-operation [operation]="deviceSoftwareChangesOperation"></c8y-single-operation>\n </fieldset>\n\n <fieldset class="d-contents" [disabled]="deviceSoftwareChangesInProgress">\n \x3c!-- EMPTY STATE --\x3e\n <div class="card-block" *ngIf="softwareList.length === 0">\n <div class="c8y-empty-state text-center m-t-16">\n <h1 class="c8y-icon c8y-icon-tools c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No software installed.</strong> <br />\n <small translate>Click below to install software into this device.</small>\n </p>\n </div>\n </div>\n\n \x3c!-- NOT EMPTY STATE --\x3e\n <ng-container *ngIf="softwareList.length > 0">\n <c8y-device-software-list\n [softwareList]="softwareList"\n [deviceSoftwareChanges]="deviceSoftwareChanges"\n (update)="updateSoftware($event)"\n (remove)="removeSoftware($event)"\n class="d-block p-l-16 p-r-16"\n >\n </c8y-device-software-list>\n </ng-container>\n </fieldset>\n </div>\n\x3c!-- INSTALL SOFTWARE--\x3e\n <div class="card-footer large-padding separator sticky-bottom">\n <button\n class="btn btn-default"\n title="{{ \'Install software\' | translate }}"\n (click)="installSoftware()"\n [disabled]="deviceSoftwareChangesInProgress"\n >\n <i c8yIcon="plus-circle"></i>\n {{ \'Install software\' | translate }}\n </button>\n </div>\n</div>\n'}]}],G.ctorParameters=function(){return[{type:O},{type:c.InventoryService},{type:y.BsModalService}]},G.propDecorators={softwareList:[{type:t.Input}],deviceSoftwareChanges:[{type:t.Input}],deviceSoftwareChangesOperation:[{type:t.Input}],deviceSoftwareChangesInProgress:[{type:t.Input}],deviceTypeQuery:[{type:t.Input}],changes:[{type:t.Output}]};var W=function(){function e(){this.update=new t.EventEmitter,this.remove=new t.EventEmitter}return e.prototype.ngAfterContentInit=function(){this.showUpdate=this.update.observers.length>0,this.showRemove=this.remove.observers.length>0},e.prototype.isSoftwareGoingToBeChanged=function(e){return l.filter(this.deviceSoftwareChanges,e).length>0},e}();W.decorators=[{type:t.Component,args:[{selector:"c8y-device-software-list",template:'<c8y-list-group class="no-border-last">\n <c8y-li\n [ngClass]="{ disabled: isSoftwareGoingToBeChanged(software) }"\n *ngFor="let software of softwareList"\n >\n \x3c!-- SOFTWARE ICON --\x3e\n <c8y-li-icon>\n <i c8yIcon="c8y-tools"></i>\n </c8y-li-icon>\n\n <c8y-li-body class="content-flex-20">\n <div title="{{ software.name }}" class="col-8">\n \x3c!-- SOFTWARE NAME --\x3e\n <p class="text-truncate">{{ software.name }}</p>\n \x3c!-- SOFTWARE VERSION --\x3e\n <p class="text-truncate">\n <span class="text-label-small m-r-4" translate>\n Version\n </span>\n <span title="{{ software.version }}">\n {{ software.version }}\n </span>\n </p>\n </div>\n\n <div *ngIf="showUpdate || showRemove" class="col-4 text-right">\n \x3c!-- UPDATE SOFTWARE --\x3e\n <button\n *ngIf="showUpdate && !isSoftwareGoingToBeChanged(software)"\n class="btn btn-default btn-xs showOnHover"\n (click)="update.emit(software)"\n title="{{ \'Update`software,verb`\' | translate }}"\n translate\n >\n Update\n </button>\n\n \x3c!-- REMOVE SOFTWARE --\x3e\n <button\n *ngIf="showRemove && !isSoftwareGoingToBeChanged(software)"\n title="{{ \'Remove`software`\' | translate }}"\n class="showOnHover btn btn-dot pull-right"\n (click)="remove.emit(software)"\n >\n <i c8yIcon="minus-circle" class="text-danger"></i>\n </button>\n </div>\n </c8y-li-body>\n </c8y-li>\n</c8y-list-group>\n'}]}],W.propDecorators={softwareList:[{type:t.Input}],deviceSoftwareChanges:[{type:t.Input}],update:[{type:t.Output}],remove:[{type:t.Output}]};var q=function(){function e(){this.clear=new t.EventEmitter,this.drop=new t.EventEmitter,this.apply=new t.EventEmitter,this.changes$=new p.BehaviorSubject([]),this.installations$=this.changes$.pipe(d.map((function(e){return e.filter((function(e){return"install"===e.action}))}))),this.removals$=this.changes$.pipe(d.map((function(e){return e.filter((function(e){return"delete"===e.action}))})))}return e.prototype.ngOnChanges=function(e){e.changes&&this.changes$.next(e.changes.currentValue)},e}();q.decorators=[{type:t.Component,args:[{selector:"c8y-device-software-changes",template:'<div class="inner-scroll d-flex d-col">\n <div class="card-header separator large-padding sticky-top">\n <h4 class="card-title" translate>Software changes</h4>\n </div>\n <div class="flex-grow">\n <div class="card-block large-padding"\n *ngIf="(changes$ | async).length === 0; else changesList"\n >\n <div class="c8y-empty-state text-center">\n <h1 class="c8y-icon c8y-icon-device-control c8y-icon-duocolor"></h1>\n <p>\n <strong translate>No software changes.</strong> <br />\n <small translate>Selected actions will be displayed here.</small>\n </p>\n </div>\n </div>\n\n <ng-template #changesList>\n <fieldset class="card-block p-t-0 p-b-0"\n *ngIf="(installations$ | async).length > 0"\n [disabled]="changesInProgress"\n >\n <div class="form-block legend" translate>Installations`software`</div>\n <c8y-device-software-list\n [softwareList]="installations$ | async"\n (remove)="drop.emit($event)"\n ></c8y-device-software-list>\n </fieldset>\n\n <fieldset class="card-block p-t-0 p-b-0"\n *ngIf="(removals$ | async).length > 0"\n [disabled]="changesInProgress"\n >\n <div class="form-block legend" translate>Removals`software`</div>\n <c8y-device-software-list\n [softwareList]="removals$ | async"\n (remove)="drop.emit($event)"\n ></c8y-device-software-list>\n </fieldset>\n </ng-template>\n </div>\n <div\n class="card-footer separator large-padding sticky-bottom"\n *ngIf="(changes$ | async).length > 0"\n >\n <button\n class="btn btn-default"\n (click)="clear.emit()"\n title="{{ \'Clear changes\' | translate }}"\n [disabled]="changesInProgress"\n translate\n >\n Clear`changes`\n </button>\n <button\n class="btn btn-primary"\n [ngClass]="{ \'btn-pending\': changesInProgress }"\n [disabled]="changesInProgress"\n (click)="apply.emit()"\n title="{{ \'Apply changes\' | translate }}"\n translate\n >\n Apply changes\n </button>\n </div>\n</div>\n'}]}],q.propDecorators={changes:[{type:t.Input}],changesInProgress:[{type:t.Input}],clear:[{type:t.Output}],drop:[{type:t.Output}],apply:[{type:t.Output}]};var z=function(){function e(){this.configurationsUpdated=new t.EventEmitter}return e.prototype.updateConfigurations=function(e){this.configurationsUpdated.emit(e)},e.prototype.hasAnySupportedOperation=function(e,t){var n=e.c8y_SupportedOperations;return!!n&&(Array.isArray(t)||(t=[t]),n.some((function(e){return t.includes(e)})))},e}();z.decorators=[{type:t.Injectable}];var Y=function(){function t(e,t,n,i,r){this.route=e,this.alertService=t,this.repositoryService=n,this.deviceConfigurationService=i,this.inventoryService=r,this.reloadingConfig=!1}return t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.load()];case 1:return e.sent(),[2]}}))}))},t.prototype.load=function(){return w(this,void 0,void 0,(function(){return S(this,(function(t){switch(t.label){case 0:return this.device=this.route.snapshot.parent.data.contextData,[4,this.loadDevice()];case 1:return t.sent(),[4,this.loadOperation()];case 2:return t.sent(),this.showTextBasedConfigReload=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.SEND_CONFIG]),this.showTextBasedConfigSave=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.CONFIG]),this.device.c8y_Configuration&&this.device.c8y_Configuration.config&&(this.config=this.device.c8y_Configuration.config),[2]}}))}))},t.prototype.loadOperation=function(){return w(this,void 0,void 0,(function(){var e,t=this;return S(this,(function(n){switch(n.label){case 0:return[4,this.repositoryService.getLastConfigUpdateOperation(this.device.id)];case 1:return null!==(e=n.sent())&&this.repositoryService.observeOperation(e).subscribe((function(e){t.latestOperation=e})),[2]}}))}))},Object.defineProperty(t.prototype,"savingConfig",{get:function(){return!!this.latestOperation&&(this.latestOperation.status===c.OperationStatus.PENDING||this.latestOperation.status===c.OperationStatus.EXECUTING)},enumerable:!1,configurable:!0}),t.prototype.reloadConfiguration=function(){return w(this,void 0,void 0,(function(){var e,t=this;return S(this,(function(n){switch(n.label){case 0:return this.reloadingConfig=!0,[4,this.repositoryService.createTextBasedConfigurationReloadOperation(this.device)];case 1:e=n.sent();try{this.repositoryService.createObservedOperation(e).subscribe((function(e){return t.onOperationReloadSuccess(e)}),(function(e){return t.onOperationReloadError(e)}),(function(){return t.onOperationReloadComplete()}))}catch(e){this.alertService.addServerFailure(e)}return[2]}}))}))},t.prototype.updateConfiguration=function(e){return w(this,void 0,void 0,(function(){var t,n=this;return S(this,(function(i){switch(i.label){case 0:return[4,this.repositoryService.createTextBasedConfigurationUpdateOperation(this.device,e)];case 1:t=i.sent();try{this.repositoryService.createObservedOperation(t).subscribe((function(e){return n.onOperationUpdateSuccess(e)}),(function(e){return n.onOperationUpdateError(e)}),(function(){return n.onOperationUpdateComplete()}))}catch(e){this.alertService.addServerFailure(e)}return[2]}}))}))},t.prototype.onOperationReloadSuccess=function(e){this.latestOperation=e,e.status===c.OperationStatus.PENDING&&this.alertService.success(n.gettext("Configuration will be reloaded."))},t.prototype.onOperationReloadError=function(e){this.latestOperation=e,this.reloadingConfig=!1},t.prototype.onOperationReloadComplete=function(){return w(this,void 0,void 0,(function(){return S(this,(function(e){switch(e.label){case 0:return[4,this.loadDevice()];case 1:return e.sent(),this.config=this.device.c8y_Configuration.config,this.reloadingConfig=!1,[2]}}))}))},t.prototype.onOperationUpdateSuccess=function(e){this.latestOperation=e,e.status===c.OperationStatus.PENDING&&this.alertService.success(n.gettext("Configuration will be updated."))},t.prototype.onOperationUpdateError=function(e){this.latestOperation=e},t.prototype.onOperationUpdateComplete=function(){this.device.c8y_Configuration.config=this.config},t.prototype.loadDevice=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return e=this,[4,this.inventoryService.detail(this.device.id,{withChildren:!1})];case 1:return e.device=t.sent().data,[2]}}))}))},t}();Y.decorators=[{type:t.Component,args:[{selector:"c8y-text-based-configuration",template:'<div class="d-flex d-col fit-h">\n <fieldset *ngIf="latestOperation !== undefined" class="card-block bg-gray-white fit-w">\n <div class="content-flex-50">\n <c8y-single-operation [operation]="latestOperation" class="flex-grow"></c8y-single-operation>\n <div class="flex-item-right d-flex">\n <button\n title="{{ \'Get snapshot from device\' | translate }}"\n type="button"\n class="btn btn-default btn-sm flex-item-v-center m-t-8 m-b-8"\n *ngIf="showTextBasedConfigReload"\n (click)="reloadConfiguration()"\n [disabled]="reloadingConfig || savingConfig"\n >\n <i\n c8yIcon="refresh"\n *ngIf="reloadingConfig"\n class="m-r-4"\n [ngClass]="{ \'icon-spin\': reloadingConfig }"\n ></i>\n <i c8yIcon="download" *ngIf="!reloadingConfig" class="m-r-4"></i>\n\n {{ \'Get snapshot from device\' | translate }}\n </button>\n </div>\n </div>\n </fieldset>\n <div class="flex-grow">\n <textarea\n [(ngModel)]="config"\n class="form-control fit-h p-r-16 p-l-16"\n [disabled]="reloadingConfig || savingConfig"\n c8y-spellcheck="false"\n ></textarea>\n </div>\n <div class="card-footer fit-w separator" *ngIf="showTextBasedConfigSave">\n <button\n type="button"\n (click)="updateConfiguration(config)"\n [disabled]="reloadingConfig || savingConfig"\n class="btn btn-primary"\n [ngClass]="{ \'btn-pending\': savingConfig }"\n >\n <span title="{{ \'Send\' | translate }}" *ngIf="!savingConfig">\n {{ \'Send configuration to device\' | translate }}\n </span>\n <span title="{{ \'Sending…\' | translate }}" *ngIf="savingConfig">\n {{ \'Sending…\' | translate }}\n </span>\n </button>\n </div>\n</div>\n'}]}],Y.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:n.AlertService},{type:O},{type:z},{type:c.InventoryService}]};var Q=function(){function t(e,t,n,i){var r=this;this.route=e,this.deviceConfigurationService=t,this.realtime=n,this.repositoryService=i,this.supportedConfigurations=[],this.showBinaryBasedConfig=!1,this.configSnapshot={},this.reloading=!1,this.deviceConfigurationService.configurationsUpdated.subscribe((function(e){r.updateSnapshots(e)}))}return t.prototype.ngOnInit=function(){this.device=this.route.snapshot.parent.data.contextData,this.device.c8y_SupportedConfigurations&&(this.supportedConfigurations=this.device.c8y_SupportedConfigurations.map((function(e){return{name:e}}))),this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.DOWNLOAD_CONFIG,e.DeviceConfigurationOperation.UPLOAD_CONFIG])&&this.supportedConfigurations.push({name:n.gettext("Legacy configuration snapshot"),isLegacy:!0}),this.supportedConfigurations.length>0&&(this.showBinaryBasedConfig=!0),this.repositorySnapshotsEmptyState={icon:"gears",title:n.gettext("No configurations available."),text:n.gettext("Add configuration to configuration repository")},this.showTextBasedConfig=this.deviceConfigurationService.hasAnySupportedOperation(this.device,[e.DeviceConfigurationOperation.CONFIG,e.DeviceConfigurationOperation.SEND_CONFIG])},t.prototype.onConfigTypeSelected=function(e){return w(this,void 0,void 0,(function(){return S(this,(function(t){return this.configurationType=e.name,this.isLegacy=e.isLegacy,this.updateSnapshots(),[2]}))}))},t.prototype.onRepositoryConfigSelected=function(e){return w(this,void 0,void 0,(function(){var t,n;return S(this,(function(i){switch(i.label){case 0:if(this.repositorySnapshot={id:e.id,time:e.creationTime,name:e.name,binaryUrl:e.url,deviceType:e.deviceType,configurationType:e.configurationType},!e.url)return[3,6];i.label=1;case 1:return i.trys.push([1,5,,6]),[4,this.repositoryService.getBinaryFile(e.url,{allowExternal:!1})];case 2:return(t=i.sent())?(n=this.repositorySnapshot,[4,t.text()]):[3,4];case 3:n.binary=i.sent(),i.label=4;case 4:return[3,6];case 5:return i.sent(),[3,6];case 6:return[2]}}))}))},t.prototype.updateSnapshots=function(e){return w(this,void 0,void 0,(function(){var t,n,i;return S(this,(function(r){switch(r.label){case 0:return this.reloading=!0,this.repositorySnapshot=void 0,t=this,[4,this.repositoryService.getSnapshotsFromRepository(this.device,this.configurationType)];case 1:return t.repositorySnapshots=r.sent(),e?[3,6]:(n=this,this.isLegacy?[4,this.repositoryService.getLegacyConfigSnapshot(this.device)]:[3,3]);case 2:return i=r.sent(),[3,5];case 3:return[4,this.repositoryService.getConfigSnapshot(this.device,this.configurationType)];case 4:i=r.sent(),r.label=5;case 5:n.configSnapshot=i,r.label=6;case 6:return this.showTextBasedConfig?[4,this.textBasedConfigurationComponent.load()]:[3,8];case 7:r.sent(),r.label=8;case 8:return this.reloading=!1,[2]}}))}))},t}();Q.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration",template:'<c8y-action-bar-item [placement]="\'right\'">\n <button class="btn btn-link" title="{{ \'Reload\' | translate }}" (click)="updateSnapshots()">\n <i c8yIcon="refresh" [ngClass]="{ \'icon-spin\': reloading }"></i>\n {{ \'Reload\' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class="card content-fullpage card-has-tabs">\n <tabset>\n <div class="card-header separator" *ngIf="showBinaryBasedConfig && !showTextBasedConfig">\n <h4 class="card-title">{{ \'Configurations\' | translate }}</h4>\n </div>\n <div class="card-header separator" *ngIf="!showBinaryBasedConfig && showTextBasedConfig">\n <h4 class="card-title">{{ \'Text-based configuration\' | translate }}</h4>\n </div>\n <tab heading="{{ \'Configurations\' | translate }}" *ngIf="showBinaryBasedConfig">\n <div class="card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0">\n \x3c!-- DEVICE SUPPORTED CONFIGURATIONS --\x3e\n <div class="card--grid__inner-scroll bg-gray-white">\n <div class="p-l-16 p-r-16">\n <h5 class="legend form-block">\n <span translate>Device-supported configurations</span>\n </h5>\n </div>\n <c8y-device-configuration-list\n [items]="supportedConfigurations"\n [itemIcon]="\'gears\'"\n (configSelected)="onConfigTypeSelected($event)"\n ></c8y-device-configuration-list>\n </div>\n\n \x3c!-- CONFIGURATION PREVIEW --\x3e\n <div class="card--grid__inner-scroll d-flex d-col flex-grow">\n <div class="card-block d-flex d-col flex-grow">\n <h5 class="legend form-block"><span translate>Preview</span></h5>\n\n \x3c!-- EMPTY STATE --\x3e\n <div class="c8y-empty-state text-left" *ngIf="!configurationType">\n <h1 [c8yIcon]="\'file-text\'"></h1>\n <p>\n <strong translate>No configuration selected.</strong><br />\n <small translate>Select a configuration to preview</small>\n </p>\n </div>\n\n \x3c!-- PREVIEW AVAILABLE STATE --\x3e\n <c8y-device-configuration-preview\n *ngIf="configurationType"\n [device]="device"\n [configurationType]="configurationType"\n [configSnapshot]="configSnapshot"\n [canSaveSnapshot]="true"\n [operationToTrigger]="\'c8y_UploadConfigFile\'"\n [actionButtonText]="\'Get snapshot from device\' | translate"\n [actionButtonIcon]="\'download\'"\n [isLegacy]="isLegacy"\n class="d-flex d-col flex-grow"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n\n \x3c!-- AVAILABLE SUPPORTED CONFIGURATIONS --\x3e\n <div class="card--grid__inner-scroll bg-gray-white">\n <div class="p-l-16 p-r-16">\n <h5 class="legend form-block" translate>Available supported configurations</h5>\n </div>\n\n \x3c!-- EMPTY STATE --\x3e\n <div class="c8y-empty-state text-left" *ngIf="!configurationType">\n <h1 [c8yIcon]="\'gears\'"></h1>\n <p>\n <strong translate>No selection</strong><br />\n <small translate\n >Select a configuration from the device-supported configuration list</small\n >\n </p>\n </div>\n <div class="p-r-16" *ngIf="configurationType">\n <c8y-device-configuration-list\n [items]="repositorySnapshots"\n [itemIcon]="\'file-text\'"\n [emptyState]="repositorySnapshotsEmptyState"\n [isFilterEnabled]="true"\n (configSelected)="onRepositoryConfigSelected($event)"\n ></c8y-device-configuration-list>\n </div>\n </div>\n\n \x3c!-- CONFIGURATION PREVIEW --\x3e\n <div class="card--grid__inner-scroll d-flex d-col flex-grow">\n <div class="card-block flex-grow d-flex d-col">\n <h5 class="legend form-block" translate>Preview</h5>\n\n \x3c!-- EMPTY STATE --\x3e\n\n <div class="c8y-empty-state text-left" *ngIf="!repositorySnapshot">\n <h1 [c8yIcon]="\'file-text\'"></h1>\n <p>\n <strong translate>No configuration selected.</strong><br />\n <small *ngIf="!configurationType; else noSnapshot" translate\n >Select a configuration to preview</small\n >\n <ng-template #noSnapshot>\n <small translate>Select the configuration you want to preview</small>\n </ng-template>\n </p>\n </div>\n\n \x3c!-- CONFIGURATION SELECTED STATE --\x3e\n <c8y-device-configuration-preview\n *ngIf="repositorySnapshot"\n [device]="device"\n [configurationType]="configurationType"\n [configSnapshot]="repositorySnapshot"\n [operationToTrigger]="\'c8y_DownloadConfigFile\'"\n [actionButtonText]="\'Send configuration to device\' | translate"\n [actionButtonIcon]="\'upload\'"\n [isLegacy]="isLegacy"\n class="d-flex d-col flex-grow"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n </div>\n </tab>\n <tab heading="{{ \'Text-based configuration\' | translate }}" *ngIf="showTextBasedConfig">\n <c8y-text-based-configuration></c8y-text-based-configuration>\n </tab>\n </tabset>\n</div>\n'}]}],Q.ctorParameters=function(){return[{type:u.ActivatedRoute},{type:z},{type:c.Realtime},{type:O}]},Q.propDecorators={textBasedConfigurationComponent:[{type:t.ViewChild,args:[Y]}]};var K=function(){};K.decorators=[{type:t.Component,args:[{selector:"c8y-source-code-preview",template:'<textarea\n [disabled]="isDisabled"\n class="text-monospace form-control no-resize flex-grow"\n rows="4"\n >{{ text }}</textarea\n>\n'}]}],K.propDecorators={isDisabled:[{type:t.Input}],text:[{type:t.Input}]};var H=function(){function t(e,t,n){var i=this;this.modal=e,this.alertService=t,this.repositoryService=n,this.result=new Promise((function(e,t){i._save=e,i._cancel=t}))}return t.prototype.save=function(){return w(this,void 0,void 0,(function(){var t,i;return S(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),t={selected:{configurationType:this.configSnapshot.configurationType},version:this.configSnapshot.name,deviceType:this.configSnapshot.deviceType,description:this.configSnapshot.description,binary:{file:new File([this.configSnapshot.binary],this.configSnapshot.name)}},[4,this.repositoryService.save(t,e.RepositoryType.CONFIGURATION)];case 1:return r.sent(),this.alertService.success(n.gettext("Configuration saved.")),this._save(),[3,3];case 2:return i=r.sent(),this.alertService.addServerFailure(i),[3,3];case 3:return[2]}}))}))},t.prototype.close=function(){this._cancel(),this.modal.hide()},t}();H.decorators=[{type:t.Component,args:[{selector:"c8y-save-config-to-configuration-repository",template:'<div class="modal-header bg-primary text-center text-white">\n <div style="font-size: 62px;">\n <span c8yIcon="gears"></span>\n </div>\n <h4 class="text-uppercase" translate>\n Save configuration\n </h4>\n</div>\n<div class="modal-body">\n <form #saveConfigurationSnapshot="ngForm" class="p-t-24">\n <c8y-form-group>\n <label translate for="name">Name</label>\n <input\n id="name"\n type="text"\n class="form-control"\n autocomplete="off"\n name="name"\n [(ngModel)]="configSnapshot.name"\n required\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="deviceType">Device type</label>\n <input\n id="deviceType"\n class="form-control"\n rows="6"\n name="deviceType"\n [(ngModel)]="configSnapshot.deviceType"\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="description">Description</label>\n <input\n type="text"\n id="description"\n class="form-control"\n maxlength="254"\n autocomplete="off"\n name="description"\n [(ngModel)]="configSnapshot.description"\n />\n </c8y-form-group>\n <c8y-form-group>\n <label translate for="configurationType">Configuration type</label>\n <input\n id="configurationType"\n class="form-control"\n rows="6"\n name="configurationType"\n [(ngModel)]="configSnapshot.configurationType"\n />\n </c8y-form-group>\n </form>\n</div>\n<div class="modal-footer">\n <button title="{{ \'Cancel\' | translate }}" class="btn btn-default" (click)="close()" translate>\n Cancel\n </button>\n\n <button\n title="{{ \'Save configuration to repository\' | translate }}"\n class="btn btn-primary"\n (click)="save()"\n [disabled]="saveConfigurationSnapshot.form.invalid"\n translate\n >\n Save\n </button>\n</div>\n'}]}],H.ctorParameters=function(){return[{type:y.BsModalRef},{type:n.AlertService},{type:O}]};var X=function(){function t(t,n,i,r,a,o,s,c,l){this.deviceConfigurationService=t,this.realtime=n,this.operationRealtime=i,this.bsModal=r,this.user=a,this.appState=o,this.repositoryService=s,this.operationService=c,this.alertService=l,this.isLegacy=!1,this.canCallAction=!0,this.deviceConfigurationOperation=e.DeviceConfigurationOperation}return Object.defineProperty(t.prototype,"configurationType",{get:function(){return this._configurationType},set:function(e){this._configurationType=e,this.setOperation(e)},enumerable:!1,configurable:!0}),t.prototype.ngOnInit=function(){return w(this,void 0,void 0,(function(){var e=this;return S(this,(function(t){return this.setOperation(this._configurationType),this.operationsSubscription=this.operationRealtime.onAll$(this.device.id).pipe(d.map((function(e){return e.data}))).subscribe((function(t){e.updatePreview(t)})),this.isLegacy&&(this.canCallAction=this.deviceConfigurationService.hasAnySupportedOperation(this.device,this.operationToTrigger)),[2]}))}))},t.prototype.setOperation=function(e){return w(this,void 0,void 0,(function(){var t,n,i=this;return S(this,(function(r){switch(r.label){case 0:return[4,this.repositoryService.getConfigFileOperationList(this.device.id,this.operationToTrigger)];case 1:return t=r.sent(),n=this.isLegacy?t.find((function(e){return e[i.operationToTrigger]&&!e[i.operationToTrigger].type})):t.find((function(t){return t[i.operationToTrigger].type===e})),this.operation=n&&n.status!==c.OperationStatus.SUCCESSFUL?n:void 0,[2]}}))}))},t.prototype.createDeviceOperation=function(){return w(this,void 0,void 0,(function(){var t,n,i;return S(this,(function(r){switch(r.label){case 0:this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG&&(t=this.repositoryService.getDownloadConfigurationFileOperation(this.device,this._configurationType,this.configSnapshot,this.isLegacy)),this.operationToTrigger===e.DeviceConfigurationOperation.UPLOAD_CONFIG&&(t=this.repositoryService.getUploadConfigurationFileOperation(this.device,this._configurationType,this.isLegacy)),r.label=1;case 1:return r.trys.push([1,3,,4]),n=this,[4,this.operationService.create(t)];case 2:return n.operation=r.sent().data,[3,4];case 3:return i=r.sent(),this.alertService.addServerFailure(i),[3,4];case 4:return[2]}}))}))},t.prototype.showOperation=function(){return this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG?!!this.operation:this.operation&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING,c.OperationStatus.FAILED].includes(this.operation.status)},t.prototype.showBinary=function(){return this.operationToTrigger===e.DeviceConfigurationOperation.DOWNLOAD_CONFIG||!this.showOperation()},t.prototype.isCreateOperationDisabled=function(){return this.operation&&[c.OperationStatus.PENDING,c.OperationStatus.EXECUTING].includes(this.operation.status)},t.prototype.updatePreview=function(e){e&&e[this.operationToTrigger]&&(this.isLegacy||e[this.operationToTrigger].type&&e[this.operationToTrigger].type===this.configurationType)&&(this.operation=e,this.updateSnapshotsOnConfigUpload(e))},t.prototype.download=function(){var e=new Blob([this.configSnapshot.binary],{type:this.configSnapshot.binaryType}),t=this.configSnapshot.name;switch(this.configSnapshot.binaryType){case"text/csv":case"application/csv":t=t.concat(".csv");break;case"text/yaml":case"application/x-yaml":t=t.concat(".yaml");break;case"application/json":t=t.concat(".json")}g.saveAs(e,t)},t.prototype.saveToRepository=function(){return w(this,void 0,void 0,(function(){var e,t;return S(this,(function(n){switch(n.label){case 0:e={configSnapshot:l.cloneDeep(this.configSnapshot)},t=this.bsModal.show(H,{class:"modal-sm",initialState:e,ignoreBackdropClick:!0}).content,n.label=1;case 1:return n.trys.push([1,3,,4]),[4,t.result];case 2:return n.sent(),this.deviceConfigurationService.updateConfigurations(!0),t.close(),[3,4];case 3:return n.sent(),[3,4];case 4:return[2]}}))}))},t.prototype.hasPermission=function(){return this.user.hasAnyRole(this.appState.currentUser.value,["ROLE_INVENTORY_ADMIN","ROLE_INVENTORY_CREATE"])},t.prototype.ngOnDestroy=function(){this.operationsSubscription&&this.operationsSubscription.unsubscribe()},t.prototype.updateSnapshotsOnConfigUpload=function(t){return w(this,void 0,void 0,(function(){return S(this,(function(n){return t[e.DeviceConfigurationOperation.UPLOAD_CONFIG]&&t.status===c.OperationStatus.SUCCESSFUL&&this.deviceConfigurationService.updateConfigurations(),[2]}))}))},t}();X.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration-preview",template:'<div class="content-flex-55 p-b-16">\n <div class="col-7 p-t-4">\n <p>\n <span class="text-label-small text-uppercase m-r-4" translate>Configuration</span>\n <span *ngIf="configSnapshot?.name; else emptyText">\n <strong>{{ configSnapshot.name }}</strong>\n </span>\n <ng-template #emptyText> --- </ng-template>\n </p>\n <p>\n <span class="text-label-small text-uppercase m-r-4" translate>Last updated</span>\n <small *ngIf="configSnapshot?.time; else emptyDate">\n {{ configSnapshot.time | c8yDate }}\n </small>\n <ng-template #emptyDate> --- </ng-template>\n </p>\n </div>\n <div class="col-5">\n <button\n class="btn btn-default btn-sm pull-right"\n type="button"\n title="{{ actionButtonText | translate }}"\n (click)="createDeviceOperation()"\n [disabled]="isCreateOperationDisabled()"\n *ngIf="canCallAction"\n >\n <i [c8yIcon]="actionButtonIcon"></i> {{ actionButtonText | translate }}\n </button>\n </div>\n</div>\n<div class="c8y-empty-state text-left" *ngIf="!configSnapshot?.binary && showBinary()">\n <h1 [c8yIcon]="\'file-image-o\'"></h1>\n <p>\n <strong translate>No preview available.</strong><br />\n <small *ngIf="configSnapshot?.binary !== \'\'; else emptyFile" translate\n >The file is not available.</small\n >\n <ng-template #emptyFile>\n <small translate>The file is empty.</small>\n </ng-template>\n </p>\n</div>\n<div *ngIf="configSnapshot?.binary && showBinary()" class="flex-grow d-flex d-col">\n <c8y-source-code-preview\n [text]="configSnapshot.binary"\n [isDisabled]="true"\n class="d-contents"\n ></c8y-source-code-preview>\n <div *ngIf="canSaveSnapshot" class="p-t-16">\n <button\n type="button"\n class="btn btn-primary btn-sm pull-right m-l-8"\n (click)="download()"\n translate\n >\n Download\n </button>\n <button\n *ngIf="hasPermission()"\n type="button"\n class="btn btn-default btn-sm pull-right"\n (click)="saveToRepository()"\n translate\n >\n Save to repository\n </button>\n </div>\n</div>\n<div *ngIf="showOperation()">\n <c8y-single-operation [operation]="operation"></c8y-single-operation>\n</div>\n'}]}],X.ctorParameters=function(){return[{type:z},{type:c.Realtime},{type:n.OperationRealtimeService},{type:y.BsModalService},{type:c.UserService},{type:n.AppStateService},{type:O},{type:c.OperationService},{type:n.AlertService}]},X.propDecorators={device:[{type:t.Input}],configurationType:[{type:t.Input}],configSnapshot:[{type:t.Input}],canSaveSnapshot:[{type:t.Input}],actionButtonText:[{type:t.Input}],actionButtonIcon:[{type:t.Input}],isLegacy:[{type:t.Input}],operationToTrigger:[{type:t.Input}]};var Z=function(){function e(){}return e.prototype.transform=function(e,t){var n=this;return 0===t.trim().length?e:e.filter((function(e){return n.filterContainString(e.name,t)||n.filterContainString(e.deviceType,t)}))},e.prototype.filterContainString=function(e,t){var n=t.toLowerCase().trim();return e&&e.toLowerCase().indexOf(n)>-1},e}();Z.decorators=[{type:t.Pipe,args:[{name:"configurationFilterPipe"}]}];var J=function(){function t(e){this.deviceConfigurationService=e}return t.prototype.canActivate=function(t,n){var i=t.data.contextData||t.parent.data.contextData;return!!i&&(i.c8y_SupportedConfigurations&&i.c8y_SupportedConfigurations.length>0||this.deviceConfigurationService.hasAnySupportedOperation(i,[e.DeviceConfigurationOperation.DOWNLOAD_CONFIG,e.DeviceConfigurationOperation.UPLOAD_CONFIG,e.DeviceConfigurationOperation.CONFIG,e.DeviceConfigurationOperation.SEND_CONFIG]))},t}();J.decorators=[{type:t.Injectable}],J.ctorParameters=function(){return[{type:z}]};var ee,te=function(){function e(){this.configSelected=new t.EventEmitter,this.filterTerm=""}return e.prototype.showConfigurationTypePreview=function(e){this.selectedConfig=e,this.configSelected.emit(e)},e.prototype.updatePipe=function(e){this.filterTerm=e},e}();te.decorators=[{type:t.Component,args:[{selector:"c8y-device-configuration-list",template:'<div class="p-l-16 m-b-8" *ngIf="isFilterEnabled">\n <c8y-filter [icon]="\'search\'" (onSearch)="updatePipe($event)"></c8y-filter>\n</div>\n\n\x3c!-- EMPTY STATE --\x3e\n<div class="c8y-empty-state text-left" *ngIf="items?.length === 0">\n <h1 [c8yIcon]="emptyState.icon"></h1>\n <p>\n <strong>{{ emptyState.title | translate }}</strong\n ><br />\n <small>{{ emptyState.text | translate }}</small>\n </p>\n</div>\n\n\x3c!-- CONFIGURATIONS AVAILABLE --\x3e\n<div class="c8y-nav-stacked">\n <div\n class="c8y-stacked-item flex-row"\n [class.active]="config === selectedConfig"\n *ngFor="let config of items | configurationFilterPipe: filterTerm"\n (click)="showConfigurationTypePreview(config)"\n >\n <div class="list-item-icon">\n <i [c8yIcon]="itemIcon"></i>\n </div>\n <div class="list-item-body text-truncate">\n <div class="d-flex">\n <span class="text-truncate" title="{{ config.name }}">{{ config.name }}</span>\n <span class="text-label-small flex-item-right flex-item-middle">{{ config.deviceType }}</span>\n </div>\n </div>\n </div>\n</div>\n\n\x3c!-- for Carlos: config.configurationType to differentiate whether a config matches configuration type. --\x3e\n'}]}],te.propDecorators={items:[{type:t.Input}],itemIcon:[{type:t.Input}],emptyState:[{type:t.Input}],isFilterEnabled:[{type:t.Input}],configSelected:[{type:t.Output}]},function(e){e[e.DOWNLOAD=0]="DOWNLOAD",e[e.LINK=1]="LINK",e[e.TEXTONLY=2]="TEXTONLY"}(ee||(ee={}));var ne=function(){function e(e,t){this.repositoryService=e,this.inventoryBinaryService=t,this.linkRenderType=ee}return e.prototype.getBinaryName$=function(e){return this.repositoryService.getBinaryName$(e)},e.prototype.determineBehavior=function(){return this.inventoryBinaryService.getIdFromUrl(this.url)?ee.DOWNLOAD:this.url.match(/\/\//g)?ee.LINK:ee.TEXTONLY},e.prototype.downloadFile=function(){return w(this,void 0,void 0,(function(){var e;return S(this,(function(t){switch(t.label){case 0:return[4,this.repositoryService.getBinaryFile(this.url,{allowExternal:!1})];case 1:return e=t.sent(),h.saveAs(e),[2]}}))}))},e}();ne.decorators=[{type:t.Component,args:[{selector:"c8y-file-download",template:'<a\n *ngIf="determineBehavior() === linkRenderType.LINK"\n href="{{ url }}"\n class="pointer"\n target="_blank"\n rel="noopener noreferrer"\n>\n {{ getBinaryName$(url) | async }}\n</a>\n\n<span *ngIf="determineBehavior() === linkRenderType.TEXTONLY">{{ getBinaryName$(url) | async }}</span>\n\n<a *ngIf="determineBehavior() === linkRenderType.DOWNLOAD" class="pointer" (click)="downloadFile()">\n {{getBinaryName$(url) | async}}\n</a>\n'}]}],ne.ctorParameters=function(){return[{type:O},{type:c.InventoryBinaryService}]},ne.propDecorators={url:[{type:t.Input}]},b([n.memoize()],ne.prototype,"getBinaryName$",null),b([n.memoize()],ne.prototype,"determineBehavior",null);var ie=[{path:"firmware",component:R},{path:"firmware/:id",component:_},{context:n.ViewContext.Device,path:"firmware",component:N,label:n.gettext("Firmware"),icon:"c8y-firmware",priority:500,canActivate:[L]},{path:"software",component:A},{path:"software/:id",component:B},{context:n.ViewContext.Device,path:"software",component:U,label:n.gettext("Software"),icon:"c8y-tools",priority:499,canActivate:[j]},{path:"configuration",component:M},{context:n.ViewContext.Device,path:"device-configuration",component:Q,label:n.gettext("Configuration"),icon:"gears",priority:600,canActivate:[J]}],re=function(){};re.decorators=[{type:t.NgModule,args:[{imports:[n.CoreModule,n.FormsModule,s.SingleOperationDetailsModule,i.BsDropdownModule.forRoot(),a.TooltipModule,o.PopoverModule,r.TabsModule.forRoot()],exports:[],declarations:[R,_,$,E,A,B,D,N,U,G,V,W,q,M,P,Q,te,K,X,Z,H,Y,ne],entryComponents:[R,_,$,E,A,B,D,N,U,W,V,q,M,P,Q,H,Y],providers:[O,n.OperationRealtimeService,z,L,j,J,{provide:n.HOOK_NAVIGATOR_NODES,useClass:k,multi:!0},{provide:n.HOOK_ONCE_ROUTE,useValue:ie,multi:!0}]}]}],e.AddFirmwareModalComponent=$,e.AddFirmwarePatchModalComponent=E,e.AddSoftwareModalComponent=D,e.ConfigurationDetailComponent=P,e.ConfigurationFilterPipe=Z,e.ConfigurationListComponent=M,e.ConfigurationPreviewComponent=X,e.DeviceConfigurationComponent=Q,e.DeviceConfigurationGuard=J,e.DeviceConfigurationListComponent=te,e.DeviceConfigurationService=z,e.DeviceSoftwareChangesComponent=q,e.DeviceSoftwareListComponent=W,e.FirmwareDetailsComponent=_,e.FirmwareDeviceTabComponent=N,e.FirmwareDeviceTabGuard=L,e.FirmwareListComponent=R,e.InstalledSoftwareComponent=G,e.REPOSITORY_BINARY_TYPES=T,e.RepositoryModule=re,e.RepositoryNavigationFactory=k,e.RepositorySelectModalComponent=V,e.RepositoryService=O,e.SaveToRepositoryComponent=H,e.SoftwareDetailsComponent=B,e.SoftwareDeviceTabComponent=U,e.SoftwareDeviceTabGuard=j,e.SoftwareListComponent=A,e.SourceCodePreviewComponent=K,e.TextBasedConfigurationComponent=Y,e.ɵ0=ie,e.ɵa=ne,Object.defineProperty(e,"__esModule",{value:!0})}));
|
|
16
16
|
//# sourceMappingURL=c8y-ngx-components-repository.umd.min.js.map
|