UNPKG

@momsfriendlydevco/angular-ui-history

Version:
1 lines 32.5 kB
"use strict";angular.module("angular-ui-history",["angular-bs-tooltip","ngQuill","ui.gravatar"]).factory("$debounce",["$timeout",function(l){return function(o,i,s){i=angular.isUndefined(i)?0:i,s=!!angular.isUndefined(s)||s;var a=0;return function(){var t,n=this,e=arguments,r=(t=++a,function(){if(t===a)return o.apply(n,e)});return l(r,i,s)}}}]).provider("uiHistory",function(){this.defaults={},this.$get=function(){return this}}).component("uiHistory",{bindings:{allowPost:"<?",allowDelete:"<?",allowUpload:"<?",allowUploadList:"<?",buttons:"<?",display:"<?",posts:"<?",queryUrl:"<?",postUrl:"<?",deleteUrl:"<?",templates:"<?",onError:"&?",onLoadingStart:"&?",onLoadingStop:"&?",onQuery:"&?",onUpload:"&?",onUploadStart:"&?",onUploadProgress:"&?",onUploadEnd:"&?",tags:"<?",userAvatar:"@?",baseUrlImage:"<?",mentionUrl:"<?"},template:'\n\t\t<div class="ui-history">\n\t\t\t\x3c!-- Modal: Upload list {{{ --\x3e\n\t\t\t<div class="modal fade angular-ui-history-modal-uploadList">\n\t\t\t\t<div ng-if="$ctrl.showFilesModal" class="modal-dialog">\n\t\t\t\t\t<div class="modal-content">\n\t\t\t\t\t\t<div class="modal-header">\n\t\t\t\t\t\t\t<a class="close" data-dismiss="modal"><i class="fa fa-times"></i></a>\n\t\t\t\t\t\t\t<h4 class="modal-title">Upload List</h4>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class="modal-body">\n\t\t\t\t\t\t\t<ui-history-files\n\t\t\t\t\t\t\t\tallow-upload="$ctrl.allowUpload"\n\t\t\t\t\t\t\t\tquery-url="$ctrl.queryUrl"\n\t\t\t\t\t\t\t\tpost-url="$ctrl.postUrl"\n\t\t\t\t\t\t\t\ton-error="$ctrl.onError"\n\t\t\t\t\t\t\t\ton-loading-start="$ctrl.onLoadingStart"\n\t\t\t\t\t\t\t\ton-loading-stop="$ctrl.onLoadingStop"\n\t\t\t\t\t\t\t\ton-query="$ctrl.onQuery"\n\t\t\t\t\t\t\t\ton-upload="$ctrl.onUpload"\n\t\t\t\t\t\t\t></ui-history-files>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t<ui-history-upload\n\t\t\t\tquery-url="$ctrl.queryUrl"\n\t\t\t\tpost-url="$ctrl.postUrl"\n\t\t\t\ton-error="$ctrl.onError"\n\t\t\t\ton-upload="$ctrl.onUpload"\n\t\t\t\ton-upload-start="$ctrl.onUploadStart"\n\t\t\t\ton-upload-progress="$ctrl.onUploadProgress"\n\t\t\t\ton-upload-end="$ctrl.onUploadEnd"\n\t\t\t\ttags="$ctrl.tags"\n\t\t\t></ui-history-upload>\n\n\t\t\t\x3c!-- Header editor (if display=\'recentFirst\') {{{ --\x3e\n\t\t\t<div ng-if="$ctrl.allowPost && $ctrl.display == \'recentFirst\'">\n\t\t\t\t<div ng-show="$ctrl.isPosting" class="text-center">\n\t\t\t\t\t<h3><i class="fa fa-spinner fa-spin"></i> Posting...</h3>\n\t\t\t\t</div>\n\t\t\t\t<div ng-show="!$ctrl.isPosting">\n\t\t\t\t\t<ui-history-editor\n\t\t\t\t\t\tbuttons="$ctrl.buttons"\n\t\t\t\t\t\ttemplates="$ctrl.templates"\n\t\t\t\t\t\ton-post="$ctrl.makePost(body, tags, mentions)"\n\t\t\t\t\t\ttags="$ctrl.tags"\n\t\t\t\t\t\tbase-url-image="$ctrl.baseUrlImage"\n\t\t\t\t\t\tmention-url="$ctrl.mentionUrl"\n\t\t\t\t\t></ui-history-editor>\n\t\t\t\t</div>\n\t\t\t\t<hr/>\n\t\t\t</div>\n\t\t\t\x3c!-- }}} --\x3e\n\t\t\t<div ng-repeat="post in $ctrl.posts | orderBy:\'date\':$ctrl.display==\'recentFirst\' track by (post.date + post._id)" ng-switch="post.type" class="ui-history-item">\n\t\t\t\t<div class="ui-history-meta">\n\t\t\t\t\t<div ng-if="$ctrl.allowDelete" class="ui-history-delete-post" tooltip="Delete" ng-click="$ctrl.deletePost(post._id)"><i class="fa fa-trash-o" aria-hidden="true"></i></div>\n\t\t\t\t\t<div ng-if="post.tags && post.tags.length" class="ui-history-tags">\n\t\t\t\t\t\t<span ng-repeat="tag in post.tags" class="ui-history-tag">\n\t\t\t\t\t\t\t{{tag}}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="ui-history-timestamp" tooltip="{{post.date | date:\'medium\'}}">\n\t\t\t\t\t\t{{post.date | uiHistoryDate}}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- type=user.change {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.change" class="ui-history-user-change">\n\t\t\t\t\t<div class="ui-history-user-change-user">\n\t\t\t\t\t\t<user-history-avatar user="post.user" user-avatar="{{$ctrl.userAvatar}}" default-image="{{$ctrl.gravatarDefault}}"></user-history-avatar>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if="post.field" class="ui-history-user-change-main">\n\t\t\t\t\t\tChanged\n\t\t\t\t\t\t{{post.field}}\n\t\t\t\t\t\t<em>{{post.from}}</em>\n\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t<em>{{post.to}}</em>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if="post.fields" class="ui-history-user-change-main">\n\t\t\t\t\t\tChanges:\n\t\t\t\t\t\t<div ng-repeat="(field, change) in post.fields track by field">\n\t\t\t\t\t\t\t{{field}}\n\t\t\t\t\t\t\t<em>{{change.from}}</em>\n\t\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t\t<em>{{change.to}}</em>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type=user.comment {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.comment" class="ui-history-user-comment">\n\t\t\t\t\t<div class="ui-history-user-comment-user">\n\t\t\t\t\t\t<user-history-avatar user="post.user" user-avatar="{{$ctrl.userAvatar}}" default-image="{{$ctrl.gravatarDefault}}"></user-history-avatar>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="ui-history-user-comment-main">\n\t\t\t\t\t\t<div ng-if="post.user.company" class="ui-history-company">\n\t\t\t\t\t\t\t{{post.user.company}}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div ng-if="post.title" class="ui-history-user-comment-header">{{post.title}}</div>\n\t\t\t\t\t\t<div class="ui-history-user-comment-body" ng-bind-html="post.body"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type=user.upload {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.upload" class="ui-history-user-upload">\n\t\t\t\t\t<div class="ui-history-user-upload-user">\n\t\t\t\t\t\t<user-history-avatar user="post.user" user-avatar="{{$ctrl.userAvatar}}" default-image="{{$ctrl.gravatarDefault}}"></user-history-avatar>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="ui-history-user-upload-main">\n\t\t\t\t\t\t<div style="margin-bottom: 10px">Attached files:</div>\n\t\t\t\t\t\t<ul class="list-group">\n\t\t\t\t\t\t\t<a ng-if="post.filename" ng-href="{{post.url}}" target="_blank" class="list-group-item">\n\t\t\t\t\t\t\t\t<div ng-if="post.size" class="pull-right">{{post.size}}</div>\n\t\t\t\t\t\t\t\t<i ng-if="post.icon" class="{{post.icon}}"></i>\n\t\t\t\t\t\t\t\t{{post.filename || \'Unknown file\'}}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<a ng-if="post.files" ng-repeat="file in post.files track by file.filename" ng-href="{{file.url}}" target="_blank" class="list-group-item">\n\t\t\t\t\t\t\t\t<div ng-if="file.size" class="pull-right">{{file.size}}</div>\n\t\t\t\t\t\t\t\t<i ng-if="file.icon" class="{{file.icon}}"></i>\n\t\t\t\t\t\t\t\t{{file.filename || \'Unknown file\'}}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type=user.status {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.status" class="ui-history-user-status">\n\t\t\t\t\t<div class="ui-history-user-status-user">\n\t\t\t\t\t\t<user-history-avatar user="post.user" user-avatar="{{$ctrl.userAvatar}}" default-image="{{$ctrl.gravatarDefault}}"></user-history-avatar>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="ui-history-user-status-main" ng-bind-html="post.body"></div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type=system.change {{{ --\x3e\n\t\t\t\t<div ng-switch-when="system.change" class="ui-history-system-change">\n\t\t\t\t\t<div ng-if="post.field">\n\t\t\t\t\t\tChanged\n\t\t\t\t\t\t{{post.field}}\n\t\t\t\t\t\t<em>{{post.from}}</em>\n\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t<em>{{post.to}}</em>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if="post.fields">\n\t\t\t\t\t\tChanges:\n\t\t\t\t\t\t<div ng-repeat="(field, change) in post.fields track by field">\n\t\t\t\t\t\t\t{{field}}\n\t\t\t\t\t\t\t<em>{{change.from}}</em>\n\t\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t\t<em>{{change.to}}</em>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type=system.status {{{ --\x3e\n\t\t\t\t<div ng-switch-when="system.status" class="ui-history-system-status" ng-bind-html="post.body"></div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\x3c!-- type unknown {{{ --\x3e\n\t\t\t\t<div ng-switch-default class="ui-history-unknown">\n\t\t\t\t\tUnknown history type: [{{post.type}}]\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t</div>\n\t\t\t<div ng-if="!$ctrl.posts.length" class="text-muted text-center">No history to display</div>\n\t\t\t\x3c!-- Footer editor (if !display || display=\'oldestFirst\') {{{ --\x3e\n\t\t\t<div ng-if="$ctrl.allowPost && (!$ctrl.display || $ctrl.display == \'oldestFirst\')">\n\t\t\t\t<hr/>\n\t\t\t\t<div ng-show="$ctrl.isPosting" class="text-center">\n\t\t\t\t\t<h3><i class="fa fa-spinner fa-spin"></i> Posting...</h3>\n\t\t\t\t</div>\n\t\t\t\t<div ng-show="!$ctrl.isPosting">\n\t\t\t\t\t<ui-history-editor\n\t\t\t\t\t\tbuttons="$ctrl.buttons"\n\t\t\t\t\t\ttemplates="$ctrl.templates"\n\t\t\t\t\t\ton-post="$ctrl.makePost(body, tags, mentions)"\n\t\t\t\t\t\tbase-url-image="$ctrl.baseUrlImage"\n\t\t\t\t\t\tmention-url="$ctrl.mentionUrl"\n\t\t\t\t\t></ui-history-editor>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t\x3c!-- }}} --\x3e\n\t\t</div>\n\t',controller:["$element","$http","$q","$rootScope","$sce","$scope","$timeout","uiHistory",function(t,o,i,s,n,e,r,a){var l=this;l.posts,l.isLoading=!1,l.refresh=function(){if(!(0<arguments.length&&void 0!==arguments[0]&&arguments[0])&&l.posts)return i.resolve();i.resolve().then(function(){return l.isLoading=!0}).then(function(){if(angular.isFunction(l.onLoadingStart))return l.onLoadingStart()}).then(function(){if(angular.isString(l.queryUrl)||angular.isFunction(l.queryUrl)){var n=angular.isString(l.queryUrl)?l.queryUrl:l.queryUrl(l);if(!n)throw new Error("Resovled URL is empty");return o.get(n).then(function(t){if(angular.isArray(t.data))return t.data;throw new Error('Expected history feed at URL "'.concat(n,'" to be an array but got something else'))})}if(angular.isArray(l.posts))return l.posts;throw new Error("Cannot refresh posts - neither queryUrl (func / array) or posts (array) are specified")}).then(function(t){l.posts=t.map(function(t){return"string"!=typeof t.body||"user.comment"!=t.type&&"user.status"!=t.type&&"system.status"!=t.type||(t.body=n.trustAsHtml(t.body)),t})}).then(function(){var t;l.onQuery&&(t=l.onQuery({posts:l.posts}),angular.isArray(t)&&(l.posts=t))}).catch(function(t){angular.isFunction(l.onError)&&l.onError({error:t})}).finally(function(){return l.isLoading=!1}).finally(function(){if(angular.isFunction(l.onLoadingStop))return l.onLoadingStop()})},e.$on("angular-ui-history.refresh",function(){return l.refresh(!0)}),l.isPosting=!1,l.makePost=function(t,n,e){if(!l.allowPost)throw new Error("Posting not allowed");if(t){var r=angular.isString(l.postUrl)?l.postUrl:angular.isFunction(l.postUrl)?l.postUrl(l):angular.isString(l.queryUrl)?l.queryUrl:angular.isFunction(l.queryUrl)?l.queryUrl(l):void 0;if(!r)throw new Error("Resolved POST URL is empty");return i.resolve().then(function(){return l.isPosting=!0}).then(function(){return o.post(r,{body:t,tags:n})}).then(function(){return l.refresh(!0)}).then(function(){return s.$broadcast("angular-ui-history.posted",t,e)}).catch(function(t){l.onError&&l.onError({error:t})}).finally(function(){return l.isPosting=!1})}s.$broadcast("angular-ui-history.empty-post")},l.isDeleting=!1,l.deletePost=function(t){if(!l.allowDelete)throw new Error("Deleting not allowed");if(t){var n=angular.isString(l.deleteUrl)?l.deleteUrl:angular.isFunction(l.deleteUrl)?l.deleteUrl(l):void 0;if(!n)throw new Error("Resolved DELETE URL is empty");return i.resolve().then(function(){return l.isDeleting=!0}).then(function(){return o.delete("".concat(n,"/").concat(t))}).then(function(){return l.refresh(!0)}).then(function(){return s.$broadcast("angular-ui-history.deleted",t)}).catch(function(t){l.onError&&l.onError({error:t})}).finally(function(){return l.isDeleting=!1})}},e.$on("angular-ui-history.button.upload",function(){return l.selectFiles()}),l.selectFiles=function(){return t.find("input[type=file]").click()},l.showFilesModal=!1,e.$on("angular-ui-history.button.uploadList",function(){l.showFilesModal=!0,t.find(".angular-ui-history-modal-uploadList").modal("show").one("hidden.bs.modal",function(){return e.$apply(function(){return l.showFilesModal=!0})})}),l.$onInit=function(){for(var t in a.defaults)void 0===l[t]&&(l[t]=a.defaults[t]);l.buttons||(l.buttons=[],l.allowUpload&&(void 0!==l.allowUploadList&&!l.allowUploadList||l.buttons.push({title:"File list",icon:"fa fa-folder-o",action:"uploadList"}),l.buttons.push({title:"Upload files...",icon:"fa fa-file",action:"upload"}))),e.$watch("$ctrl.queryUrl",function(){return l.refresh(!0)})}}]}).component("uiHistoryEditor",{bindings:{buttons:"<",templates:"<",onPost:"&",tags:"<?",baseUrlImage:"<?",mentionUrl:"<?"},template:'\n\t\t<form ng-submit="$ctrl.makePost()" class="form-horizontal">\n\t\t\t<div class="form-group">\n\t\t\t\t<div class="col-sm-12">\n\t\t\t\t\t<ng-quill-editor ng-model="$ctrl.newPost.body" on-content-changed="$ctrl.contentChanged()" modules="$ctrl.modules" on-editor-created="$ctrl.editorCreated(editor)">\n\t\t\t\t\t\t\x3c!-- ng-quill toolbar config {{{ --\x3e\n\t\t\t\t\t\t<ng-quill-toolbar>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-bold" ng-attr-title="{{\'Bold\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-italic" ng-attr-title="{{\'Italic\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-underline" ng-attr-title="{{\'Underline\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-strike" ng-attr-title="{{\'Strikethough\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-blockquote" ng-attr-title="{{\'Block Quote\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-code-block" ng-attr-title="{{\'Code Block\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-header" value="1" ng-attr-title="{{\'Header 1\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-header" value="2" ng-attr-title="{{\'Header 2\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-list" value="ordered" ng-attr-title="{{\'Numered list\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-list" value="bullet" ng-attr-title="{{\'Bulleted list\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-indent" value="-1" ng-attr-title="{{\'De-indent\'}}"></button>\n\t\t\t\t\t\t\t\t\t<button class="ql-indent" value="+1" ng-attr-title="{{\'Indent\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<select class="ql-color" ng-attr-title="{{\'Text color\'}}">\n\t\t\t\t\t\t\t\t\t\t<option selected="selected"></option>\n\t\t\t\t\t\t\t\t\t\t<option ng-repeat="color in ::$ctrl.colors" value="{{::color}}"></option>\n\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t<select class="ql-background" ng-attr-title="{{\'Background color\'}}">\n\t\t\t\t\t\t\t\t\t\t<option selected="selected"></option>\n\t\t\t\t\t\t\t\t\t\t<option ng-repeat="color in ::$ctrl.colors" value="{{::color}}"></option>\n\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-link" value="ordered" ng-attr-title="{{\'Add link\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span class="ql-formats">\n\t\t\t\t\t\t\t\t\t<button class="ql-clean" value="ordered" ng-attr-title="{{\'Clear formatting\'}}"></button>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<div class="pull-right">\n\t\t\t\t\t\t\t\t\t<div class="btn-group">\n\t\t\t\t\t\t\t\t\t\t<a ng-if="$ctrl.templates" class="btn btn-default dropdown-toggle" data-toggle="dropdown">\n\t\t\t\t\t\t\t\t\t\t\tTemplate\n\t\t\t\t\t\t\t\t\t\t\t<i class="fa fa-chevron-down"></i>\n\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t<ul class="dropdown-menu">\n\t\t\t\t\t\t\t\t\t\t\t<li ng-repeat="template in $ctrl.templates">\n\t\t\t\t\t\t\t\t\t\t\t\t<a ng-click="$ctrl.setTemplate(template)">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<i ng-if="template.icon" ng-class="template.icon"></i>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{{template.title}}\n\t\t\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<a ng-repeat="button in $ctrl.buttons" class="btn" ng-class="button.class || \'btn-default\'" ng-click="$ctrl.runButton(button)">\n\t\t\t\t\t\t\t\t\t\t<i ng-if="button.icon" class="{{button.icon}}"></i>\n\t\t\t\t\t\t\t\t\t\t{{button.title}}\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t<a ng-click="$ctrl.makePost()" class="btn btn-sm btn-success">\n\t\t\t\t\t\t\t\t\t\t<i class="fa fa-plus"></i>\n\t\t\t\t\t\t\t\t\t\tPost\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</ng-quill-toolbar>\n\t\t\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t\t\t</ng-quill-editor>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t',controller:["$scope","$q","$element","$debounce","$http",function(n,e,t,r,o){var i=this;i.modules={},i.colors=["#e60000","#ff9900","#ffff00","#008a00","#0066cc","#9933ff","#ffffff","#facccc","#ffebcc","#ffffcc","#cce8cc","#cce0f5","#ebd6ff","#bbbbbb","#f06666","#ffc266","#ffff66","#66b966","#66a3e0","#c285ff","#888888","#a10000","#b26b00","#b2b200","#006100","#0047b2","#6b24b2","#444444","#5c0000","#663d00","#666600","#003700","#002966","#3d1466"],i.contentChanged=r(function(){e.resolve().then(function(){return i.baseUrlImage?null:e.reject("SKIP")}).then(function(){return Array.from(t[0].querySelectorAll('img:not([src^="data:"])'))}).then(function(t){return e.all(t.map(function(n){return e.resolve().then(function(){return n.classList.add("img--loading")}).then(function(){return i.convertImgToBase64URL(n.getAttribute("src"))}).then(function(t){return n.setAttribute("src",t)}).finally(function(){return n.classList.remove("img--loading")})}))}).catch(function(t){return"SKIP"==t?null:e.reject(t)}).finally(function(){return n.$emit("angular-ui-history.content",i.newPost.body)})},300),i.convertImgToBase64URL=function(o){return new Promise(function(t,n){var e=document.createElement("CANVAS"),r=document.createElement("img");r.setAttribute("src",o),r.setAttribute("crossorigin","anonymous"),r.onload=function(){e.height=r.height,e.width=r.width,e.getContext("2d").drawImage(r,10,10,r.width,r.height),t(e.toDataURL())},r.onerror=function(t){return n("Could not load image, please check that the file is accessible")}})},i.editorCreated=function(t){return i.quill=t},i.mentionList=function(){var n={};return i.quill.getContents().ops.filter(function(t){return t.insert&&t.insert.mention}).map(function(t){return t.insert.mention}).forEach(function(t){n[t._id]||(n[t._id]={_id:t._id,name:t.value})}),Object.values(n)},i.newPost={body:""},i.makePost=function(){if(!i.onPost)throw new Error("Post content provided but no onPost binding defined");var t=i.onPost({body:i.newPost.body,tags:i.newPost.tags,mentions:i.mentionUrl?i.mentionList():[]});t&&angular.isFunction(t.then)&&t.then(function(){i.newPost={body:""},i.tags&&i.tags.length&&(i.newPost.tags=i.tags.map(function(t){return t}))})},n.$on("angular-ui-history.post",i.makePost),i.runButton=function(t){t.action&&n.$emit("angular-ui-history.button.".concat(t.action),t),n.$emit("angular-ui-history.button",t)},i.setTemplate=function(t){i.newPost.body=t.content,n.$emit("angular-ui-history.template",t)},i.$onInit=function(){i.tags&&i.tags.length&&(i.newPost.tags=i.tags.map(function(t){return t})),i.baseUrlImage&&(i.modules.imageDrop=!0),i.mentionUrl&&(i.modules.mention={allowedChars:/^[A-Za-z\sÅÄÖåäö]*$/,mentionDenotationChars:["@"],dataAttributes:["_id"],source:function(t,n){return e.resolve().then(function(){if(angular.isString(i.mentionUrl)||angular.isFunction(i.mentionUrl)){var n=angular.isString(i.mentionUrl)?i.mentionUrl:i.mentionUrl(t);return n?o.get(n).then(function(t){if(angular.isArray(t.data))return t.data;throw new Error('Expected mention feed at URL "'.concat(n,'" to be an array but got something else'))}):e.reject(new Error("Resovled URL is empty"))}}).then(function(t){return n(t)}).catch(console.error)}})}}]}).component("uiHistoryUpload",{bindings:{queryUrl:"<",postUrl:"<",onError:"&?",onUpload:"&?",onUploadStart:"&?",onUploadProgress:"&?",onUploadEnd:"&?",tags:"<?"},template:'\n\t\t<div style="display: none">\n\t\t\t<input name="file" multiple type="file"/>\n\t\t</div>\n\t',controller:["$scope","$element","$http","$timeout",function(n,t,o,e){var i=this;i.isUploading=!1,i.upload=function(){var r=this;console.log("upload",i.postUrl,i.queryUrl,this.files),e(function(){var t=angular.isString(i.postUrl)?i.postUrl:angular.isFunction(i.postUrl)?i.postUrl(i):angular.isString(i.queryUrl)?i.queryUrl:angular.isFunction(i.queryUrl)?i.queryUrl(i):void 0;if(!t)throw new Error("Resovled POST URL is empty");var e=new FormData;Object.keys(r.files).forEach(function(t,n){return e.append("file_"+n,r.files[t])}),i.tags&&i.tags.length&&i.tags.forEach(function(t){return e.append("tags[]",t)}),i.isUploading=!0,Promise.resolve().then(function(){i.onUploadStart&&i.onUploadStart({files:r.files})}).then(function(){return o.post(t,e,{headers:{"Content-Type":void 0},transformRequest:angular.identity,uploadEventHandlers:i.onUploadProgress?{progress:function(t){i.onUploadProgress({files:r.files,progress:Math.round(t.loaded/t.total*100)})}}:void 0})}).then(function(t){i.onUpload&&i.onUpload(t),i.onUploadEnd&&i.onUploadEnd({files:r.files})}).catch(function(t){i.onError&&i.onError({error:t})}).then(function(){return n.$emit("angular-ui-history.refresh")}).finally(function(){return i.isUploading=!1})})},t.find("input[type=file]").on("change",i.upload)}]}).component("uiHistoryFiles",{bindings:{buttons:"<",allowUpload:"<",queryUrl:"<",postUrl:"<",onError:"&?",onLoadingStart:"&?",onLoadingStop:"&?",onQuery:"&?",onUpload:"&?",onUploadStart:"&?",onUploadProgress:"&?",onUploadEnd:"&?",tags:"<?"},controller:["$http","$scope","$element",function(t,n,e){var r=this;r.uploads,r.isLoading,r.refresh=function(){if(!r.queryUrl)throw new Error("queryUrl is undefined");var n=angular.isString(r.queryUploadsUrl)?r.queryUploadsUrl:angular.isString(r.queryUrl)?r.queryUrl:r.queryUrl(r);if(!n)throw new Error("Resovled URL for uploads is empty");r.isLoading=!0,r.onLoadingStart&&r.onLoadingStart(),t.get(n).then(function(t){if(!angular.isArray(t.data))throw new Error('Expected file upload feed at URL "'.concat(n,'" to be an array but got something else'));r.uploads=t.data.filter(function(t){return void 0===t.type||"user.upload"==t.type}).reduce(function(t,n){return n.filename?(t.push(n),t):n.files?t.concat(n.files):void 0},[]).sort(function(t,n){return t.filename==n.filename?0:t.filename>n.filename?1:-1}).filter(function(t,n,e){return 0==n||e[n-1].filename!=t.filename})}).catch(function(t){r.onError&&r.onError({error:t})}).finally(function(){return r.isLoading=!1}).finally(function(){r.onLoadingStop&&r.onLoadingStop()})},n.$on("angular-ui-history.refresh",function(){return r.refresh(!0)}),r.getSelectedFiles=function(t){return r.uploads},r.downloadFiles=function(){var t=r.getSelectedFiles(),n=document.createElement("a");n.style.display="none",document.body.appendChild(n);for(var e=0;e<t.length;e++)n.setAttribute("download",t[e].filename),n.setAttribute("href",t[e].url),n.click();document.body.removeChild(n)},n.$on("angular-ui-history.button.upload",function(){return r.selectFiles()}),r.selectFiles=function(){return e.find("input[type=file]").click()},r.runButton=function(t){t.action&&n.$emit("angular-ui-history.button.".concat(t.action),t),n.$emit("angular-ui-history.button",t)},r.$onInit=function(){r.buttons||(r.buttons=[],r.allowUpload&&r.buttons.push({title:"Upload files...",icon:"fa fa-file",class:"btn-primary",action:"upload"}))},n.$evalAsync(r.refresh)}],template:'\n\t\t<ui-history-upload\n\t\t\tquery-url="$ctrl.queryUrl"\n\t\t\tpost-url="$ctrl.postUrl"\n\t\t\ton-error="$ctrl.onError"\n\t\t\ton-upload="$ctrl.onUpload"\n\t\t\ton-upload-start="$ctrl.onUploadStart"\n\t\t\ton-upload-progress="$ctrl.onUploadProgress"\n\t\t\ton-upload-end="$ctrl.onUploadEnd"\n\t\t\ttags="$ctrl.tags"\n\t\t></ui-history-upload>\n\n\t\t<div ng-if="$ctrl.isLoading">\n\t\t\t<h2>\n\t\t\t\t<i class="fa fa-spinner fa-spin"></i>\n\t\t\t\tFetching list of files...\n\t\t\t</h2>\n\t\t</div>\n\t\t<div ng-if="!$ctrl.isLoading && $ctrl.uploads.length == 0" class="text-muted text-center">\n\t\t\tNo file uploads found\n\t\t</div>\n\t\t<ul class="list-group">\n\t\t\t<a ng-repeat="file in $ctrl.uploads track by file.filename" ng-href="{{file.url}}" target="_blank" class="list-group-item">\n\t\t\t\t<div class="pull-right">\n\t\t\t\t\t<span class="badge">{{file.size}}</span>\n\t\t\t\t</div>\n\t\t\t\t{{file.filename}}\n\t\t\t</a>\n\t\t</ul>\n\t\t<div class="form-group">\n\t\t\t<a ng-repeat="button in $ctrl.buttons" class="btn" ng-class="button.class || \'btn-default\'" ng-click="$ctrl.runButton(button)">\n\t\t\t\t<i ng-if="button.icon" class="{{button.icon}}"></i>\n\t\t\t\t{{button.title}}\n\t\t\t</a>\n\t\t\t<a ng-click="$ctrl.downloadFiles()" ng-class="$ctrl.getSelectedFiles().length > 0?\'\':\'disabled\'" class="btn btn-primary">\n\t\t\t\t<i class="fa fa-download"></i> Download All Files\n\t\t\t</a>\n\t\t</div>\n\t'}).component("uiHistoryLatest",{bindings:{queryUrl:"<?",onError:"&?",onLoadingStart:"&?",onLoadingStop:"&?",onQuery:"&?"},template:'\n\t\t<div class="ui-history ui-history-latest">\n\t\t\t<div class="ui-history-item" ng-switch="$ctrl.post.type" ng-if="$ctrl.post">\n\t\t\t\t<div class="ui-history-meta">\n\t\t\t\t\t<a ng-href="{{$ctrl.post.user.url}}" target="_blank" class="ui-history-latest-user">\n\t\t\t\t\t\t{{$ctrl.post.user.name}}{{$ctrl.post.date ? \',\' : \'\'}}\n\t\t\t\t\t</a>\n\t\t\t\t\t<div class="ui-history-timestamp" >\n\t\t\t\t\t\t{{$ctrl.post.date ? ($ctrl.post.date | uiHistoryDate) : \'\'}}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t\x3c!-- type=user.change {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.change" class="ui-history-user-change">\n\t\t\t\t\t<div ng-if="$ctrl.post.field" class="ui-history-user-change-main">\n\t\t\t\t\t\t<a ng-href="{{$ctrl.post.user.url}}" target="_blank">\n\t\t\t\t\t\t\t{{$ctrl.post.user.name}}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\tChanged\n\t\t\t\t\t\t{{$ctrl.post.field}}\n\t\t\t\t\t\t<em>{{$ctrl.post.from}}</em>\n\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t<em>{{$ctrl.post.to}}</em>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if="$ctrl.post.fields" class="ui-history-user-change-main">\n\t\t\t\t\t\tChanges:\n\t\t\t\t\t\t<div ng-repeat="(field, change) in $ctrl.post.fields track by field">\n\t\t\t\t\t\t\t{{field}}\n\t\t\t\t\t\t\t<em>{{change.from}}</em>\n\t\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t\t<em>{{change.to}}</em>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type=user.comment {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.comment" class="ui-history-user-comment">\n\t\t\t\t\t<div ng-if="$ctrl.post.user.company" class="ui-history-company">\n\t\t\t\t\t\t{{$ctrl.post.user.company}}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class="ui-history-user-comment-main">\n\t\t\t\t\t\t<div ng-if="$ctrl.post.title" class="ui-history-user-comment-header">{{$ctrl.post.title}}</div>\n\t\t\t\t\t\t<div class="ui-history-user-comment-body" ng-bind-html="$ctrl.post.body"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type=user.upload {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.upload" class="ui-history-user-upload">\n\t\t\t\t\t<div class="ui-history-user-upload-main">\n\t\t\t\t\t\t<div style="margin-bottom: 10px"><a ng-href="{{$ctrl.post.user.url}}" target="_blank" >{{$ctrl.post.user.name}}</a> attached files:</div>\n\t\t\t\t\t\t<ul class="list-group">\n\t\t\t\t\t\t\t<a ng-if="$ctrl.post.filename" ng-href="{{$ctrl.post.url}}" target="_blank" class="list-group-item">\n\t\t\t\t\t\t\t\t<div ng-if="$ctrl.post.size" class="pull-right">{{$ctrl.post.size}}</div>\n\t\t\t\t\t\t\t\t<i ng-if="$ctrl.post.icon" class="{{$ctrl.post.icon}}"></i>\n\t\t\t\t\t\t\t\t{{$ctrl.post.filename || \'Unknown file\'}}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<a ng-if="$ctrl.post.files" ng-repeat="file in $ctrl.post.files track by file.filename" ng-href="{{file.url}}" target="_blank" class="list-group-item">\n\t\t\t\t\t\t\t\t<div ng-if="file.size" class="pull-right">{{file.size}}</div>\n\t\t\t\t\t\t\t\t<i ng-if="file.icon" class="{{file.icon}}"></i>\n\t\t\t\t\t\t\t\t{{file.filename || \'Unknown file\'}}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type=user.status {{{ --\x3e\n\t\t\t\t<div ng-switch-when="user.status" class="ui-history-user-status">\n\t\t\t\t\t<div class="ui-history-user-status-main" ng-bind-html="$ctrl.post.body"></div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type=system.change {{{ --\x3e\n\t\t\t\t<div ng-switch-when="system.change" class="ui-history-system-change">\n\t\t\t\t\t<div ng-if="$ctrl.post.field">\n\t\t\t\t\t\tChanged\n\t\t\t\t\t\t{{$ctrl.post.field}}\n\t\t\t\t\t\t<em>{{$ctrl.post.from}}</em>\n\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t<em>{{$ctrl.post.to}}</em>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div ng-if="$ctrl.post.fields">\n\t\t\t\t\t\tChanges:\n\t\t\t\t\t\t<div ng-repeat="(field, change) in $ctrl.post.fields track by field">\n\t\t\t\t\t\t\t{{field}}\n\t\t\t\t\t\t\t<em>{{change.from}}</em>\n\t\t\t\t\t\t\t<i class="fa fa-long-arrow-right"></i>\n\t\t\t\t\t\t\t<em>{{change.to}}</em>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type=system.status {{{ --\x3e\n\t\t\t\t<div ng-switch-when="system.status" class="ui-history-system-status" ng-bind-html="$ctrl.post.body"></div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\n\t\t\t\t\x3c!-- type unknown {{{ --\x3e\n\t\t\t\t<div ng-switch-default class="ui-history-unknown">\n\t\t\t\t\tUnknown history type: [{{$ctrl.post.type}}]\n\t\t\t\t</div>\n\t\t\t\t\x3c!-- }}} --\x3e\n\t\t\t</div>\n\t\t</div>\n\t',controller:["$http","$q","$sce","$scope","$filter",function(t,n,e,r,o){var i=this;i.posts,i.post,i.refresh=function(){if(!(0<arguments.length&&void 0!==arguments[0]&&arguments[0])&&i.posts)return n.resolve();n.resolve().then(function(){return i.isLoading=!0}).then(function(){if(angular.isFunction(i.onLoadingStart))return i.onLoadingStart()}).then(function(){if(angular.isString(i.queryUrl)||angular.isFunction(i.queryUrl)){var n=angular.isString(i.queryUrl)?i.queryUrl:i.queryUrl(i);if(!n)throw new Error("Resovled URL is empty");return t.get(n).then(function(t){if(angular.isArray(t.data))return t.data;throw new Error('Expected history feed at URL "'.concat(n,'" to be an array but got something else'))}).catch(function(t){return console.log("err:",t)})}if(angular.isArray(i.posts))return i.posts;throw new Error("Cannot refresh posts - neither queryUrl (func / array) or posts (array) are specified")}).then(function(t){i.posts=t}).then(function(){var t;i.onQuery&&(t=i.onQuery({posts:i.posts}),angular.isArray(t)&&(i.posts=t))}).then(function(){i.posts=o("orderBy")(i.posts,"date",!0),i.post=i.posts[0]}).then(function(t){var n=i.post;n&&n.body&&"string"==typeof n.body&&("user.comment"==n.type||"user.status"==n.type||"system.status"==n.type)&&(n.body=e.trustAsHtml(n.body))}).catch(function(t){angular.isFunction(i.onError)&&i.onError({error:t})}).finally(function(){return i.isLoading=!1}).finally(function(){if(angular.isFunction(i.onLoadingStop))return i.onLoadingStop()})},i.$onInit=function(){r.$watch("$ctrl.queryUrl",function(){return i.refresh(!0)})}}]}).component("userHistoryAvatar",{bindings:{user:"<",userAvatar:"@?",defaultImage:"@?"},template:'\n\t\t<div ng-if="$ctrl.userAvatar" ng-include="$ctrl.userAvatar"></div>\n\t\t<a ng-if="!$ctrl.userAvatar" ng-href="{{$ctrl.user.url}}" target="_blank">\n\t\t\t<img gravatar-src="$ctrl.user.email" gravatar-size="50" gravatar-default="{{$ctrl.defaultImage || \'monsterid\'}}" tooltip="{{$ctrl.user.name}}"/>\n\t\t</a>\n\t'}).filter("uiHistoryDate",function(){return function(t){var n=moment(t);if(!n._isValid)return"Invalid date";t=moment(Date.now()).diff(n,"days");return t<0?moment(n).fromNow(!0)+" from now":t<1?n.format("h:mma"):1===t?"Yesterday":1<t&&t<7?n.format("dddd"):n.format("D MMMM, YYYY")}});