Commit 67aeaf4e5fedcaca23c45f1cf0869380941588a3
1 parent
6e6aa9b0
Exists in
master
commit
Showing
56 changed files
with
2153 additions
and
2153 deletions
Show diff stats
common_components/directives/BindHtmlCompile.directive.js
@@ -1,21 +0,0 @@ | @@ -1,21 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - 'use strict'; | ||
3 | - | ||
4 | - var module = angular.module('framework.directives.utils', []); | ||
5 | - | ||
6 | - module.directive('bindHtmlCompile', ['$compile', bindHtmlCompile]); | ||
7 | - | ||
8 | - function bindHtmlCompile($compile) { | ||
9 | - return { | ||
10 | - restrict: 'A', | ||
11 | - link: function (scope, element, attrs) { | ||
12 | - scope.$watch(function () { | ||
13 | - return scope.$eval(attrs.bindHtmlCompile); | ||
14 | - }, function (value) { | ||
15 | - element.html(value); | ||
16 | - $compile(element.contents())(scope); | ||
17 | - }); | ||
18 | - } | ||
19 | - }; | ||
20 | - } | ||
21 | -}(angular)); | ||
22 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/directives/Card.directive.js
@@ -1,48 +0,0 @@ | @@ -1,48 +0,0 @@ | ||
1 | -(function(angular){ | ||
2 | - var module = angular.module('framework.directives.UI',[]); | ||
3 | - | ||
4 | - module.directive('card', cardDirective); | ||
5 | - cardDirective.$inject=['$state', '$interval', '$parse']; | ||
6 | - function cardDirective($state, $interval, $parse) { | ||
7 | - return { | ||
8 | - restrict: 'E', | ||
9 | - transclude: true, | ||
10 | - replace: true, | ||
11 | - scope: true, | ||
12 | - template: function(element, attrs) { | ||
13 | - var template=''; | ||
14 | - template += '<div class="card"><div class="card-container"'; | ||
15 | - if(attrs.allowClick!="false") { | ||
16 | - template += ' ng-click="viewItem(item)"' | ||
17 | - } | ||
18 | - template += '><svg class="logo" style="background-image:url(\'{{::accessors.LogoUrl(item)}}\')" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="transparent" stroke-width="10" stroke-linecap="round" ng-show="showScore==true" stroke-location="outside"></circle></svg>'; | ||
19 | - if(attrs.showTitle!="false") { | ||
20 | - template += '<strong>{{ ::accessors.Title(item) }}</strong>'; | ||
21 | - } | ||
22 | - if(attrs.showSubtitle!="false") { | ||
23 | - template += '<small>{{ ::accessors.SubTitle(item) }}</small>'; | ||
24 | - } | ||
25 | - template += '</div></div>'; | ||
26 | - return template; | ||
27 | - }, | ||
28 | - link: function(scope, elem, attrs, ctrls, transcludeFn) { | ||
29 | - if(attrs.item) { | ||
30 | - var getter = $parse(attrs.item); | ||
31 | - scope.item = getter(scope); | ||
32 | - } | ||
33 | - scope.viewItem = viewItem; | ||
34 | - if(scope.accessors.Score) { | ||
35 | - var percentScore = (2 * Math.PI*50)/100*scope.accessors.Score(scope.item); | ||
36 | - var percentColor = (percentScore < 90)? 'red': (percentScore >= 90 && percentScore <180)? 'orange' :(percentScore >= 180 && percentScore <270)? 'rgb(25, 195, 45)' : 'rgb(25, 195, 45);'; | ||
37 | - elem.find("circle") | ||
38 | - .attr("stroke", percentColor) | ||
39 | - .attr("stroke-dasharray",percentScore+",10000"); | ||
40 | - } | ||
41 | - | ||
42 | - function viewItem(item) { | ||
43 | - $state.go(scope.rNavTo, { Id: item.Id }); | ||
44 | - } | ||
45 | - } | ||
46 | - } | ||
47 | - } | ||
48 | -})(angular); | ||
49 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/directives/FieldFor.directive.js
@@ -1,218 +0,0 @@ | @@ -1,218 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.directives.UI'); | ||
3 | - | ||
4 | - module.directive('fieldFor', fieldForDirective); | ||
5 | - module.directive('formFor', formForDirective); | ||
6 | - module.filter('propSearch', propertySearchFilter); | ||
7 | - | ||
8 | - formForDirective.$inject = ['Model']; | ||
9 | - function formForDirective(Model) { | ||
10 | - return { | ||
11 | - restrict: 'A', | ||
12 | - scope: true, | ||
13 | - transclude: true, | ||
14 | - template: function (element, attrs) { | ||
15 | - return '<form name="formFor.form" class="transclude-target" autocomplete="off" novalidate></form>'; | ||
16 | - }, | ||
17 | - link: function (scope, element, attrs, ctrls, transcludeFn) { | ||
18 | - scope.formFor = (scope.formFor || {}); | ||
19 | - scope.formFor.target = scope.$eval(attrs.formFor); | ||
20 | - scope.formFor.schema = (attrs.schema) ? Model[attrs.schema].$schema : scope.target.$$schema; | ||
21 | - scope.formFor.mode = 'EDIT'; | ||
22 | - | ||
23 | - scope.$watch(function () { | ||
24 | - return scope.target; | ||
25 | - }, function (newvalue) { | ||
26 | - | ||
27 | - }); | ||
28 | - | ||
29 | - if (attrs.mode) { | ||
30 | - scope.formFor.mode = attrs.mode; | ||
31 | - attrs.$observe('mode', function (newvalue) { | ||
32 | - scope.formFor.mode = newvalue; | ||
33 | - }); | ||
34 | - } | ||
35 | - | ||
36 | - transcludeFn(scope, function (clone, scope) { | ||
37 | - element.children('.transclude-target').append(clone); | ||
38 | - }); | ||
39 | - } | ||
40 | - } | ||
41 | - }; | ||
42 | - | ||
43 | - fieldForDirective.$inject = ['Model']; | ||
44 | - function fieldForDirective(Model) { | ||
45 | - var defaults = { | ||
46 | - inputType: 'text', | ||
47 | - required: false, | ||
48 | - selectTheme: 'selectize', | ||
49 | - selectSelectedTemplate: '{{$select.selected.Name}}', | ||
50 | - selectOptionTemplate: '<div ng-bind-html="option.Name | highlight: $select.search"></div><small class="text-muted">{{option.Description}}</small>' | ||
51 | - }; | ||
52 | - return { | ||
53 | - restrict: 'A', | ||
54 | - scope: true, | ||
55 | - template: function (element, attrs) { | ||
56 | - var formParent = element.closest('[form-for]'), | ||
57 | - subformParent = element.closest('[sub-form-for]'), | ||
58 | - schemaName = ((subformParent.length) ? subformParent : formParent).attr('schema'), | ||
59 | - ctor = Model[schemaName], | ||
60 | - schema = ctor && ctor.$schema, | ||
61 | - fieldDef = schema && schema[attrs.fieldFor], | ||
62 | - subForm = subformParent.attr('sub-form-for') || ''; | ||
63 | - | ||
64 | - if (!fieldDef) { | ||
65 | - return; | ||
66 | - } | ||
67 | - | ||
68 | - var inputConfig = angular.extend({ display: attrs.fieldFor, inputType: 'text' }, defaults, fieldDef, fieldDef.input, attrs); | ||
69 | - | ||
70 | - //need to fetch these. | ||
71 | - var labelText = attrs.display || attrs.fieldFor, | ||
72 | - fieldName = attrs.fieldFor, | ||
73 | - selectFrom = attrs.selectFrom; | ||
74 | - | ||
75 | - var template = '' + | ||
76 | - '<div class="form-group">' + | ||
77 | - '<label class="control-label" for="' + subForm + fieldName + 'Input">' + inputConfig.display + '</label>' + | ||
78 | - '<div ng-if="formFor.mode === \'VIEW\'">' + | ||
79 | - '<p class="form-control-static" ng-bind="::formFor.target.' + ((subForm) ? (subForm + '.') : '') + (inputConfig.displayField ? inputConfig.displayField : fieldName) + (inputConfig.displayFilters ? inputConfig.displayFilters : '') + '"></p>' + | ||
80 | - '</div>' + | ||
81 | - '<div ng-if="formFor.mode === \'EDIT\'">'; | ||
82 | - | ||
83 | - if (selectFrom) { | ||
84 | - template += '' + | ||
85 | - '<ui-select ng-model="formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName + '" name="' + subForm + fieldName + 'Input" theme="' + inputConfig.selectTheme + '" ng-disabled="' + (angular.isDefined(inputConfig.editable) && !inputConfig.editable) + '" ng-required="' + inputConfig.required + '">' + | ||
86 | - '<ui-select-match allow-clear="true" placeholder="' + (inputConfig.placeholder || 'Select..') + '">' + inputConfig.selectSelectedTemplate + '</ui-select-match>' + | ||
87 | - '<ui-select-choices repeat="option.Id as option in ' + selectFrom + ' | propSearch: { Name: $select.search }">' + | ||
88 | - inputConfig.selectOptionTemplate + | ||
89 | - '</ui-select-choices>'+ | ||
90 | - '</ui-select>'; | ||
91 | - } else if (inputConfig.type === moment) { | ||
92 | - template += '' + | ||
93 | - '<div class="input-group">' + | ||
94 | - buildElement('input', { | ||
95 | - class: 'form-control', | ||
96 | - type: 'text', | ||
97 | - name: subForm + fieldName + 'Input', | ||
98 | - ngModel: 'formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName, | ||
99 | - ngRequired: inputConfig.required, | ||
100 | - datepickerPopup: 'dd/MM/yyyy', | ||
101 | - isOpen: 'opened', | ||
102 | - placeholder: 'DD/MM/YYYY', | ||
103 | - ngDisabled: angular.isDefined(inputConfig.editable) && !inputConfig.editable | ||
104 | - }) + | ||
105 | - '<span class="input-group-btn">' + | ||
106 | - '<button type="button" class="btn btn-default" ng-click="openCalendar($event)"><i class="glyphicon glyphicon-calendar"></i></button>' + | ||
107 | - '</span>' + | ||
108 | - '</div>'; | ||
109 | - } else { | ||
110 | - if (inputConfig.append || inputConfig.prepend) { | ||
111 | - template += '<div class="input-group">'; | ||
112 | - } | ||
113 | - if (inputConfig.prepend) { | ||
114 | - template += '<span class="input-group-btn">' + | ||
115 | - '<button type="button" class="btn btn-default" ng-click="' + inputConfig.prepend.click + '"><i class="' + inputConfig.prepend.icon + '"></i>' + inputConfig.prepend.text + '</button>' + | ||
116 | - '</span>' | ||
117 | - } | ||
118 | - template += buildElement('input', { | ||
119 | - class: 'form-control', | ||
120 | - type: inputConfig.inputType, | ||
121 | - name: subForm + fieldName + 'Input', | ||
122 | - ngModel: 'formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName, | ||
123 | - ngRequired: inputConfig.required, | ||
124 | - placeholder: inputConfig.placeholder | ||
125 | - }); | ||
126 | - if (inputConfig.append) { | ||
127 | - template += '<span class="input-group-btn">' + | ||
128 | - '<button type="button" class="btn btn-default" ng-click="' + inputConfig.append.click + '"><i class="' + inputConfig.append.icon + '"></i>' + inputConfig.append.text + '</button>' + | ||
129 | - '</span>' | ||
130 | - } | ||
131 | - if (inputConfig.append || inputConfig.prepend) { | ||
132 | - template += '</div>'; | ||
133 | - } | ||
134 | - } | ||
135 | - | ||
136 | - template += '' + | ||
137 | - '<div ng-messages="formFor.form.' + subForm + fieldName + 'Input.$error" class="help-block">' + | ||
138 | - '<div ng-message="required">' + inputConfig.display + ' is required.</div>' + | ||
139 | - '<div ng-message="parse">' + inputConfig.display + ' is incorrectly formatted.</div>' + | ||
140 | - '<div ng-message="email">' + inputConfig.display + ' is not a valid e-mail.</div>' + | ||
141 | - '</div>' + | ||
142 | - '</div>'; | ||
143 | - template += '</div>'; | ||
144 | - return template; | ||
145 | - }, | ||
146 | - link: function (scope, element, attrs) { | ||
147 | - scope.opened = false; | ||
148 | - | ||
149 | - scope.openCalendar = function (event) { | ||
150 | - event.preventDefault(); | ||
151 | - event.stopPropagation(); | ||
152 | - scope.opened = true; | ||
153 | - } | ||
154 | - } | ||
155 | - }; | ||
156 | - }; | ||
157 | - | ||
158 | - function propertySearchFilter() { | ||
159 | - return function (items, props) { | ||
160 | - var out = []; | ||
161 | - | ||
162 | - if (angular.isArray(items)) { | ||
163 | - items.forEach(function (item) { | ||
164 | - var itemMatches = false; | ||
165 | - | ||
166 | - var keys = Object.keys(props); | ||
167 | - for (var i = 0; i < keys.length; i++) { | ||
168 | - var prop = keys[i]; | ||
169 | - var text = props[prop].toLowerCase(); | ||
170 | - if (item[prop].toString().toLowerCase().indexOf(text) !== -1) { | ||
171 | - itemMatches = true; | ||
172 | - break; | ||
173 | - } | ||
174 | - } | ||
175 | - | ||
176 | - if (itemMatches) { | ||
177 | - out.push(item); | ||
178 | - } | ||
179 | - }); | ||
180 | - } else { | ||
181 | - // Let the output be the input untouched | ||
182 | - out = items; | ||
183 | - } | ||
184 | - | ||
185 | - return out; | ||
186 | - }; | ||
187 | - }; | ||
188 | - | ||
189 | - function buildElement(elementType, attrs) { | ||
190 | - var result = '<' + elementType + ' '; | ||
191 | - | ||
192 | - angular.forEach(attrs, function (value, key) { | ||
193 | - if (angular.isDefined(value) && value !== null) | ||
194 | - result += normalise(key) + '="' + value + '"'; | ||
195 | - }); | ||
196 | - | ||
197 | - if (elementType === 'input') { | ||
198 | - result += ' />'; | ||
199 | - } else { | ||
200 | - result += ' ></' + elementType + '>'; | ||
201 | - } | ||
202 | - return result; | ||
203 | - } | ||
204 | - | ||
205 | - function normalise(input) { | ||
206 | - var result = ''; | ||
207 | - for (var i = 0; i < input.length; i++) { | ||
208 | - var char = input[i]; | ||
209 | - if (char == char.toUpperCase()) { | ||
210 | - result += '-' + char.toLowerCase(); | ||
211 | - } else { | ||
212 | - result += char; | ||
213 | - } | ||
214 | - } | ||
215 | - return result; | ||
216 | - } | ||
217 | - | ||
218 | -}(angular)); | ||
219 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/directives/Score.directive.js
@@ -1,53 +0,0 @@ | @@ -1,53 +0,0 @@ | ||
1 | -(function(angular){ | ||
2 | - var module = angular.module('framework.directives.UI'); | ||
3 | - | ||
4 | - module.directive('score', scoreDirective); | ||
5 | - | ||
6 | - scoreDirective.$inject=['$state', '$interval', '$parse']; | ||
7 | - | ||
8 | - function scoreDirective($state, $interval, $parse) { | ||
9 | - return { | ||
10 | - restrict: 'E', | ||
11 | - transclude: true, | ||
12 | - replace: true, | ||
13 | - scope: true, | ||
14 | - template: function(element, attrs) { | ||
15 | - var template=''; | ||
16 | - template += '<div class="score"'; | ||
17 | - if(attrs.size) { | ||
18 | - var scoreSize = parseInt(attrs.size); | ||
19 | - template += ' style="position:relative;width:'+ (scoreSize) +'px; height: ' + (scoreSize) + 'px; border-radius:'+ (scoreSize/2) + 'px;padding:5px;">'; | ||
20 | - } | ||
21 | - else { | ||
22 | - template += ' style="width:100px;height:100px;border-radius:50px;">'; | ||
23 | - } | ||
24 | - if(attrs.showScore) { | ||
25 | - template += '<div class="score-value" style="line-height:' + scoreSize + 'px">'+attrs.showScore+'</div>'; | ||
26 | - } | ||
27 | - template += '<svg class="dial" viewBox="0 0 100 100">' + | ||
28 | - '<circle class="score-back-circle" cx="50" cy="50" r="45" fill="transparent" stroke-linecap="round"></circle>' + | ||
29 | - '<circle class="score-front-circle" cx="50" cy="50" r="45" fill="transparent" stroke-linecap="round"></circle>' + | ||
30 | - '</svg>'; | ||
31 | - template += '</div>'; | ||
32 | - return template; | ||
33 | - }, | ||
34 | - link: function(scope, elem, attrs, ctrls, transcludeFn) { | ||
35 | - if(!attrs.value) | ||
36 | - return; | ||
37 | - | ||
38 | - var strokeWidth = (attrs.strokeWidth)? attrs.strokeWidth : 5; | ||
39 | - var percentScore = (2 * Math.PI*50)/100 * attrs.value; | ||
40 | - var percentColor = (percentScore < 90)? 'red': (percentScore >= 90 && percentScore <180)? 'orange' :(percentScore >= 180 && percentScore <270)? 'rgb(25, 195, 45)' : 'rgb(25, 195, 45)'; | ||
41 | - | ||
42 | - elem.find("circle.score-back-circle") | ||
43 | - .attr("stroke", "#eee") | ||
44 | - .attr("stroke-width", strokeWidth); | ||
45 | - | ||
46 | - elem.find("circle.score-front-circle") | ||
47 | - .attr("stroke", percentColor) | ||
48 | - .attr("stroke-width", strokeWidth) | ||
49 | - .attr("stroke-dasharray", percentScore+",10000"); | ||
50 | - } | ||
51 | - } | ||
52 | - } | ||
53 | -})(angular); | ||
54 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/directives/TableFor.directive.js
@@ -1,592 +0,0 @@ | @@ -1,592 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.directives.UI'); | ||
3 | - | ||
4 | - module.directive('tableFor', tableForDirective); | ||
5 | - module.directive('tableTitlebar', tableTitlebarDirective); | ||
6 | - module.directive('tableHeading', tableHeadingDirective); | ||
7 | - module.directive('tableDataRows', tableDataRowsDirective); | ||
8 | - module.directive('tableFooter', tableFooterDirective); | ||
9 | - module.filter('publish', publishFilter); | ||
10 | - module.filter('softFilter', softFilter); | ||
11 | - module.filter('pageGroup', pageGroupFilter); | ||
12 | - | ||
13 | - | ||
14 | - | ||
15 | - tableForDirective.$inject = ['$parse', 'Model', '$modal', '$q', '$filter', '$timeout']; | ||
16 | - function tableForDirective($parse, Model, $modal, $q, $filter, $timeout) { | ||
17 | - var defaults = { | ||
18 | - wrapperClass: 'table-responsive', | ||
19 | - tableClass: 'table table-bordered', | ||
20 | - minWidth: '600px' | ||
21 | - } | ||
22 | - | ||
23 | - function linkFn(scope, element, attrs, ctrls, transcludeFn) { | ||
24 | - var externalSearch = $parse(attrs.filtering)(scope); | ||
25 | - var externalSorting = $parse(attrs.sorting)(scope); | ||
26 | - var externalGrouping = $parse(attrs.grouping)(scope); | ||
27 | - var externalPaging = $parse(attrs.paging)(scope); | ||
28 | - | ||
29 | - scope.$schema = Model[attrs.schema].$schema; | ||
30 | - scope.$table = { | ||
31 | - actionColumn: false, | ||
32 | - selectionColumn: false, | ||
33 | - cardTemplate: '{{$row | json}}', | ||
34 | - toggleSelectAll: toggleSelectAll, | ||
35 | - toggleRowSelection: toggleRowSelection, | ||
36 | - toggleGroupSelection: toggleGroupSelection, | ||
37 | - allSelected: false, | ||
38 | - reset: reset, | ||
39 | - configureColumns: configureColumns, | ||
40 | - sort: sort, | ||
41 | - getSortingClass: getSortingClass | ||
42 | - }; | ||
43 | - scope.$columns = generateColumns(scope.$schema); | ||
44 | - scope.$filtering = externalSearch || { | ||
45 | - $: '' | ||
46 | - } | ||
47 | - scope.$sorting = externalSorting || []; | ||
48 | - scope.$grouping = externalGrouping || { | ||
49 | - value: undefined | ||
50 | - }; | ||
51 | - scope.$paging = externalPaging || { | ||
52 | - currentPage: 1, | ||
53 | - totalItems: 0, | ||
54 | - maxPerPage: 10 | ||
55 | - }; | ||
56 | - scope.$data = {}; //object as it's grouped | ||
57 | - scope.$datasource = function () { | ||
58 | - return arguments[4]; //returns existing data by default; | ||
59 | - }; | ||
60 | - | ||
61 | - var datasource = $parse(attrs.datasource)(scope); | ||
62 | - if (angular.isArray(datasource)) { | ||
63 | - scope.$datasource = generateLocalDatasource(datasource); | ||
64 | - } else if (angular.isFunction(datasource)) { | ||
65 | - scope.$datasource = datasource; | ||
66 | - } else { | ||
67 | - scope.$datasource = generateModelDatasource(scope.$schema.query); | ||
68 | - } | ||
69 | - | ||
70 | - scope.$watchCollection(function () { return scope.$filtering; }, debouncedUpdateData); | ||
71 | - scope.$watchCollection(function () { return scope.$sorting; }, debouncedUpdateData); | ||
72 | - scope.$watchCollection(function () { return scope.$grouping; }, debouncedUpdateData); | ||
73 | - scope.$watch(function () { return scope.$paging.currentPage; }, debouncedUpdateData); | ||
74 | - scope.$watch(function () { return scope.$paging.maxPerPage; }, debouncedUpdateData); | ||
75 | - | ||
76 | - var updateDebounce = null; | ||
77 | - | ||
78 | - function debouncedUpdateData() { | ||
79 | - if (updateDebounce) { | ||
80 | - $timeout.cancel(updateDebounce); | ||
81 | - updateDebounce = null; | ||
82 | - } | ||
83 | - updateDebounce = $timeout(updateData, 500); | ||
84 | - } | ||
85 | - | ||
86 | - function updateData() { | ||
87 | - for (var key in scope.$data) { | ||
88 | - delete scope.$data[key]; | ||
89 | - } | ||
90 | - scope.$data.$loading = true; | ||
91 | - scope.$data.$error = null; | ||
92 | - scope.$datasource(scope.$filtering, scope.$sorting, scope.$grouping, scope.$paging, scope.$data).then(dataReceived, dataError, dataNotified); | ||
93 | - } | ||
94 | - | ||
95 | - function dataReceived(data) { | ||
96 | - for (var key in scope.$data) { | ||
97 | - delete scope.$data[key]; | ||
98 | - } | ||
99 | - scope.$data.$loading = false; | ||
100 | - angular.extend(scope.$data, data); | ||
101 | - } | ||
102 | - | ||
103 | - function dataError(error) { | ||
104 | - for (var key in scope.$data) { | ||
105 | - delete scope.$data[key]; | ||
106 | - } | ||
107 | - scope.$data.$loading = false; | ||
108 | - scope.$data.$error = error; | ||
109 | - } | ||
110 | - | ||
111 | - function dataNotified(dataLength) { | ||
112 | - scope.$paging.totalItems = dataLength; | ||
113 | - } | ||
114 | - | ||
115 | - transcludeFn(scope, function (clone, scope) { | ||
116 | - element.find('table').append(clone); | ||
117 | - }); | ||
118 | - | ||
119 | - function generateLocalDatasource(initialData) { | ||
120 | - var data = initialData; | ||
121 | - return function (filtering, sorting, grouping, paging, existing) { | ||
122 | - var deferred = $q.defer(); | ||
123 | - | ||
124 | - setTimeout(function () { | ||
125 | - var filter = $filter('filter'); | ||
126 | - var orderBy = $filter('orderBy'); | ||
127 | - var groupBy = $filter('groupBy'); | ||
128 | - var pageGroup = $filter('pageGroup'); | ||
129 | - | ||
130 | - deferred.notify(filter(data, filtering).length); | ||
131 | - | ||
132 | - var amendedSorting = [grouping.value]; | ||
133 | - [].push.apply(amendedSorting, sorting); | ||
134 | - | ||
135 | - var result = pageGroup(groupBy(orderBy(filter(data, filtering), amendedSorting), grouping.value), paging); | ||
136 | - | ||
137 | - deferred.resolve(result); | ||
138 | - }, 0); | ||
139 | - | ||
140 | - return deferred.promise; | ||
141 | - } | ||
142 | - } | ||
143 | - | ||
144 | - function generateModelDatasource(modelQuery) { | ||
145 | - var queryBase = modelQuery; | ||
146 | - return function (filtering, sorting, grouping, paging, existing) { | ||
147 | - var deferred = $q.defer(); | ||
148 | - | ||
149 | - query = queryBase(); | ||
150 | - if (grouping.value) { | ||
151 | - query.orderBy(grouping.value); | ||
152 | - } | ||
153 | - | ||
154 | - angular.forEach(ordering, function (o) { query.orderBy(o); }); | ||
155 | - | ||
156 | - | ||
157 | - setTimeout(function () { | ||
158 | - var filter = $filter('filter'); | ||
159 | - var groupBy = $filter('groupBy'); | ||
160 | - var pageGroup = $filter('pageGroup'); | ||
161 | - | ||
162 | - deferred.notify(filter(data, filtering).length); | ||
163 | - | ||
164 | - var amendedSorting = [grouping.value]; | ||
165 | - [].push.apply(amendedSorting, sorting); | ||
166 | - | ||
167 | - var result = pageGroup(groupBy(orderBy(filter(data, filtering), amendedSorting), grouping.value), paging); | ||
168 | - | ||
169 | - deferred.resolve(result); | ||
170 | - }, 0); | ||
171 | - | ||
172 | - return deferred.promise; | ||
173 | - } | ||
174 | - } | ||
175 | - | ||
176 | - function generateColumns(modelSchema) { | ||
177 | - var columns = []; | ||
178 | - angular.forEach(modelSchema, function (value, key) { | ||
179 | - var config = angular.extend({}, value, value.table || {}); | ||
180 | - if (config.hidden) { | ||
181 | - return; | ||
182 | - } | ||
183 | - if (!angular.isDefined(config.visible)) { | ||
184 | - config.visible = true; | ||
185 | - } | ||
186 | - if (!angular.isDefined(config.binding) && config.type === moment) { | ||
187 | - config.binding = key + ".toDate() | date:'dd/MM/yyyy'"; | ||
188 | - } | ||
189 | - columns.push({ key: key, title: config.display || key, accessor: angular.isFunction(config.binding) ? config.binding : buildAccessor(config.binding || key), binding: config.binding || key, visible: config.visible, filters: config.filters }); | ||
190 | - }); | ||
191 | - return columns; | ||
192 | - } | ||
193 | - | ||
194 | - function toggleSelectAll() { | ||
195 | - scope.$table.allSelected = !scope.$table.allSelected; | ||
196 | - angular.forEach(scope.$data, function (group) { | ||
197 | - toggleGroupSelection(group, scope.$table.allSelected); | ||
198 | - }); | ||
199 | - } | ||
200 | - | ||
201 | - function toggleRowSelection(group, row, force) { | ||
202 | - row.$selected = angular.isDefined(force) ? force : !row.$selected; | ||
203 | - var selected = group.filter(function (d) { return d.$selected; }); | ||
204 | - group.$selected = selected.length === group.length; | ||
205 | - | ||
206 | - var groups = 0; | ||
207 | - var selectedGroups = 0; | ||
208 | - angular.forEach(scope.$data, function (group, title) { | ||
209 | - if (title[0] == '$') { | ||
210 | - return; | ||
211 | - } | ||
212 | - groups++; | ||
213 | - if (group.$selected) selectedGroups++; | ||
214 | - }); | ||
215 | - scope.$table.allSelected = groups === selectedGroups; | ||
216 | - } | ||
217 | - | ||
218 | - function toggleGroupSelection(group, force) { | ||
219 | - if (angular.isDefined(force)) { | ||
220 | - group.$selected = force; | ||
221 | - } else { | ||
222 | - group.$selected = !group.$selected; | ||
223 | - } | ||
224 | - angular.forEach(group, function (row) { | ||
225 | - row.$selected = group.$selected; | ||
226 | - }); | ||
227 | - | ||
228 | - if (!angular.isDefined(force)) { | ||
229 | - var groups = 0; | ||
230 | - var selectedGroups = 0; | ||
231 | - angular.forEach(scope.$data, function (group, title) { | ||
232 | - if (title[0] == '$') { | ||
233 | - return; | ||
234 | - } | ||
235 | - groups++; | ||
236 | - if (group.$selected) selectedGroups++; | ||
237 | - }); | ||
238 | - debugger; | ||
239 | - scope.$table.allSelected = groups === selectedGroups; | ||
240 | - } | ||
241 | - } | ||
242 | - | ||
243 | - function setAreAllSelected() { | ||
244 | - scope.$table.allSelected = false; | ||
245 | - } | ||
246 | - | ||
247 | - function sort(col) { | ||
248 | - //multisort | ||
249 | - var currentSort = scope.$sorting[0]; | ||
250 | - if (col == currentSort) { | ||
251 | - scope.$sorting[0] = '-' + col; | ||
252 | - } else if ('-' + col == currentSort) { | ||
253 | - scope.$sorting[0] = col; | ||
254 | - } else { | ||
255 | - scope.$sorting.length = 0; | ||
256 | - scope.$sorting.push(col); | ||
257 | - } | ||
258 | - } | ||
259 | - | ||
260 | - function getSortingClass(col) { | ||
261 | - if (col == scope.$sorting[0]) { | ||
262 | - return 'icon-Arrow-Down2 brand-primary'; | ||
263 | - } | ||
264 | - else if ('-' + col == scope.$sorting[0]) { | ||
265 | - return 'icon-Arrow-Up2 brand-primary'; | ||
266 | - } else { | ||
267 | - return 'icon-Arrow-Down'; | ||
268 | - } | ||
269 | - } | ||
270 | - | ||
271 | - function reset() { | ||
272 | - scope.$filtering = externalSearch || { | ||
273 | - $: '' | ||
274 | - } | ||
275 | - scope.$sorting = []; | ||
276 | - | ||
277 | - //TODO: Deselect ALL | ||
278 | - | ||
279 | - scope.$columns.length = 0; | ||
280 | - [].push.apply(scope.$columns, generateColumns(scope.$schema)); | ||
281 | - } | ||
282 | - | ||
283 | - function buildAccessor(fieldName) { | ||
284 | - console.log('return row.' + fieldName + ';'); | ||
285 | - window.count = window.count || 0; | ||
286 | - return new Function('row', 'return row.' + fieldName + ';'); | ||
287 | - } | ||
288 | - | ||
289 | - function configureColumns() { | ||
290 | - $modal.open({ | ||
291 | - template: '' + | ||
292 | - '<div class="modal-header">' + | ||
293 | - '<button class="close" type="button" ng-click="$close()"><i class="icon-Close"></i></button>' + | ||
294 | - '<h3 class="modal-title">Customize Columns</h3>' + | ||
295 | - '</div>' + | ||
296 | - '<div class="modal-body">' + | ||
297 | - '<div ng-repeat="column in columns">' + | ||
298 | - '<a ng-click="moveUp(column)" ng-hide="$first"><i class="icon-Arrow-UpinCircle brand-primary"></i></a>' + | ||
299 | - ' {{column.title}}' + | ||
300 | - ' <a ng-click="moveDown(column)" ng-hide="$last"><i class="icon-Arrow-DowninCircle brand-primary"></i></a>' + | ||
301 | - '<div class="checkbox pull-right m0">' + | ||
302 | - '<input type="checkbox" id="columncustomise{{::$index}}" ng-model="column.visible" ng-checked="column.visible" />' + | ||
303 | - '<label for="columncustomise{{::$index}}"></label>' + | ||
304 | - '</div><br class="clearfix">' + | ||
305 | - '</div>' + | ||
306 | - '</div>', | ||
307 | - controller: function ($scope, columns) { | ||
308 | - $scope.columns = columns; | ||
309 | - $scope.moveUp = function (column) { | ||
310 | - var index = $scope.columns.indexOf(column); | ||
311 | - move(index, index - 1); | ||
312 | - } | ||
313 | - $scope.moveDown = function (column) { | ||
314 | - var index = $scope.columns.indexOf(column); | ||
315 | - move(index, index + 1); | ||
316 | - } | ||
317 | - | ||
318 | - function move(old_index, new_index) { | ||
319 | - $scope.columns.splice(new_index, 0, $scope.columns.splice(old_index, 1)[0]); | ||
320 | - } | ||
321 | - }, | ||
322 | - size: 'sm', | ||
323 | - resolve: { | ||
324 | - columns: function () { | ||
325 | - return scope.$columns | ||
326 | - } | ||
327 | - } | ||
328 | - }); | ||
329 | - } | ||
330 | - } | ||
331 | - | ||
332 | - function compileFn(element, attrs) { | ||
333 | - return linkFn; | ||
334 | - } | ||
335 | - | ||
336 | - return { | ||
337 | - scope: true, | ||
338 | - transclude: true, | ||
339 | - template: function (element, attrs) { | ||
340 | - return '<div class="' + (attrs.wrapperClass || defaults.wrapperClass) + '"><table class="' + (attrs.tableClass || defaults.tableClass) + ' module-table" style="min-width:' + (attrs.minWidth || defaults.minWidth) + '"></table></div>' | ||
341 | - }, | ||
342 | - compile: function (element, attrs) { | ||
343 | - return linkFn; | ||
344 | - } | ||
345 | - }; | ||
346 | - } | ||
347 | - | ||
348 | - function tableTitlebarDirective() { | ||
349 | - return { | ||
350 | - restrict: 'E', | ||
351 | - scope: true, | ||
352 | - replace: true, | ||
353 | - template: function (element, attrs) { | ||
354 | - var template = '' + | ||
355 | - '<thead><tr><th colspan="100" class="table-arrange">'; | ||
356 | - if (attrs.title) { | ||
357 | - template += '<h3 class="table-title">' + attrs.title + '</h3>'; | ||
358 | - } | ||
359 | - if (attrs.showCount) { | ||
360 | - template += '<h3 class="table-title brand-primary">({{$visible.length}} / {{ $data.length }})</h3>'; | ||
361 | - } | ||
362 | - if (attrs.columnsOptions) { | ||
363 | - template += '<div class="columns-options">' + | ||
364 | - '<a href="" ng-click="$table.reset()"><i class="icon-Reset"></i>Reset</a>' + | ||
365 | - '<a href="" ng-click="$table.configureColumns()"><i class="icon-Receipt-2"></i>Arrange</a>' + | ||
366 | - '</div>'; | ||
367 | - } | ||
368 | - template += '<div class="pull-right">' + | ||
369 | - '<pagination class="pagination-sm" style="margin: 0;" total-items="$paging.totalItems" ng-model="$paging.currentPage" items-per-page="$paging.maxPerPage" boundary-links="true" max-size="5"></pagination>' + | ||
370 | - '</div>'; | ||
371 | - if (attrs.search) { | ||
372 | - template += '<input type="text" class="form-control pull-right" style="width:300px" placeholder="Search.." ng-model="$filtering.$" />'; | ||
373 | - } | ||
374 | - template += '</th></tr></thead>' | ||
375 | - return template; | ||
376 | - } | ||
377 | - } | ||
378 | - } | ||
379 | - | ||
380 | - function tableHeadingDirective() { | ||
381 | - var defaults = { | ||
382 | - } | ||
383 | - return { | ||
384 | - restrict: 'E', | ||
385 | - scope: true, | ||
386 | - replace: true, | ||
387 | - template: function (element, attrs) { | ||
388 | - var tmpl = '' + | ||
389 | - '<thead><tr>' + | ||
390 | - '<th ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
391 | - '<div class="checkbox"><input type="checkbox" id="table-group-check" ng-click="$table.toggleSelectAll()" ng-checked="$table.allSelected"/><label for="table-group-check"></label></div>' + | ||
392 | - | ||
393 | - '</th>' + | ||
394 | - '<th ng-repeat="$column in $columns | filter: { visible: true }" class="module-table-head">' + | ||
395 | - '<div><i ng-class="$column.icon"></i> {{ ::$column.title }}' + | ||
396 | - '<span class="table-sort"><a href="" ng-click="$table.sort($column.key)"><i ng-class="$table.getSortingClass($column.key)"></i></a></span>' + | ||
397 | - '</div>' + //add filter and search menu | ||
398 | - '</th>' + | ||
399 | - '<th ng-if="::$table.actionColumn" style="text-align:center;">' + | ||
400 | - 'Actions' + | ||
401 | - '</th>' + | ||
402 | - '</tr>'; | ||
403 | - tmpl += '</thead>'; | ||
404 | - return tmpl; | ||
405 | - } | ||
406 | - }; | ||
407 | - } | ||
408 | - | ||
409 | - tableDataRowsDirective.$inject = ['$parse', 'Model']; | ||
410 | - function tableDataRowsDirective($parse, Model) { | ||
411 | - return { | ||
412 | - restrict: 'E', | ||
413 | - scope: true, | ||
414 | - replace: true, | ||
415 | - template: function (element, attrs) { | ||
416 | - var tmp = '' + | ||
417 | - '<tbody ng-repeat="(title, group) in $data track by title">' + | ||
418 | - '<tr ng-hide="title == \'undefined\'">' + | ||
419 | - '<td ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
420 | - '<div class="checkbox"><input id="group-check-{{::title}}" type="checkbox" ng-click="$table.toggleGroupSelection(group)" ng-checked="group.$selected"/><label for="group-check-{{::title}}"></label></div>' + | ||
421 | - '</td>' + | ||
422 | - '<td colspan="1000"><b><u>{{ title }}</u></b></td>' + | ||
423 | - '</tr>' + | ||
424 | - '<tr ng-repeat="$row in group track by $row.Id">' + | ||
425 | - '<td ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
426 | - '<div class="checkbox"><input id="table-check-{{::title}}{{::$index}}" type="checkbox" ng-click="$table.toggleRowSelection(group, $row)" ng-checked="$row.$selected"/><label for="table-check-{{::title}}{{::$index}}"></label></div>' + | ||
427 | - '</td>' + | ||
428 | - '<td ng-repeat="$column in $columns | filter: { visible: true } track by $column.key">' + | ||
429 | - '{{$column.accessor($row)}}' + | ||
430 | - '</td>' + | ||
431 | - '<td ng-if="::$table.actionColumn" style="text-align:center;" bind-html-compile="$table.actionColumn.html">' + | ||
432 | - '</td>' + | ||
433 | - '</tr>' + | ||
434 | - '</tbody>'; | ||
435 | - return tmp; | ||
436 | - }, | ||
437 | - compile: function (element, attrs) { | ||
438 | - var selectionElement = _findSelectionColumn(element); | ||
439 | - var actionsElement = _findActionColumn(element); | ||
440 | - | ||
441 | - return link; | ||
442 | - | ||
443 | - function link(scope, element, attrs) { | ||
444 | - scope.$table.actionColumn = actionsElement; | ||
445 | - scope.$table.selectionColumn = selectionElement; | ||
446 | - scope.$table.getCellValue = getCellValue; | ||
447 | - | ||
448 | - function getCellValue(row, col) { | ||
449 | - console.log('GetCellValue is depreciated for performance, please use "$column.accessor($row)" instead, functions are now precompilied;'); | ||
450 | - if (typeof col.binding === 'string') | ||
451 | - return $parse(col.binding)(row); | ||
452 | - else if (angular.isFunction(col.binding)) | ||
453 | - return col.binding(row, col); | ||
454 | - else | ||
455 | - return ''; | ||
456 | - } | ||
457 | - } | ||
458 | - } | ||
459 | - } | ||
460 | - | ||
461 | - function _findActionColumn(element) { | ||
462 | - var actionsElement = jQuery(element.context).find('table-actions'); | ||
463 | - if (actionsElement.length) { | ||
464 | - return { | ||
465 | - html: actionsElement.html() | ||
466 | - }; | ||
467 | - } | ||
468 | - return false; | ||
469 | - } | ||
470 | - | ||
471 | - function _findSelectionColumn(element) { | ||
472 | - var selectionElement = jQuery(element.context).find('table-selection'); | ||
473 | - if (selectionElement.length) { | ||
474 | - return { | ||
475 | - html: selectionElement.html() | ||
476 | - }; | ||
477 | - } | ||
478 | - return false; | ||
479 | - } | ||
480 | - } | ||
481 | - | ||
482 | - function tableFooterDirective() { | ||
483 | - return { | ||
484 | - restrict: 'E', | ||
485 | - scope: true, | ||
486 | - replace: true, | ||
487 | - template: function (element, attrs) { | ||
488 | - var template = '' + | ||
489 | - '<tfoot><tr><th colspan="100" class="table-arrange">'; | ||
490 | - if (attrs.title) { | ||
491 | - template += '<h3 class="table-title">' + attrs.title + '</h3>'; | ||
492 | - } | ||
493 | - if (attrs.showCount) { | ||
494 | - template += '<b class="brand-primary">(showing {{$paging.maxPerPage}} from {{ $paging.totalItems }})</b>'; | ||
495 | - } | ||
496 | - if (attrs.columnsOptions) { | ||
497 | - template += '<div class="columns-options">' + | ||
498 | - '<a href="" ng-click="$table.reset()"><i class="icon-Reset"></i>Reset</a>' + | ||
499 | - '<a href="" ng-click="$table.configureColumns()"><i class="icon-Receipt-2"></i>Arrange</a>' + | ||
500 | - '</div>'; | ||
501 | - } | ||
502 | - template += '<div class="pull-right">' + | ||
503 | - '<pagination class="pagination-sm" style="margin: 0;" total-items="$paging.totalItems" ng-model="$paging.currentPage" items-per-page="$paging.maxPerPage" boundary-links="true" max-size="5"></pagination>' + | ||
504 | - '</div>'; | ||
505 | - if (attrs.search) { | ||
506 | - template += '<input type="text" class="form-control pull-right" style="width:300px" placeholder="Search.." ng-model="$filtering.$" />'; | ||
507 | - } | ||
508 | - template += '</th></tr></tfoot>' | ||
509 | - return template; | ||
510 | - } | ||
511 | - } | ||
512 | - } | ||
513 | - | ||
514 | - softFilter.$inject = ['$filter']; | ||
515 | - function softFilter($filter) { | ||
516 | - return function (array, filteringConfig) { | ||
517 | - var filterFn = $filter('filter'); | ||
518 | - var filtered = filterFn(array, filteringConfig); | ||
519 | - for (var i = 0; i < array.length; i++) { | ||
520 | - var target = array[i]; | ||
521 | - if (filtered.indexOf(target) > -1) { | ||
522 | - target.$filtered = true; | ||
523 | - } else { | ||
524 | - target.$filtered = false; | ||
525 | - } | ||
526 | - } | ||
527 | - return array; | ||
528 | - } | ||
529 | - } | ||
530 | - | ||
531 | - function pageGroupFilter() { | ||
532 | - return function (groups, pagingConfig) { | ||
533 | - var newGroups = {}; | ||
534 | - var skip = (pagingConfig.currentPage - 1) * pagingConfig.maxPerPage; | ||
535 | - var take = pagingConfig.maxPerPage; | ||
536 | - | ||
537 | - if (angular.isArray(groups)) { | ||
538 | - newGroups.undefined = groups.slice(skip, skip + take); | ||
539 | - } else { | ||
540 | - var groupNames = []; | ||
541 | - for (var key in groups) { | ||
542 | - if (groups.hasOwnProperty(key) && key[0] != '$') { | ||
543 | - groupNames.push(key); | ||
544 | - } | ||
545 | - } | ||
546 | - groupNames.sort(); | ||
547 | - | ||
548 | - angular.forEach(groupNames, function (title) { | ||
549 | - var values = groups[title]; | ||
550 | - if (take <= 0) { | ||
551 | - return; | ||
552 | - } else if (skip > values.length) { | ||
553 | - skip -= values.length; | ||
554 | - return; | ||
555 | - } else if (skip > 0) { | ||
556 | - values.splice(0, skip); | ||
557 | - skip = 0; | ||
558 | - } | ||
559 | - | ||
560 | - if (take >= values.length) { | ||
561 | - newGroups[title] = values; | ||
562 | - take -= values.length; | ||
563 | - } else { | ||
564 | - newGroups[title] = values.slice(0, take); | ||
565 | - take = 0; | ||
566 | - } | ||
567 | - }); | ||
568 | - } | ||
569 | - return newGroups; | ||
570 | - }; | ||
571 | - } | ||
572 | - | ||
573 | - function pagingFilter() { | ||
574 | - return function (array, pagingConfig) { | ||
575 | - if (array.length > pagingConfig.minimum) { | ||
576 | - | ||
577 | - } else { | ||
578 | - return array; | ||
579 | - } | ||
580 | - } | ||
581 | - } | ||
582 | - | ||
583 | - function publishFilter() { | ||
584 | - return function (array, target) { | ||
585 | - if (angular.isArray(target)) { | ||
586 | - target.length = 0; | ||
587 | - [].push.apply(target, array); | ||
588 | - } | ||
589 | - return array; | ||
590 | - } | ||
591 | - } | ||
592 | -})(angular); | ||
593 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/filters/utility.filter.js
@@ -1,110 +0,0 @@ | @@ -1,110 +0,0 @@ | ||
1 | -(function(angular){ | ||
2 | - var module = angular.module('framework.filters.utility',[]); | ||
3 | - | ||
4 | - module.filter('RemoveSpaces', removeSpaces); | ||
5 | - module.filter('Truncate', truncate); | ||
6 | - module.filter('AbbrValue', abbrValue); | ||
7 | - module.filter('Countdown', countdown); | ||
8 | - | ||
9 | - | ||
10 | - function removeSpaces() { | ||
11 | - return function (text) { | ||
12 | - return text.replace(/\s/g, ''); | ||
13 | - } | ||
14 | - } | ||
15 | - | ||
16 | - function truncate () { | ||
17 | - return function (text, length, end) { | ||
18 | - if (isNaN(length)) | ||
19 | - length = 10; | ||
20 | - if (end === undefined) | ||
21 | - end = "..."; | ||
22 | - if (text.length <= length || text.length - end.length <= length) | ||
23 | - { return text; } | ||
24 | - else | ||
25 | - { return String(text).substring(0, length - end.length) + end; } | ||
26 | - } | ||
27 | - } | ||
28 | - | ||
29 | - function abbrValue() { | ||
30 | - return function (val) { | ||
31 | - | ||
32 | - return Math.abs(Number(val)) >= 1.0e+9 | ||
33 | - | ||
34 | - ? Math.round(Math.abs((Number(val)) / 1.0e+9)*10)/10 + "b" | ||
35 | - // Six Zeroes for Millions | ||
36 | - : Math.abs(Number(val)) >= 1.0e+6 | ||
37 | - | ||
38 | - ? Math.round(Math.abs((Number(val)) / 1.0e+6)*10)/10 + "m" | ||
39 | - // Three Zeroes for Thousands | ||
40 | - : Math.abs(Number(val)) >= 1.0e+3 | ||
41 | - | ||
42 | - ? Math.round(Math.abs((Number(val)) / 1.0e+3)*10)/10 + "k" | ||
43 | - | ||
44 | - : Math.abs(Number(val)); | ||
45 | - } | ||
46 | - } | ||
47 | - | ||
48 | - function countdown() { | ||
49 | - return function (input) { | ||
50 | - var substitute = function (stringOrFunction, number, strings) { | ||
51 | - var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, dateDifference) : stringOrFunction; | ||
52 | - var value = (strings.numbers && strings.numbers[number]) || number; | ||
53 | - return string.replace(/%d/i, value); | ||
54 | - }, | ||
55 | - nowTime = (new Date()).getTime(), | ||
56 | - date = (new Date(input)).getTime(), | ||
57 | - allowFuture = true, | ||
58 | - strings = { | ||
59 | - prefixAgo: null, | ||
60 | - prefixFromNow: null, | ||
61 | - suffixAgo: "ago", | ||
62 | - suffixFromNow: "",//"from now" | ||
63 | - seconds: "less than a minute", | ||
64 | - minute: "a minute", | ||
65 | - minutes: "%d minutes", | ||
66 | - hour: "an hour", | ||
67 | - hours: "%d hours", | ||
68 | - day: "a day", | ||
69 | - days: "%d days", | ||
70 | - month: "a month", | ||
71 | - months: "%d months", | ||
72 | - year: "a year", | ||
73 | - years: "%d years" | ||
74 | - }, | ||
75 | - dateDifference = nowTime - date, | ||
76 | - words, | ||
77 | - seconds = Math.abs(dateDifference) / 1000, | ||
78 | - minutes = seconds / 60, | ||
79 | - hours = minutes / 60, | ||
80 | - days = hours / 24, | ||
81 | - years = days / 365, | ||
82 | - separator = strings.wordSeparator === undefined ? " " : strings.wordSeparator, | ||
83 | - prefix = strings.prefixAgo, | ||
84 | - suffix = strings.suffixAgo; | ||
85 | - | ||
86 | - if (allowFuture) { | ||
87 | - if (dateDifference < 0) { | ||
88 | - prefix = strings.prefixFromNow; | ||
89 | - suffix = strings.suffixFromNow; | ||
90 | - } | ||
91 | - } | ||
92 | - | ||
93 | - words = seconds < 45 && substitute(strings.seconds, Math.round(seconds), strings) || | ||
94 | - seconds < 90 && substitute(strings.minute, 1, strings) || | ||
95 | - minutes < 45 && substitute(strings.minutes, Math.round(minutes), strings) || | ||
96 | - minutes < 90 && substitute(strings.hour, 1, strings) || | ||
97 | - hours < 24 && substitute(strings.hours, Math.round(hours), strings) || | ||
98 | - hours < 42 && substitute(strings.day, 1, strings) || | ||
99 | - days < 30 && substitute(strings.days, Math.round(days), strings) || | ||
100 | - days < 45 && substitute(strings.month, 1, strings) || | ||
101 | - days < 365 && substitute(strings.months, Math.round(days / 30), strings) || | ||
102 | - years < 1.5 && substitute(strings.year, 1, strings) || | ||
103 | - substitute(strings.years, Math.round(years), strings); | ||
104 | - | ||
105 | - return $.trim([prefix, words, suffix].join(separator)); | ||
106 | - } | ||
107 | - } | ||
108 | - | ||
109 | - | ||
110 | -})(angular); | ||
111 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/breadcrumb/breadcrumb.controller.js
@@ -1,48 +0,0 @@ | @@ -1,48 +0,0 @@ | ||
1 | -(function (window, angular) { | ||
2 | - var app = angular.module("framework.UI.breadcrumb", []); | ||
3 | - | ||
4 | - app.controller('BarController', barController); | ||
5 | - | ||
6 | - barController.$inject = ['$scope', '$state', '$modal', '$rootScope']; | ||
7 | - function barController($scope, $state, $modal, $rootScope) { | ||
8 | - $scope.breadcrumbs = []; | ||
9 | - $scope.helpAvailable = null; | ||
10 | - $scope.showHelp = showHelp; | ||
11 | - | ||
12 | - function showHelp() { | ||
13 | - if ($scope.helpAvailable) | ||
14 | - $modal.open({ | ||
15 | - templateUrl: $scope.helpAvailable, | ||
16 | - }); | ||
17 | - } | ||
18 | - | ||
19 | - $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { | ||
20 | - _parseStateName(toState.name); | ||
21 | - $scope.helpAvailable = toState.hasHelp; | ||
22 | - }); | ||
23 | - | ||
24 | - $scope.helpAvailable = $state.current.hasHelp; | ||
25 | - _parseStateName($state.current.name); | ||
26 | - | ||
27 | - function _parseStateName(stateName) { | ||
28 | - var parts = stateName.split('.'); | ||
29 | - var breadcrumbs = []; | ||
30 | - for (var i = 0; i < parts.length; i++) { | ||
31 | - var p = parts[i]; | ||
32 | - if (p === "root") | ||
33 | - continue; | ||
34 | - var full = parts.slice(0, i + 1).join('.'); | ||
35 | - breadcrumbs.push({ | ||
36 | - name: parts[i], | ||
37 | - $html: _generateBreadcrumbHtml(p, full) | ||
38 | - }); | ||
39 | - } | ||
40 | - $scope.breadcrumbs = breadcrumbs; | ||
41 | - } | ||
42 | - | ||
43 | - function _generateBreadcrumbHtml(name, state) { | ||
44 | - var template = '<a ui-sref="' + state + '" >' + name + '</a>'; | ||
45 | - return template; | ||
46 | - } | ||
47 | - }; | ||
48 | -})(window, angular); | ||
49 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/breadcrumb/breadcrumb.partial.html
@@ -1,8 +0,0 @@ | @@ -1,8 +0,0 @@ | ||
1 | -<div ng-controller="BarController"> | ||
2 | - <ol class="breadcrumb"> | ||
3 | - <li ng-repeat="item in breadcrumbs" ui-sref-active="active" bind-html-compile="item.$html"></li> | ||
4 | - </ol> | ||
5 | - <span class="module-help" ng-if="helpAvailable"> | ||
6 | - <a href="" ng-click="showHelp()"><i class="icon-Assistant"></i>Help</a> | ||
7 | - </span> | ||
8 | -</div> |
common_components/layouts/documentsview/documents-view.controller.js
@@ -1,12 +0,0 @@ | @@ -1,12 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.documents',[]); | ||
3 | - | ||
4 | - module.controller('DocumentsController', DocumentsController); | ||
5 | - | ||
6 | - DocumentsController.$inject = ['$scope', 'rData', '$state']; | ||
7 | - function DocumentsController($scope, rData, $state) { | ||
8 | - $scope.documents = rData; | ||
9 | - $scope.selectedDocument=rData[0]; | ||
10 | - } | ||
11 | - | ||
12 | -})(angular); | ||
13 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/documentsview/documents-view.partial.html
@@ -1,36 +0,0 @@ | @@ -1,36 +0,0 @@ | ||
1 | -<div class="document-options"> | ||
2 | - <a href="" class="btn btn-xs btn-primary"><i class="icon-Add-File"></i> Add New</a> | ||
3 | -</div> | ||
4 | -<div class="row"> | ||
5 | - <div class="col-md-4"> | ||
6 | - <div class="panel panel-default"> | ||
7 | - <div class="panel-heading"> | ||
8 | - <h3 class="panel-title">Documents</h3> | ||
9 | - </div> | ||
10 | - <div class="panel-body"> | ||
11 | - <div ng-repeat="doc in documents"> | ||
12 | - <div class="document" ng-click="$parent.selectedDocument=doc" ng-class="(selectedDocument==doc)?'active':''"> | ||
13 | - <small class="pull-right grey">{{doc.ExpiryDate | countdown}}</small> | ||
14 | - <strong>{{doc.Name}}</strong><br /> | ||
15 | - {{doc.IdentificationNo}} | ||
16 | - <small class="pull-right grey mt5"><i class="icon-Pencil"></i></small> | ||
17 | - </div> | ||
18 | - </div> | ||
19 | - </div> | ||
20 | - </div> | ||
21 | - </div> | ||
22 | - <div class="col-md-8"> | ||
23 | - <div class="panel panel-default"> | ||
24 | - <div class="panel-heading"> | ||
25 | - <h3 class="panel-title">Viewer</h3> | ||
26 | - </div> | ||
27 | - <div class="panel-body document-viewer"> | ||
28 | - <div class="document-viewer-options"> | ||
29 | - <a href="" class="btn-icon"><i class="icon-Download"></i>Save</a> | ||
30 | - <a href="" class="btn-icon"><i class="icon-Close-Window"></i>Delete</a> | ||
31 | - </div> | ||
32 | - <img src="{{selectedDocument.DocumentURL}}" width="500px" /> | ||
33 | - </div> | ||
34 | - </div> | ||
35 | - </div> | ||
36 | -</div> | ||
37 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-base.layout.html
@@ -1,11 +0,0 @@ | @@ -1,11 +0,0 @@ | ||
1 | -<div class="module"> | ||
2 | - <div ui-view name="options-area"></div> | ||
3 | - <div class="row"> | ||
4 | - <div class="col-md-12 col-lg-9 module-primary"> | ||
5 | - <div ui-view name="view-area"></div> | ||
6 | - </div> | ||
7 | - <div class="visible-lg col-lg-3 module-secondary"> | ||
8 | - <div ui-view name="stats-area"></div> | ||
9 | - </div> | ||
10 | - </div> | ||
11 | -</div> | ||
12 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-cards.controller.js
@@ -1,37 +0,0 @@ | @@ -1,37 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.UI.module',[]); | ||
3 | - | ||
4 | - module.controller('ModuleCardsController', moduleCardsController); | ||
5 | - | ||
6 | - moduleCardsController.$inject = ['$scope', 'rData', 'rNavTo','rAccessors', '$state', '$interval', '$timeout']; | ||
7 | - function moduleCardsController($scope, rData, rNavTo, rAccessors, $state, $interval, $timeout) { | ||
8 | - $scope.rawItems = rData; | ||
9 | - $scope.accessors = rAccessors; | ||
10 | - $scope.rNavTo = rNavTo; | ||
11 | - $scope.showScore = false; | ||
12 | - $scope.chosenGroup = null; | ||
13 | - $scope.cardLimit = 2; | ||
14 | - | ||
15 | - $scope.groups = {}; | ||
16 | - rData = rData.sort(function(a,b){ | ||
17 | - var valA = rAccessors.Title(a), valB = rAccessors.Title(b); | ||
18 | - if(valA < valB) { | ||
19 | - return -1; | ||
20 | - } else if (valA > valB){ | ||
21 | - return 1; | ||
22 | - } else | ||
23 | - return 0; | ||
24 | - }); | ||
25 | - | ||
26 | - var i; | ||
27 | - | ||
28 | - for(i = 0; i < rData.length; i++) { | ||
29 | - var title = rAccessors.Group(rData[i]); | ||
30 | - if($scope.groups[title]) | ||
31 | - $scope.groups[title].push(rData[i]); | ||
32 | - else | ||
33 | - $scope.groups[title] = [rData[i]]; | ||
34 | - } | ||
35 | - } | ||
36 | - | ||
37 | -})(angular); | ||
38 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-cards.partial.html
@@ -1,26 +0,0 @@ | @@ -1,26 +0,0 @@ | ||
1 | -<div class="cards-wrapper"> | ||
2 | - <div class="cards-view-options"> | ||
3 | - <div class="row"> | ||
4 | - <div class="col-sm-8 col-xs-8"> | ||
5 | - <div class="group-filters"> | ||
6 | - <a class="group-options" ng-click="chosenGroup = null" ng-class="(chosenGroup == null)?'active':''">All</a> | ||
7 | - <a class="group-options" ng-click="$parent.chosenGroup = title" ng-class="($parent.chosenGroup == title)?'active':''" ng-repeat="(title, items) in groups">{{title}}({{(items | filter:searchTerm).length }})</a> | ||
8 | - </div> | ||
9 | - </div> | ||
10 | - <div class="col-sm-4 col-xs-4 text-right"> | ||
11 | - <a class="btn btn-primary btn-xs" ng-click="showScore=!showScore" ng-bind="(showScore)? 'Hide Scores':'Show Scores'" ng-class="(showScore)?'active':''">Show Scores</a> | ||
12 | - </div> | ||
13 | - </div> | ||
14 | - </div> | ||
15 | - <div ng-repeat="(title, items) in ::groups track by title" ng-if="!chosenGroup || chosenGroup==title"> | ||
16 | - <h3 class="section-title" ng-show="results.length > 0">{{title}}</h3> | ||
17 | - | ||
18 | - <card ng-repeat="item in items | filter:searchTerm as results track by item.Id" showscore="{{showScore}}" ></card> | ||
19 | - | ||
20 | - <br class="clearfix" ng-show="results.length > 0" /> | ||
21 | - </div> | ||
22 | - <div ng-if="rawItems.length === 0"> | ||
23 | - No Items Added Yet. | ||
24 | - </div> | ||
25 | - <br class="clearfix" /> | ||
26 | -</div> | ||
27 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-item.controller.js
@@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.UI.module'); | ||
3 | - | ||
4 | - module.controller('ModuleItemViewController', moduleItemViewController); | ||
5 | - | ||
6 | - moduleItemViewController.$inject = ['$scope', 'rTabs', 'rData', 'rAccessors']; | ||
7 | - | ||
8 | - function moduleItemViewController($scope, rTabs, rData, rAccessors) { | ||
9 | - $scope.item = rData[0]; | ||
10 | - $scope.accessors = rAccessors; | ||
11 | - $scope.tabDefs = rTabs; | ||
12 | - } | ||
13 | - | ||
14 | -})(angular); | ||
15 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-item.layout.html
@@ -1,21 +0,0 @@ | @@ -1,21 +0,0 @@ | ||
1 | -<div class="module-item"> | ||
2 | - <div class="module-item-cover"></div> | ||
3 | - <div class="module-item-nav-bar"> | ||
4 | - <card class="module-item-card" allow-click="false" show-score="false" class="single pull-left" show-title="false" show-subtitle="false"></card> | ||
5 | - <div class="module-item-brief"> | ||
6 | - <h3>{{accessors.Title(item)}}</h3> | ||
7 | - <h4>{{accessors.SubTitle(item)}}</h4> | ||
8 | - </div> | ||
9 | - <tabs data="tabDefs" type="tabs" justified="false"></tabs> | ||
10 | - </div> | ||
11 | - <div class="module-item-options"> | ||
12 | - <div ui-view name="options-area"></div> | ||
13 | - </div> | ||
14 | - <div class="module-item-content"> | ||
15 | - <div class="row"> | ||
16 | - <div class="col-md-12"> | ||
17 | - <ui-view class="tab-content"></ui-view> | ||
18 | - </div> | ||
19 | - </div> | ||
20 | - </div> | ||
21 | -</div> | ||
22 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-table.controller.js
@@ -1,22 +0,0 @@ | @@ -1,22 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.UI.module'); | ||
3 | - | ||
4 | - module.controller('ModuleTableController', moduleCardsController); | ||
5 | - | ||
6 | - moduleCardsController.$inject = ['$scope', 'rData', 'rNavTo', 'rSchema', '$state', '$q']; | ||
7 | - function moduleCardsController($scope, rData, rNavTo, rSchema, $state, $q) { | ||
8 | - $scope.items = rData; | ||
9 | - | ||
10 | - function n() { | ||
11 | - console.log(arguments); | ||
12 | - return $q.when(rData); | ||
13 | - }; | ||
14 | - | ||
15 | - $scope.viewItem = viewItem; | ||
16 | - $scope.Schema = rSchema; | ||
17 | - function viewItem(item) { | ||
18 | - $state.go(rNavTo, { Id: 11 }); | ||
19 | - } | ||
20 | - } | ||
21 | - | ||
22 | -})(angular); | ||
23 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/module/module-table.partial.html
@@ -1,17 +0,0 @@ | @@ -1,17 +0,0 @@ | ||
1 | -<table-for datasource="items" class="table table-condensed table-hover" schema="{{Schema}}" filtering="searchTerm" sorting="" paging="" grouping="grouping" wrapper-class="" table-class=""> | ||
2 | - <table-titlebar columns-options="true" paging="true"></table-titlebar> | ||
3 | - <table-heading sorting="true"> | ||
4 | - <!--<table-cell column=""></table-cell>--> <!-- for overriding --> | ||
5 | - </table-heading> | ||
6 | - <table-data-rows> | ||
7 | - <table-selection></table-selection> | ||
8 | - <!--<table-cell column=""></table-cell>--> <!-- for overriding --> | ||
9 | - <!--<table-expand-template></table-expand-template>--> <!-- for expanding --> | ||
10 | - <table-actions> | ||
11 | - <a class="btn btn-xs btn-primary" ng-click="viewItem(item)"><i class="icon-D-Eyeglasses2"></i>View</a> | ||
12 | - </table-actions> | ||
13 | - </table-data-rows> | ||
14 | - <table-footer paging="true"> | ||
15 | - | ||
16 | - </table-footer> | ||
17 | -</table-for> | ||
18 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/structure/page.controller.js
@@ -1,12 +0,0 @@ | @@ -1,12 +0,0 @@ | ||
1 | -(function (window, angular) { | ||
2 | - var app = angular.module("framework.UI.structure", []); | ||
3 | - | ||
4 | - app.controller('PageController', pageController); | ||
5 | - | ||
6 | - pageController.$inject = ['$scope', '$interval']; | ||
7 | - | ||
8 | - function pageController($scope, $interval) { | ||
9 | - setupUIElements(); | ||
10 | - }; | ||
11 | - | ||
12 | -})(window, angular); | ||
13 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/structure/page.layout.html
@@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
1 | -<div id="application-layout" ng-controller="PageController"> | ||
2 | - <div id="sidebar-left" ui-view name="sidebar-left"></div> | ||
3 | - <div id="topbar" ui-view name="topbar"></div> | ||
4 | - <div id="content-wrapper"> | ||
5 | - <div id="breadcrumb-bar" ng-include="'/common_components/layouts/breadcrumb/breadcrumb.partial.html'"> | ||
6 | - | ||
7 | - </div> | ||
8 | - <div ui-view name="content-wrapper"> | ||
9 | - | ||
10 | - </div> | ||
11 | - </div> | ||
12 | - <div id="sidebar-toggle"> | ||
13 | - <i class="icon-Align-JustifyAll"></i> | ||
14 | - </div> | ||
15 | - <div id="sidebar-right" ui-view name="sidebar-right"></div> | ||
16 | -</div> | ||
17 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/layouts/table-page/table-page.layout.html
@@ -1,12 +0,0 @@ | @@ -1,12 +0,0 @@ | ||
1 | -<div class="container-fluid tablepage-layout"> | ||
2 | - <div class="row"> | ||
3 | - <div class="col-md-12"> | ||
4 | - <div ui-view name="table-options"></div> | ||
5 | - </div> | ||
6 | - </div> | ||
7 | - <div class="row"> | ||
8 | - <div class="col-md-12"> | ||
9 | - <div ui-view name="table-content"></div> | ||
10 | - </div> | ||
11 | - </div> | ||
12 | -</div> |
common_components/services/ConsoleLoggingProvider.service.js
@@ -1,67 +0,0 @@ | @@ -1,67 +0,0 @@ | ||
1 | -(function () { | ||
2 | - var app = angular.module('framework.services.logging'); | ||
3 | - | ||
4 | - app.service('ConsoleLoggingProvider', ['$window', consoleLoggingProvider]); | ||
5 | - | ||
6 | - function consoleLoggingProvider($window) { | ||
7 | - this.log = log; | ||
8 | - this.debug = debug; | ||
9 | - this.info = info; | ||
10 | - this.warning = warning; | ||
11 | - this.error = error; | ||
12 | - | ||
13 | - function log(level, catagory, msg, others) { | ||
14 | - switch (level) { | ||
15 | - case 1: | ||
16 | - debug(catagory, msg, others); | ||
17 | - break; | ||
18 | - case 2: | ||
19 | - info(catagory, msg, others); | ||
20 | - break; | ||
21 | - case 3: | ||
22 | - warning(catagory, msg, others); | ||
23 | - break; | ||
24 | - case 4: | ||
25 | - error(catagory, msg, exception, others); | ||
26 | - break; | ||
27 | - default: | ||
28 | - debug(catagory, msg, others); | ||
29 | - break; | ||
30 | - } | ||
31 | - } | ||
32 | - | ||
33 | - function debug(catagory, msg, others) { | ||
34 | - var date = new Date(); | ||
35 | - console.debug(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
36 | - angular.forEach(others, function (val, ind) { | ||
37 | - console.debug('additional info ' + ind + ': ', val); | ||
38 | - }); | ||
39 | - } | ||
40 | - | ||
41 | - function info(catagory, msg, others) { | ||
42 | - var date = new Date(); | ||
43 | - console.info(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
44 | - angular.forEach(others, function (val, ind) { | ||
45 | - console.info('additional info ' + ind + ': ', val); | ||
46 | - }); | ||
47 | - } | ||
48 | - | ||
49 | - function warning(catagory, msg, others) { | ||
50 | - var date = new Date(); | ||
51 | - console.warn(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
52 | - angular.forEach(others, function (val, ind) { | ||
53 | - console.warn('additional info ' + ind + ': ', val); | ||
54 | - }); | ||
55 | - } | ||
56 | - | ||
57 | - function error(catagory, msg, exception, others) { | ||
58 | - var date = new Date(); | ||
59 | - console.error(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
60 | - console.error('original exception: ' + exception); | ||
61 | - angular.forEach(others, function (val, ind) { | ||
62 | - console.error('additional info ' + ind + ': ', val); | ||
63 | - }); | ||
64 | - } | ||
65 | - } | ||
66 | - | ||
67 | -})(); | ||
68 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/services/Logger.service.js
@@ -1,139 +0,0 @@ | @@ -1,139 +0,0 @@ | ||
1 | -(function (window, angular) { | ||
2 | - var app = angular.module("framework.services.logging", []); | ||
3 | - | ||
4 | - app.provider('Logger', function () { | ||
5 | - var providers = []; | ||
6 | - var hiddenCatagorys = []; | ||
7 | - var loggingLevel = 1; | ||
8 | - | ||
9 | - this.DEBUG = 1; | ||
10 | - this.INFO = 2; | ||
11 | - this.WARNING = 3; | ||
12 | - this.ERROR = 4; | ||
13 | - | ||
14 | - this.setGlobalLoggingLevel = setGlobalLoggingLevel; | ||
15 | - this.addProvider = addProvider; | ||
16 | - this.hideCatagory = hideCatagory; | ||
17 | - | ||
18 | - function setGlobalLoggingLevel(level) { | ||
19 | - loggingLevel = level; | ||
20 | - } | ||
21 | - | ||
22 | - function addProvider(provider) { | ||
23 | - providers.push(provider); | ||
24 | - } | ||
25 | - | ||
26 | - function hideCatagory(catagory) { | ||
27 | - hiddenCatagorys.push(catagory); | ||
28 | - } | ||
29 | - | ||
30 | - this.$get = buildLoggerService; | ||
31 | - | ||
32 | - buildLoggerService.$inject = ['$injector']; | ||
33 | - function buildLoggerService($injector) { | ||
34 | - var instance = createLogger('Default'); | ||
35 | - this.createLogger = createLogger; | ||
36 | - this.log = instance.log; | ||
37 | - this.debug = instance.debug; | ||
38 | - this.info = instance.info; | ||
39 | - this.warning = instance.warning; | ||
40 | - this.error = instance.error; | ||
41 | - this.DEBUG = 1; | ||
42 | - this.INFO = 2; | ||
43 | - this.WARNING = 3; | ||
44 | - this.ERROR = 4; | ||
45 | - var concreteProviders = []; | ||
46 | - angular.forEach(providers, function (value) { | ||
47 | - if (angular.isObject(value)) { | ||
48 | - concreteProviders.push(value); | ||
49 | - } else if (angular.isFunction(value)) { | ||
50 | - var pro = { | ||
51 | - log: value, | ||
52 | - debug: log.bind(null, 1), | ||
53 | - info: log.bind(null, 2), | ||
54 | - warning: log.bind(null, 3), | ||
55 | - error: log.bind(null, 4) | ||
56 | - }; | ||
57 | - concreteProviders.push(pro); | ||
58 | - } else if (angular.isArray(value)) { | ||
59 | - var pro = $injector.invoke(value, null, { | ||
60 | - Levels: { | ||
61 | - DEBUG: 1, | ||
62 | - INFO: 2, | ||
63 | - WARNING: 3, | ||
64 | - ERROR: 4 | ||
65 | - } | ||
66 | - }); | ||
67 | - concreteProviders.push(pro); | ||
68 | - } else if (typeof value === 'string') { | ||
69 | - var pro = $injector.get(value); | ||
70 | - concreteProviders.push(pro); | ||
71 | - } | ||
72 | - }); | ||
73 | - | ||
74 | - function createLogger(catagory) { | ||
75 | - return new Logger(catagory, concreteProviders, loggingLevel, hiddenCatagorys); | ||
76 | - } | ||
77 | - | ||
78 | - return this; | ||
79 | - } | ||
80 | - }); | ||
81 | - | ||
82 | - function Logger(catagory, providers, loggingLevel, hiddenCatagorys) { | ||
83 | - this.log = log; | ||
84 | - this.debug = debug; | ||
85 | - this.info = info; | ||
86 | - this.warning = warning; | ||
87 | - this.error = error; | ||
88 | - | ||
89 | - function log(level, msg) { | ||
90 | - if (level < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
91 | - return; | ||
92 | - | ||
93 | - var args = Array.prototype.slice.call(arguments, 2); | ||
94 | - angular.forEach(providers, function (provider) { | ||
95 | - provider.log(level, catagory, msg, args); | ||
96 | - }); | ||
97 | - } | ||
98 | - | ||
99 | - function debug(msg) { | ||
100 | - if (1 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
101 | - return; | ||
102 | - | ||
103 | - var args = Array.prototype.slice.call(arguments, 1); | ||
104 | - angular.forEach(providers, function (provider) { | ||
105 | - provider.debug(catagory, msg, args); | ||
106 | - }); | ||
107 | - } | ||
108 | - | ||
109 | - function info(msg) { | ||
110 | - if (2 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
111 | - return; | ||
112 | - | ||
113 | - var args = Array.prototype.slice.call(arguments, 1); | ||
114 | - angular.forEach(providers, function (provider) { | ||
115 | - provider.info(catagory, msg, args); | ||
116 | - }); | ||
117 | - } | ||
118 | - | ||
119 | - function warning(msg) { | ||
120 | - if (3 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
121 | - return; | ||
122 | - | ||
123 | - var args = Array.prototype.slice.call(arguments, 1); | ||
124 | - angular.forEach(providers, function (provider) { | ||
125 | - provider.warning(catagory, msg, args); | ||
126 | - }); | ||
127 | - } | ||
128 | - | ||
129 | - function error(msg, exception) { | ||
130 | - if (4 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
131 | - return; | ||
132 | - | ||
133 | - var args = Array.prototype.slice.call(arguments, 2); | ||
134 | - angular.forEach(providers, function (provider) { | ||
135 | - provider.error(catagory, msg, exception, args); | ||
136 | - }); | ||
137 | - } | ||
138 | - } | ||
139 | -})(window, angular); | ||
140 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/services/Menu.service.js
@@ -1,45 +0,0 @@ | @@ -1,45 +0,0 @@ | ||
1 | -(function (window, angular) { | ||
2 | - var app = angular.module("framework.services.menu", []); | ||
3 | - | ||
4 | - app.provider('MenuService', MenuServiceProvider); | ||
5 | - | ||
6 | - function MenuServiceProvider() { | ||
7 | - var menuItems = []; | ||
8 | - var defaultIcon = 'icon-Align-JustifyAll'; | ||
9 | - var provider = { | ||
10 | - registerMenuItem: registerMenuItem, | ||
11 | - setDefaultIcon: setDefaultIcon, | ||
12 | - $get: getService | ||
13 | - }; | ||
14 | - | ||
15 | - return provider; | ||
16 | - | ||
17 | - function registerMenuItem(menuItem) { | ||
18 | - menuItems.push(menuItem); | ||
19 | - } | ||
20 | - | ||
21 | - function setDefaultIcon(icon) { | ||
22 | - defaultIcon = icon; | ||
23 | - } | ||
24 | - | ||
25 | - function getService() { | ||
26 | - angular.forEach(menuItems, function (mi) { | ||
27 | - mi.$html = _buildTemplate(mi); | ||
28 | - }); | ||
29 | - var service = { | ||
30 | - menuItems: menuItems, | ||
31 | - defaultIcon: defaultIcon | ||
32 | - }; | ||
33 | - return service; | ||
34 | - } | ||
35 | - | ||
36 | - function _buildTemplate(menuItem) { | ||
37 | - var template = '<a ui-sref="' + menuItem.state + '" style="color:white;">' + | ||
38 | - '<i class="{{item.icon ? item.icon : menu.defaultIcon}}"></i>' + | ||
39 | - '{{item.title}}' + | ||
40 | - '</a>'; | ||
41 | - return template; | ||
42 | - } | ||
43 | - | ||
44 | - }; | ||
45 | -})(window, angular); | ||
46 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/services/Model.service.js
@@ -1,300 +0,0 @@ | @@ -1,300 +0,0 @@ | ||
1 | -(function (window, angular) { | ||
2 | - var module = angular.module('framework.services.model', []); | ||
3 | - | ||
4 | - module.provider('Model', modelsProvider); | ||
5 | - //module.service('DataContext', dataService); | ||
6 | - | ||
7 | - function modelsProvider() { | ||
8 | - var schemas = { | ||
9 | - | ||
10 | - }; | ||
11 | - | ||
12 | - this.registerSchema = registerSchema; | ||
13 | - this.$get = buildService; | ||
14 | - | ||
15 | - function registerSchema(name, path, schema) { | ||
16 | - schemas[name] = [path, schema]; | ||
17 | - return this; | ||
18 | - } | ||
19 | - | ||
20 | - buildService.$inject = ['$config', '$http', '$q']; | ||
21 | - function buildService($config, $http, $q) { | ||
22 | - var models = {}; | ||
23 | - | ||
24 | - angular.forEach(schemas, function (value, key) { | ||
25 | - var modelName = key; | ||
26 | - var modelPath = value[0]; | ||
27 | - var modelSchema = value[1]; | ||
28 | - | ||
29 | - models[modelName] = BuildConstructor(modelPath, modelSchema); | ||
30 | - }); | ||
31 | - | ||
32 | - return models; | ||
33 | - | ||
34 | - function Entity(apiEndpoint, schema, values) { | ||
35 | - this.$$apiLocation = apiEndpoint; | ||
36 | - this.$$schema = schema; | ||
37 | - this.$$originalValues = {}; | ||
38 | - this.$$changedValues = {}; | ||
39 | - this.$$foreignModels = {}; | ||
40 | - | ||
41 | - this.$getChanges = getChanges; | ||
42 | - this.$validate = validateEntity; | ||
43 | - this.$save = saveEntity; | ||
44 | - this.$update = updateEntity; | ||
45 | - this.$patch = patchEntity; | ||
46 | - this.$delete = deleteEntity; | ||
47 | - this.$commit = commitEntity; | ||
48 | - this.$rollback = rollbackEntity; | ||
49 | - | ||
50 | - angular.forEach(schema, function (value, key) { | ||
51 | - var fieldName = key, | ||
52 | - fieldDef = value; | ||
53 | - | ||
54 | - if (values[fieldName] !== undefined) { | ||
55 | - if (typeof fieldDef.type === 'string' && values[fieldName] !== null) { | ||
56 | - this.$$originalValues[fieldName] = new models[fieldDef.type](values[fieldName]); | ||
57 | - this.$$foreignModels[fieldName] = fieldDef.type; | ||
58 | - } else { | ||
59 | - this.$$originalValues[fieldName] = values[fieldName]; | ||
60 | - } | ||
61 | - } else { | ||
62 | - this.$$originalValues[fieldName] = fieldDef.defaultValue; | ||
63 | - } | ||
64 | - | ||
65 | - Object.defineProperty(this, fieldName, { | ||
66 | - configurable: false, | ||
67 | - enumerable: true, | ||
68 | - get: fieldDef.calculated || function () { | ||
69 | - return this.$$changedValues.hasOwnProperty(fieldName) ? | ||
70 | - this.$$changedValues[fieldName] : this.$$originalValues[fieldName]; | ||
71 | - }, | ||
72 | - set: function (value) { | ||
73 | - if (angular.isUndefined(fieldDef.editable) || fieldDef.editable) { | ||
74 | - | ||
75 | - this.$$changedValues[fieldName] = value; //CHECK: Cast to correct type?? | ||
76 | - } | ||
77 | - } | ||
78 | - }); | ||
79 | - }, this); | ||
80 | - | ||
81 | - function getChanges() { | ||
82 | - return this.$$changedValues; | ||
83 | - } | ||
84 | - function validateEntity() { | ||
85 | - } //TODO | ||
86 | - function saveEntity() { | ||
87 | - return $http.post($config.API_ENDPOINT + this.$$apiLocation, this); | ||
88 | - } | ||
89 | - function updateEntity() { | ||
90 | - var config = { | ||
91 | - params: { | ||
92 | - id: this.Id | ||
93 | - } | ||
94 | - }; | ||
95 | - return $http.put($config.API_ENDPOINT + this.$$apiLocation, this, config); | ||
96 | - } | ||
97 | - function patchEntity(skipSubObjects) { | ||
98 | - var self = this; | ||
99 | - var delta = angular.extend({ Id: this.Id }, this.$getChanges()); | ||
100 | - var config = { | ||
101 | - params: { | ||
102 | - id: this.Id | ||
103 | - } | ||
104 | - }; | ||
105 | - var request = $http.patch($config.API_ENDPOINT + this.$$apiLocation, delta, config); | ||
106 | - request.success(function () { | ||
107 | - self.$commit(true); | ||
108 | - }); | ||
109 | - return request; | ||
110 | - } | ||
111 | - function deleteEntity() { | ||
112 | - var config = { | ||
113 | - params: { | ||
114 | - id: this.Id | ||
115 | - } | ||
116 | - }; | ||
117 | - return $http.delete($config.API_ENDPOINT + this.$$apiLocation, config); | ||
118 | - } | ||
119 | - function commitEntity(skipSubObjects) { | ||
120 | - angular.forEach(this.$$changedValues, function (value, key) { | ||
121 | - var fieldName = key, | ||
122 | - fieldValue = value; | ||
123 | - this.$$originalValues[fieldName] = fieldValue | ||
124 | - }, this); | ||
125 | - this.$$changedValues = {}; | ||
126 | - | ||
127 | - if (skipSubObjects) return; | ||
128 | - angular.forEach(this.$$foreignModels, function (value, key) { | ||
129 | - this[key].$commit(); | ||
130 | - }, this); | ||
131 | - } | ||
132 | - function rollbackEntity(skipSubObjects) { | ||
133 | - this.$$changedValues = {}; | ||
134 | - | ||
135 | - if (skipSubObjects) return; | ||
136 | - angular.forEach(this.$$foreignModels, function (value, key) { | ||
137 | - this[key].$rollback(); | ||
138 | - }, this); | ||
139 | - } | ||
140 | - } | ||
141 | - | ||
142 | - function Query(apiEndpoint, ctor) { | ||
143 | - var includes = []; | ||
144 | - var selects = []; | ||
145 | - var filters = []; | ||
146 | - var order = []; | ||
147 | - var modelCtor = ctor; | ||
148 | - this.include = include; | ||
149 | - this.select = select; | ||
150 | - this.filter = filter; | ||
151 | - this.where = filter; | ||
152 | - this.parseAs = parseAs; | ||
153 | - this.execute = execute; | ||
154 | - this.orderBy = orderBy; | ||
155 | - | ||
156 | - function parseAs(parser) { | ||
157 | - modelCtor = parser; | ||
158 | - } | ||
159 | - | ||
160 | - function include() { | ||
161 | - if (arguments.length === 2) { | ||
162 | - if (angular.isObject(arguments[1])) { | ||
163 | - //TODO: Process subquery | ||
164 | - } else if (angular.isFunction(arguments[1])) { | ||
165 | - //TODO: Process subquery | ||
166 | - } | ||
167 | - } else { | ||
168 | - [].push.apply(includes, arguments); | ||
169 | - } | ||
170 | - return this; | ||
171 | - } | ||
172 | - | ||
173 | - function orderBy(prop) { | ||
174 | - this.order.push(prop); | ||
175 | - //todo add dir and aliases | ||
176 | - } | ||
177 | - | ||
178 | - function select() { | ||
179 | - [].push.apply(selects, arguments); | ||
180 | - modelCtor = null; | ||
181 | - return this; | ||
182 | - } | ||
183 | - | ||
184 | - function filter(key, op, value) { | ||
185 | - if (arguments.length === 1) { | ||
186 | - filters.push(key); | ||
187 | - } else if (arguments.length === 3) { | ||
188 | - switch (op) { | ||
189 | - case '&&': | ||
190 | - op = 'and'; | ||
191 | - break; | ||
192 | - case '||': | ||
193 | - op = 'or'; | ||
194 | - break; | ||
195 | - case '=': | ||
196 | - case '==': | ||
197 | - case '===': | ||
198 | - op = 'eq'; | ||
199 | - break; | ||
200 | - case '!=': | ||
201 | - case '!==': | ||
202 | - case '!===': | ||
203 | - op = 'ne'; | ||
204 | - break; | ||
205 | - case '>': | ||
206 | - op = 'gt'; | ||
207 | - break; | ||
208 | - case '>=': | ||
209 | - op = 'ge'; | ||
210 | - break; | ||
211 | - case '<': | ||
212 | - op = 'lt'; | ||
213 | - break; | ||
214 | - case '<=': | ||
215 | - op = 'le'; | ||
216 | - break; | ||
217 | - default: | ||
218 | - break; | ||
219 | - } | ||
220 | - filters.push(key + ' ' + op + ' ' + value); | ||
221 | - } | ||
222 | - return this; | ||
223 | - } | ||
224 | - | ||
225 | - function execute() { | ||
226 | - var config = {}; | ||
227 | - config.params = _buildParams(); | ||
228 | - apiCall = $config.API_ENDPOINT + apiEndpoint; | ||
229 | - return $http.get(apiCall, config).then(function (response) { | ||
230 | - if (!modelCtor) { | ||
231 | - return response.data; | ||
232 | - } else { | ||
233 | - if (angular.isArray(response.data)) { | ||
234 | - var results = []; | ||
235 | - angular.forEach(response.data, function (d) { | ||
236 | - results.push(new modelCtor(d)); | ||
237 | - }); | ||
238 | - return results; | ||
239 | - } else { | ||
240 | - return new modelCtor(response.data); | ||
241 | - } | ||
242 | - } | ||
243 | - }); | ||
244 | - } | ||
245 | - | ||
246 | - function _buildParams() { | ||
247 | - var params = {}; | ||
248 | - if (includes.length) { | ||
249 | - params.$expand = includes.join(','); | ||
250 | - } | ||
251 | - if (filters.length) { | ||
252 | - params.$filter = filters.join(' and '); | ||
253 | - } | ||
254 | - if (selects.length) { | ||
255 | - params.$select = selects.join(','); | ||
256 | - } | ||
257 | - return params; | ||
258 | - } | ||
259 | - } | ||
260 | - | ||
261 | - function ModelCache() { | ||
262 | - | ||
263 | - } | ||
264 | - | ||
265 | - function BuildConstructor(apiEndpoint, schema) { | ||
266 | - function ModelCtor(values) { | ||
267 | - var values = values || {}; | ||
268 | - | ||
269 | - this.base = Entity; | ||
270 | - this.base(apiEndpoint, schema, values); | ||
271 | - } | ||
272 | - | ||
273 | - ModelCtor.prototype = new Entity; | ||
274 | - ModelCtor.$schema = schema; | ||
275 | - ModelCtor.query = query; | ||
276 | - ModelCtor.getById = getById; | ||
277 | - | ||
278 | - var passon = ModelCtor; | ||
279 | - | ||
280 | - function query() { | ||
281 | - return new Query(apiEndpoint, passon); | ||
282 | - } | ||
283 | - | ||
284 | - function getById(id) { | ||
285 | - return new Query(apiEndpoint) | ||
286 | - .filter('Id', 'eq', id); | ||
287 | - } | ||
288 | - | ||
289 | - return ModelCtor; | ||
290 | - } | ||
291 | - } | ||
292 | - } | ||
293 | - | ||
294 | - dataService.$inject = ['$config', '$http', '$q', 'Models']; | ||
295 | - function dataService($config, $http, $q, Models) { | ||
296 | - var entityIdMaps = {}; | ||
297 | - var entityArrays = {}; | ||
298 | - | ||
299 | - } | ||
300 | -})(window, angular); | ||
301 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/services/Storage.service.js
@@ -1,73 +0,0 @@ | @@ -1,73 +0,0 @@ | ||
1 | -(function () { | ||
2 | - var module = angular.module('framework.services.storage', []) | ||
3 | - | ||
4 | - module.factory('$localStorage', _storageFactory('localStorage')); | ||
5 | - module.factory('$sessionStorage', _storageFactory('sessionStorage')); | ||
6 | - | ||
7 | - function _storageFactory(storageType) { | ||
8 | - return ['$rootScope', '$window', '$log', | ||
9 | - function ($rootScope, $window, $log) { | ||
10 | - // #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app | ||
11 | - var webStorage = $window[storageType] || ($log.warn('This browser does not support Web Storage!'), {}), | ||
12 | - $storage = { | ||
13 | - $default: function (items) { | ||
14 | - for (var k in items) { | ||
15 | - angular.isDefined($storage[k]) || ($storage[k] = items[k]); | ||
16 | - } | ||
17 | - | ||
18 | - return $storage; | ||
19 | - }, | ||
20 | - $reset: function (items) { | ||
21 | - for (var k in $storage) { | ||
22 | - '$' === k[0] || delete $storage[k]; | ||
23 | - } | ||
24 | - | ||
25 | - return $storage.$default(items); | ||
26 | - } | ||
27 | - }, | ||
28 | - _last$storage, | ||
29 | - _debounce; | ||
30 | - | ||
31 | - for (var i = 0, k; i < webStorage.length; i++) { | ||
32 | - // #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty) | ||
33 | - (k = webStorage.key(i)) && 'ngStorage-' === k.slice(0, 10) && ($storage[k.slice(10)] = angular.fromJson(webStorage.getItem(k))); | ||
34 | - } | ||
35 | - | ||
36 | - _last$storage = angular.copy($storage); | ||
37 | - | ||
38 | - $rootScope.$watch(function () { | ||
39 | - _debounce || (_debounce = setTimeout(function () { | ||
40 | - _debounce = null; | ||
41 | - | ||
42 | - if (!angular.equals($storage, _last$storage)) { | ||
43 | - angular.forEach($storage, function (v, k) { | ||
44 | - angular.isDefined(v) && '$' !== k[0] && webStorage.setItem('ngStorage-' + k, angular.toJson(v)); | ||
45 | - | ||
46 | - delete _last$storage[k]; | ||
47 | - }); | ||
48 | - | ||
49 | - for (var k in _last$storage) { | ||
50 | - webStorage.removeItem('ngStorage-' + k); | ||
51 | - } | ||
52 | - | ||
53 | - _last$storage = angular.copy($storage); | ||
54 | - } | ||
55 | - }, 100)); | ||
56 | - }); | ||
57 | - | ||
58 | - // #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent` | ||
59 | - 'localStorage' === storageType && $window.addEventListener && $window.addEventListener('storage', function (event) { | ||
60 | - if ('ngStorage-' === event.key.slice(0, 10)) { | ||
61 | - event.newValue ? $storage[event.key.slice(10)] = angular.fromJson(event.newValue) : delete $storage[event.key.slice(10)]; | ||
62 | - | ||
63 | - _last$storage = angular.copy($storage); | ||
64 | - | ||
65 | - $rootScope.$apply(); | ||
66 | - } | ||
67 | - }); | ||
68 | - | ||
69 | - return $storage; | ||
70 | - } | ||
71 | - ]; | ||
72 | - } | ||
73 | -})() | ||
74 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/tables/Table.controller.js
@@ -1,157 +0,0 @@ | @@ -1,157 +0,0 @@ | ||
1 | -(function (angular) { | ||
2 | - var module = angular.module('framework.table', []); | ||
3 | - | ||
4 | - var table_defaults = { | ||
5 | - table: 'table table-bordered' | ||
6 | - }; | ||
7 | - | ||
8 | - /* | ||
9 | - * Defines Table defaults and settings | ||
10 | - */ | ||
11 | - module.constant("$table_config", table_defaults); | ||
12 | - | ||
13 | - /* | ||
14 | - * Injectable Base Class for Inhertence | ||
15 | - * Functions: | ||
16 | - * Lays out rows / columns | ||
17 | - * Sets heading title | ||
18 | - * Parses cell values | ||
19 | - * Column Sizing | ||
20 | - */ | ||
21 | - module.service('BasicTableControllerBase', function () { | ||
22 | - return BasicTableControllerBase; | ||
23 | - }); | ||
24 | - | ||
25 | - /* | ||
26 | - * Injectable Base Class for Inhertence | ||
27 | - * Functions: | ||
28 | - * As Basic Table Plus: | ||
29 | - * Sortable Columns | ||
30 | - */ | ||
31 | - module.service('SortableTableControllerBase', function () { | ||
32 | - return SortableTableControllerBase; | ||
33 | - }); | ||
34 | - | ||
35 | - /* | ||
36 | - * Default Implementations | ||
37 | - */ | ||
38 | - module.controller('BasicTableController', basicTableController); | ||
39 | - module.controller('SortableTableController', sortableTableController); | ||
40 | - | ||
41 | - //#region BaseClasses | ||
42 | - | ||
43 | - function BasicTableControllerBase($scope, columns, data) { | ||
44 | - var $injector = angular.element('*[ng-app]').injector(); | ||
45 | - var $parse = $injector.get('$parse'); | ||
46 | - | ||
47 | - $scope.rows = data.data; | ||
48 | - $scope.columns = columns; | ||
49 | - $scope.getValue = getValue; | ||
50 | - | ||
51 | - var _totalWidths = columns.reduce(function (prev, current) { | ||
52 | - return prev += (current.width || '*').length; | ||
53 | - }, 0); | ||
54 | - | ||
55 | - angular.forEach(columns, function (value) { | ||
56 | - value.$$parser = angular.isFunction(value.mapping) ? value.mapping : $parse(value.mapping || value.name); | ||
57 | - value.$$width = 100.00 / _totalWidths * (value.width || '*').length + '%'; | ||
58 | - }); | ||
59 | - | ||
60 | - function getValue(row, col) { | ||
61 | - return col.$$parser(row); | ||
62 | - } | ||
63 | - } | ||
64 | - | ||
65 | - function SortableTableControllerBase($scope, columns, data) { | ||
66 | - this.base = BasicTableControllerBase; | ||
67 | - this.base($scope, columns, data); | ||
68 | - | ||
69 | - $scope.currentSort = { | ||
70 | - value: '', | ||
71 | - column: null, | ||
72 | - reverse: false | ||
73 | - }; | ||
74 | - $scope.currentSearch = searchFunction; | ||
75 | - $scope.sortBy = sort; | ||
76 | - $scope.searchTerm = null; | ||
77 | - | ||
78 | - function sort(column, $event) { | ||
79 | - var newSort = { | ||
80 | - value: '', | ||
81 | - column: null | ||
82 | - }; | ||
83 | - | ||
84 | - if (angular.isObject(column)) { | ||
85 | - newSort.column = column; | ||
86 | - newSort.value = column.$$parser; | ||
87 | - } else if (typeof column === "string") { | ||
88 | - angular.forEach($scope.columns, function (colDef) { | ||
89 | - if ((colDef.mapping || colDef.name) === column) { | ||
90 | - newSort.column = colDef; | ||
91 | - } | ||
92 | - }); | ||
93 | - newSort.value = column; | ||
94 | - } else if (angular.isFunction(column)) { | ||
95 | - newSort.value = column; | ||
96 | - newSort.column = null; | ||
97 | - } | ||
98 | - | ||
99 | - if ($scope.currentSort.value === newSort.value) { | ||
100 | - $scope.currentSort.reverse = !$scope.currentSort.reverse; | ||
101 | - } else { | ||
102 | - $scope.currentSort.reverse = false; | ||
103 | - } | ||
104 | - | ||
105 | - $scope.currentSort.value = newSort.value; | ||
106 | - $scope.currentSort.column = newSort.column; | ||
107 | - }; | ||
108 | - | ||
109 | - function searchFunction(row) { | ||
110 | - if (!$scope.searchTerm) { | ||
111 | - return true; | ||
112 | - } | ||
113 | - var found = false; | ||
114 | - for (var i = 0; i < columns.length; i++) { | ||
115 | - var column = $scope.columns[i]; | ||
116 | - if (angular.isUndefined(column.searchable) || column.searchable) { | ||
117 | - var value = column.$$parser(row); | ||
118 | - if (angular.isFunction(column.comparator)) { | ||
119 | - found = column.comparator(value, $scope.searchTerm); | ||
120 | - } else if (typeof value === 'string') { | ||
121 | - found = value.toLowerCase().indexOf($scope.searchTerm.toLowerCase()) >= 0; | ||
122 | - } | ||
123 | - } | ||
124 | - if (found) { | ||
125 | - break; | ||
126 | - } | ||
127 | - } | ||
128 | - return found; | ||
129 | - }; | ||
130 | - } | ||
131 | - SortableTableControllerBase.prototype = BasicTableControllerBase; | ||
132 | - | ||
133 | - //#endregion | ||
134 | - | ||
135 | - //#region Default Implementations | ||
136 | - | ||
137 | - basicTableController.$inject = ['$scope', 'classes', 'columns', 'data']; | ||
138 | - function basicTableController($scope, classes, columns, data) { | ||
139 | - this.base = BasicTableControllerBase; | ||
140 | - this.base($scope, columns, data); | ||
141 | - | ||
142 | - $scope.classes = angular.extend({}, table_defaults, classes); | ||
143 | - } | ||
144 | - basicTableController.prototype = BasicTableControllerBase; | ||
145 | - | ||
146 | - | ||
147 | - sortableTableController.$inject = ['$scope', 'classes', 'columns', 'data']; | ||
148 | - function sortableTableController($scope, classes, columns, data) { | ||
149 | - this.base = SortableTableControllerBase; | ||
150 | - this.base($scope, columns, data); | ||
151 | - | ||
152 | - $scope.classes = angular.extend({}, table_defaults, classes); | ||
153 | - } | ||
154 | - sortableTableController.prototype = SortableTableControllerBase; | ||
155 | - | ||
156 | - //#endregion | ||
157 | -})(angular); | ||
158 | \ No newline at end of file | 0 | \ No newline at end of file |
common_components/tables/basic-table.layout.html
@@ -1,18 +0,0 @@ | @@ -1,18 +0,0 @@ | ||
1 | -<div class="basic-table"> | ||
2 | - <table ng-class="classes.table"> | ||
3 | - <thead ng-class="classes.head"> | ||
4 | - <tr> | ||
5 | - <th ng-repeat="col in columns" width="{{col.$$width}}" ng-class="col.classes.heading"> | ||
6 | - {{ col.name }} | ||
7 | - </th> | ||
8 | - </tr> | ||
9 | - </thead> | ||
10 | - <tbody ng-class="classes.body"> | ||
11 | - <tr ng-repeat="row in rows"> | ||
12 | - <td ng-repeat="col in columns"> | ||
13 | - {{ ::getValue(row, col) }} | ||
14 | - </td> | ||
15 | - </tr> | ||
16 | - </tbody> | ||
17 | - </table> | ||
18 | -</div> |
common_components/tables/sortable-table.layout.html
@@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||
1 | -<div class="basic-table"> | ||
2 | - <input type="text" ng-model="searchTerm" /> | ||
3 | - <table ng-class="classes.table"> | ||
4 | - <thead> | ||
5 | - <tr> | ||
6 | - <th ng-repeat="col in columns" width="{{::col.$$width}}"> | ||
7 | - {{ ::col.name }} | ||
8 | - <i class="fa" ng-class="currentSort.column === col ? (currentSort.reverse ? 'fa-sort-amount-desc' : 'fa-sort-amount-asc') : 'fa-sort-amount-asc text-muted' " ng-click="sortBy(col, $event)"></i> | ||
9 | - </th> | ||
10 | - </tr> | ||
11 | - </thead> | ||
12 | - <tbody> | ||
13 | - <tr ng-repeat="row in rows | filter:currentSearch | orderBy:currentSort.value:currentSort.reverse"> | ||
14 | - <td ng-repeat="col in columns"> | ||
15 | - {{ ::getValue(row, col) }} | ||
16 | - </td> | ||
17 | - </tr> | ||
18 | - </tbody> | ||
19 | - </table> | ||
20 | -</div> |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +(function (angular) { | ||
2 | + 'use strict'; | ||
3 | + | ||
4 | + var module = angular.module('framework.directives.utils', []); | ||
5 | + | ||
6 | + module.directive('bindHtmlCompile', ['$compile', bindHtmlCompile]); | ||
7 | + | ||
8 | + function bindHtmlCompile($compile) { | ||
9 | + return { | ||
10 | + restrict: 'A', | ||
11 | + link: function (scope, element, attrs) { | ||
12 | + scope.$watch(function () { | ||
13 | + return scope.$eval(attrs.bindHtmlCompile); | ||
14 | + }, function (value) { | ||
15 | + element.html(value); | ||
16 | + $compile(element.contents())(scope); | ||
17 | + }); | ||
18 | + } | ||
19 | + }; | ||
20 | + } | ||
21 | +}(angular)); | ||
0 | \ No newline at end of file | 22 | \ No newline at end of file |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +(function(angular){ | ||
2 | + var module = angular.module('framework.directives.UI',[]); | ||
3 | + | ||
4 | + module.directive('card', cardDirective); | ||
5 | + cardDirective.$inject=['$state', '$interval', '$parse']; | ||
6 | + function cardDirective($state, $interval, $parse) { | ||
7 | + return { | ||
8 | + restrict: 'E', | ||
9 | + transclude: true, | ||
10 | + replace: true, | ||
11 | + scope: true, | ||
12 | + template: function(element, attrs) { | ||
13 | + var template=''; | ||
14 | + template += '<div class="card"><div class="card-container"'; | ||
15 | + if(attrs.allowClick!="false") { | ||
16 | + template += ' ng-click="viewItem(item)"' | ||
17 | + } | ||
18 | + template += '><svg class="logo" style="background-image:url(\'{{::accessors.LogoUrl(item)}}\')" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="transparent" stroke-width="10" stroke-linecap="round" ng-show="showScore==true" stroke-location="outside"></circle></svg>'; | ||
19 | + if(attrs.showTitle!="false") { | ||
20 | + template += '<strong>{{ ::accessors.Title(item) }}</strong>'; | ||
21 | + } | ||
22 | + if(attrs.showSubtitle!="false") { | ||
23 | + template += '<small>{{ ::accessors.SubTitle(item) }}</small>'; | ||
24 | + } | ||
25 | + template += '</div></div>'; | ||
26 | + return template; | ||
27 | + }, | ||
28 | + link: function(scope, elem, attrs, ctrls, transcludeFn) { | ||
29 | + if(attrs.item) { | ||
30 | + var getter = $parse(attrs.item); | ||
31 | + scope.item = getter(scope); | ||
32 | + } | ||
33 | + scope.viewItem = viewItem; | ||
34 | + if(scope.accessors.Score) { | ||
35 | + var percentScore = (2 * Math.PI*50)/100*scope.accessors.Score(scope.item); | ||
36 | + var percentColor = (percentScore < 90)? 'red': (percentScore >= 90 && percentScore <180)? 'orange' :(percentScore >= 180 && percentScore <270)? 'rgb(25, 195, 45)' : 'rgb(25, 195, 45);'; | ||
37 | + elem.find("circle") | ||
38 | + .attr("stroke", percentColor) | ||
39 | + .attr("stroke-dasharray",percentScore+",10000"); | ||
40 | + } | ||
41 | + | ||
42 | + function viewItem(item) { | ||
43 | + $state.go(scope.rNavTo, { Id: item.Id }); | ||
44 | + } | ||
45 | + } | ||
46 | + } | ||
47 | + } | ||
48 | +})(angular); | ||
0 | \ No newline at end of file | 49 | \ No newline at end of file |
@@ -0,0 +1,218 @@ | @@ -0,0 +1,218 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.directives.UI'); | ||
3 | + | ||
4 | + module.directive('fieldFor', fieldForDirective); | ||
5 | + module.directive('formFor', formForDirective); | ||
6 | + module.filter('propSearch', propertySearchFilter); | ||
7 | + | ||
8 | + formForDirective.$inject = ['Model']; | ||
9 | + function formForDirective(Model) { | ||
10 | + return { | ||
11 | + restrict: 'A', | ||
12 | + scope: true, | ||
13 | + transclude: true, | ||
14 | + template: function (element, attrs) { | ||
15 | + return '<form name="formFor.form" class="transclude-target" autocomplete="off" novalidate></form>'; | ||
16 | + }, | ||
17 | + link: function (scope, element, attrs, ctrls, transcludeFn) { | ||
18 | + scope.formFor = (scope.formFor || {}); | ||
19 | + scope.formFor.target = scope.$eval(attrs.formFor); | ||
20 | + scope.formFor.schema = (attrs.schema) ? Model[attrs.schema].$schema : scope.target.$$schema; | ||
21 | + scope.formFor.mode = 'EDIT'; | ||
22 | + | ||
23 | + scope.$watch(function () { | ||
24 | + return scope.target; | ||
25 | + }, function (newvalue) { | ||
26 | + | ||
27 | + }); | ||
28 | + | ||
29 | + if (attrs.mode) { | ||
30 | + scope.formFor.mode = attrs.mode; | ||
31 | + attrs.$observe('mode', function (newvalue) { | ||
32 | + scope.formFor.mode = newvalue; | ||
33 | + }); | ||
34 | + } | ||
35 | + | ||
36 | + transcludeFn(scope, function (clone, scope) { | ||
37 | + element.children('.transclude-target').append(clone); | ||
38 | + }); | ||
39 | + } | ||
40 | + } | ||
41 | + }; | ||
42 | + | ||
43 | + fieldForDirective.$inject = ['Model']; | ||
44 | + function fieldForDirective(Model) { | ||
45 | + var defaults = { | ||
46 | + inputType: 'text', | ||
47 | + required: false, | ||
48 | + selectTheme: 'selectize', | ||
49 | + selectSelectedTemplate: '{{$select.selected.Name}}', | ||
50 | + selectOptionTemplate: '<div ng-bind-html="option.Name | highlight: $select.search"></div><small class="text-muted">{{option.Description}}</small>' | ||
51 | + }; | ||
52 | + return { | ||
53 | + restrict: 'A', | ||
54 | + scope: true, | ||
55 | + template: function (element, attrs) { | ||
56 | + var formParent = element.closest('[form-for]'), | ||
57 | + subformParent = element.closest('[sub-form-for]'), | ||
58 | + schemaName = ((subformParent.length) ? subformParent : formParent).attr('schema'), | ||
59 | + ctor = Model[schemaName], | ||
60 | + schema = ctor && ctor.$schema, | ||
61 | + fieldDef = schema && schema[attrs.fieldFor], | ||
62 | + subForm = subformParent.attr('sub-form-for') || ''; | ||
63 | + | ||
64 | + if (!fieldDef) { | ||
65 | + return; | ||
66 | + } | ||
67 | + | ||
68 | + var inputConfig = angular.extend({ display: attrs.fieldFor, inputType: 'text' }, defaults, fieldDef, fieldDef.input, attrs); | ||
69 | + | ||
70 | + //need to fetch these. | ||
71 | + var labelText = attrs.display || attrs.fieldFor, | ||
72 | + fieldName = attrs.fieldFor, | ||
73 | + selectFrom = attrs.selectFrom; | ||
74 | + | ||
75 | + var template = '' + | ||
76 | + '<div class="form-group">' + | ||
77 | + '<label class="control-label" for="' + subForm + fieldName + 'Input">' + inputConfig.display + '</label>' + | ||
78 | + '<div ng-if="formFor.mode === \'VIEW\'">' + | ||
79 | + '<p class="form-control-static" ng-bind="::formFor.target.' + ((subForm) ? (subForm + '.') : '') + (inputConfig.displayField ? inputConfig.displayField : fieldName) + (inputConfig.displayFilters ? inputConfig.displayFilters : '') + '"></p>' + | ||
80 | + '</div>' + | ||
81 | + '<div ng-if="formFor.mode === \'EDIT\'">'; | ||
82 | + | ||
83 | + if (selectFrom) { | ||
84 | + template += '' + | ||
85 | + '<ui-select ng-model="formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName + '" name="' + subForm + fieldName + 'Input" theme="' + inputConfig.selectTheme + '" ng-disabled="' + (angular.isDefined(inputConfig.editable) && !inputConfig.editable) + '" ng-required="' + inputConfig.required + '">' + | ||
86 | + '<ui-select-match allow-clear="true" placeholder="' + (inputConfig.placeholder || 'Select..') + '">' + inputConfig.selectSelectedTemplate + '</ui-select-match>' + | ||
87 | + '<ui-select-choices repeat="option.Id as option in ' + selectFrom + ' | propSearch: { Name: $select.search }">' + | ||
88 | + inputConfig.selectOptionTemplate + | ||
89 | + '</ui-select-choices>'+ | ||
90 | + '</ui-select>'; | ||
91 | + } else if (inputConfig.type === moment) { | ||
92 | + template += '' + | ||
93 | + '<div class="input-group">' + | ||
94 | + buildElement('input', { | ||
95 | + class: 'form-control', | ||
96 | + type: 'text', | ||
97 | + name: subForm + fieldName + 'Input', | ||
98 | + ngModel: 'formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName, | ||
99 | + ngRequired: inputConfig.required, | ||
100 | + datepickerPopup: 'dd/MM/yyyy', | ||
101 | + isOpen: 'opened', | ||
102 | + placeholder: 'DD/MM/YYYY', | ||
103 | + ngDisabled: angular.isDefined(inputConfig.editable) && !inputConfig.editable | ||
104 | + }) + | ||
105 | + '<span class="input-group-btn">' + | ||
106 | + '<button type="button" class="btn btn-default" ng-click="openCalendar($event)"><i class="glyphicon glyphicon-calendar"></i></button>' + | ||
107 | + '</span>' + | ||
108 | + '</div>'; | ||
109 | + } else { | ||
110 | + if (inputConfig.append || inputConfig.prepend) { | ||
111 | + template += '<div class="input-group">'; | ||
112 | + } | ||
113 | + if (inputConfig.prepend) { | ||
114 | + template += '<span class="input-group-btn">' + | ||
115 | + '<button type="button" class="btn btn-default" ng-click="' + inputConfig.prepend.click + '"><i class="' + inputConfig.prepend.icon + '"></i>' + inputConfig.prepend.text + '</button>' + | ||
116 | + '</span>' | ||
117 | + } | ||
118 | + template += buildElement('input', { | ||
119 | + class: 'form-control', | ||
120 | + type: inputConfig.inputType, | ||
121 | + name: subForm + fieldName + 'Input', | ||
122 | + ngModel: 'formFor.target.' + ((subForm) ? (subForm + '.') : '') + fieldName, | ||
123 | + ngRequired: inputConfig.required, | ||
124 | + placeholder: inputConfig.placeholder | ||
125 | + }); | ||
126 | + if (inputConfig.append) { | ||
127 | + template += '<span class="input-group-btn">' + | ||
128 | + '<button type="button" class="btn btn-default" ng-click="' + inputConfig.append.click + '"><i class="' + inputConfig.append.icon + '"></i>' + inputConfig.append.text + '</button>' + | ||
129 | + '</span>' | ||
130 | + } | ||
131 | + if (inputConfig.append || inputConfig.prepend) { | ||
132 | + template += '</div>'; | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + template += '' + | ||
137 | + '<div ng-messages="formFor.form.' + subForm + fieldName + 'Input.$error" class="help-block">' + | ||
138 | + '<div ng-message="required">' + inputConfig.display + ' is required.</div>' + | ||
139 | + '<div ng-message="parse">' + inputConfig.display + ' is incorrectly formatted.</div>' + | ||
140 | + '<div ng-message="email">' + inputConfig.display + ' is not a valid e-mail.</div>' + | ||
141 | + '</div>' + | ||
142 | + '</div>'; | ||
143 | + template += '</div>'; | ||
144 | + return template; | ||
145 | + }, | ||
146 | + link: function (scope, element, attrs) { | ||
147 | + scope.opened = false; | ||
148 | + | ||
149 | + scope.openCalendar = function (event) { | ||
150 | + event.preventDefault(); | ||
151 | + event.stopPropagation(); | ||
152 | + scope.opened = true; | ||
153 | + } | ||
154 | + } | ||
155 | + }; | ||
156 | + }; | ||
157 | + | ||
158 | + function propertySearchFilter() { | ||
159 | + return function (items, props) { | ||
160 | + var out = []; | ||
161 | + | ||
162 | + if (angular.isArray(items)) { | ||
163 | + items.forEach(function (item) { | ||
164 | + var itemMatches = false; | ||
165 | + | ||
166 | + var keys = Object.keys(props); | ||
167 | + for (var i = 0; i < keys.length; i++) { | ||
168 | + var prop = keys[i]; | ||
169 | + var text = props[prop].toLowerCase(); | ||
170 | + if (item[prop].toString().toLowerCase().indexOf(text) !== -1) { | ||
171 | + itemMatches = true; | ||
172 | + break; | ||
173 | + } | ||
174 | + } | ||
175 | + | ||
176 | + if (itemMatches) { | ||
177 | + out.push(item); | ||
178 | + } | ||
179 | + }); | ||
180 | + } else { | ||
181 | + // Let the output be the input untouched | ||
182 | + out = items; | ||
183 | + } | ||
184 | + | ||
185 | + return out; | ||
186 | + }; | ||
187 | + }; | ||
188 | + | ||
189 | + function buildElement(elementType, attrs) { | ||
190 | + var result = '<' + elementType + ' '; | ||
191 | + | ||
192 | + angular.forEach(attrs, function (value, key) { | ||
193 | + if (angular.isDefined(value) && value !== null) | ||
194 | + result += normalise(key) + '="' + value + '"'; | ||
195 | + }); | ||
196 | + | ||
197 | + if (elementType === 'input') { | ||
198 | + result += ' />'; | ||
199 | + } else { | ||
200 | + result += ' ></' + elementType + '>'; | ||
201 | + } | ||
202 | + return result; | ||
203 | + } | ||
204 | + | ||
205 | + function normalise(input) { | ||
206 | + var result = ''; | ||
207 | + for (var i = 0; i < input.length; i++) { | ||
208 | + var char = input[i]; | ||
209 | + if (char == char.toUpperCase()) { | ||
210 | + result += '-' + char.toLowerCase(); | ||
211 | + } else { | ||
212 | + result += char; | ||
213 | + } | ||
214 | + } | ||
215 | + return result; | ||
216 | + } | ||
217 | + | ||
218 | +}(angular)); | ||
0 | \ No newline at end of file | 219 | \ No newline at end of file |
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +(function(angular){ | ||
2 | + var module = angular.module('framework.directives.UI'); | ||
3 | + | ||
4 | + module.directive('score', scoreDirective); | ||
5 | + | ||
6 | + scoreDirective.$inject=['$state', '$interval', '$parse']; | ||
7 | + | ||
8 | + function scoreDirective($state, $interval, $parse) { | ||
9 | + return { | ||
10 | + restrict: 'E', | ||
11 | + transclude: true, | ||
12 | + replace: true, | ||
13 | + scope: true, | ||
14 | + template: function(element, attrs) { | ||
15 | + var template=''; | ||
16 | + template += '<div class="score"'; | ||
17 | + if(attrs.size) { | ||
18 | + var scoreSize = parseInt(attrs.size); | ||
19 | + template += ' style="position:relative;width:'+ (scoreSize) +'px; height: ' + (scoreSize) + 'px; border-radius:'+ (scoreSize/2) + 'px;padding:5px;">'; | ||
20 | + } | ||
21 | + else { | ||
22 | + template += ' style="width:100px;height:100px;border-radius:50px;">'; | ||
23 | + } | ||
24 | + if(attrs.showScore) { | ||
25 | + template += '<div class="score-value" style="line-height:' + scoreSize + 'px">'+attrs.showScore+'</div>'; | ||
26 | + } | ||
27 | + template += '<svg class="dial" viewBox="0 0 100 100">' + | ||
28 | + '<circle class="score-back-circle" cx="50" cy="50" r="45" fill="transparent" stroke-linecap="round"></circle>' + | ||
29 | + '<circle class="score-front-circle" cx="50" cy="50" r="45" fill="transparent" stroke-linecap="round"></circle>' + | ||
30 | + '</svg>'; | ||
31 | + template += '</div>'; | ||
32 | + return template; | ||
33 | + }, | ||
34 | + link: function(scope, elem, attrs, ctrls, transcludeFn) { | ||
35 | + if(!attrs.value) | ||
36 | + return; | ||
37 | + | ||
38 | + var strokeWidth = (attrs.strokeWidth)? attrs.strokeWidth : 5; | ||
39 | + var percentScore = (2 * Math.PI*50)/100 * attrs.value; | ||
40 | + var percentColor = (percentScore < 90)? 'red': (percentScore >= 90 && percentScore <180)? 'orange' :(percentScore >= 180 && percentScore <270)? 'rgb(25, 195, 45)' : 'rgb(25, 195, 45)'; | ||
41 | + | ||
42 | + elem.find("circle.score-back-circle") | ||
43 | + .attr("stroke", "#eee") | ||
44 | + .attr("stroke-width", strokeWidth); | ||
45 | + | ||
46 | + elem.find("circle.score-front-circle") | ||
47 | + .attr("stroke", percentColor) | ||
48 | + .attr("stroke-width", strokeWidth) | ||
49 | + .attr("stroke-dasharray", percentScore+",10000"); | ||
50 | + } | ||
51 | + } | ||
52 | + } | ||
53 | +})(angular); | ||
0 | \ No newline at end of file | 54 | \ No newline at end of file |
@@ -0,0 +1,592 @@ | @@ -0,0 +1,592 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.directives.UI'); | ||
3 | + | ||
4 | + module.directive('tableFor', tableForDirective); | ||
5 | + module.directive('tableTitlebar', tableTitlebarDirective); | ||
6 | + module.directive('tableHeading', tableHeadingDirective); | ||
7 | + module.directive('tableDataRows', tableDataRowsDirective); | ||
8 | + module.directive('tableFooter', tableFooterDirective); | ||
9 | + module.filter('publish', publishFilter); | ||
10 | + module.filter('softFilter', softFilter); | ||
11 | + module.filter('pageGroup', pageGroupFilter); | ||
12 | + | ||
13 | + | ||
14 | + | ||
15 | + tableForDirective.$inject = ['$parse', 'Model', '$modal', '$q', '$filter', '$timeout']; | ||
16 | + function tableForDirective($parse, Model, $modal, $q, $filter, $timeout) { | ||
17 | + var defaults = { | ||
18 | + wrapperClass: 'table-responsive', | ||
19 | + tableClass: 'table table-bordered', | ||
20 | + minWidth: '600px' | ||
21 | + } | ||
22 | + | ||
23 | + function linkFn(scope, element, attrs, ctrls, transcludeFn) { | ||
24 | + var externalSearch = $parse(attrs.filtering)(scope); | ||
25 | + var externalSorting = $parse(attrs.sorting)(scope); | ||
26 | + var externalGrouping = $parse(attrs.grouping)(scope); | ||
27 | + var externalPaging = $parse(attrs.paging)(scope); | ||
28 | + | ||
29 | + scope.$schema = Model[attrs.schema].$schema; | ||
30 | + scope.$table = { | ||
31 | + actionColumn: false, | ||
32 | + selectionColumn: false, | ||
33 | + cardTemplate: '{{$row | json}}', | ||
34 | + toggleSelectAll: toggleSelectAll, | ||
35 | + toggleRowSelection: toggleRowSelection, | ||
36 | + toggleGroupSelection: toggleGroupSelection, | ||
37 | + allSelected: false, | ||
38 | + reset: reset, | ||
39 | + configureColumns: configureColumns, | ||
40 | + sort: sort, | ||
41 | + getSortingClass: getSortingClass | ||
42 | + }; | ||
43 | + scope.$columns = generateColumns(scope.$schema); | ||
44 | + scope.$filtering = externalSearch || { | ||
45 | + $: '' | ||
46 | + } | ||
47 | + scope.$sorting = externalSorting || []; | ||
48 | + scope.$grouping = externalGrouping || { | ||
49 | + value: undefined | ||
50 | + }; | ||
51 | + scope.$paging = externalPaging || { | ||
52 | + currentPage: 1, | ||
53 | + totalItems: 0, | ||
54 | + maxPerPage: 10 | ||
55 | + }; | ||
56 | + scope.$data = {}; //object as it's grouped | ||
57 | + scope.$datasource = function () { | ||
58 | + return arguments[4]; //returns existing data by default; | ||
59 | + }; | ||
60 | + | ||
61 | + var datasource = $parse(attrs.datasource)(scope); | ||
62 | + if (angular.isArray(datasource)) { | ||
63 | + scope.$datasource = generateLocalDatasource(datasource); | ||
64 | + } else if (angular.isFunction(datasource)) { | ||
65 | + scope.$datasource = datasource; | ||
66 | + } else { | ||
67 | + scope.$datasource = generateModelDatasource(scope.$schema.query); | ||
68 | + } | ||
69 | + | ||
70 | + scope.$watchCollection(function () { return scope.$filtering; }, debouncedUpdateData); | ||
71 | + scope.$watchCollection(function () { return scope.$sorting; }, debouncedUpdateData); | ||
72 | + scope.$watchCollection(function () { return scope.$grouping; }, debouncedUpdateData); | ||
73 | + scope.$watch(function () { return scope.$paging.currentPage; }, debouncedUpdateData); | ||
74 | + scope.$watch(function () { return scope.$paging.maxPerPage; }, debouncedUpdateData); | ||
75 | + | ||
76 | + var updateDebounce = null; | ||
77 | + | ||
78 | + function debouncedUpdateData() { | ||
79 | + if (updateDebounce) { | ||
80 | + $timeout.cancel(updateDebounce); | ||
81 | + updateDebounce = null; | ||
82 | + } | ||
83 | + updateDebounce = $timeout(updateData, 500); | ||
84 | + } | ||
85 | + | ||
86 | + function updateData() { | ||
87 | + for (var key in scope.$data) { | ||
88 | + delete scope.$data[key]; | ||
89 | + } | ||
90 | + scope.$data.$loading = true; | ||
91 | + scope.$data.$error = null; | ||
92 | + scope.$datasource(scope.$filtering, scope.$sorting, scope.$grouping, scope.$paging, scope.$data).then(dataReceived, dataError, dataNotified); | ||
93 | + } | ||
94 | + | ||
95 | + function dataReceived(data) { | ||
96 | + for (var key in scope.$data) { | ||
97 | + delete scope.$data[key]; | ||
98 | + } | ||
99 | + scope.$data.$loading = false; | ||
100 | + angular.extend(scope.$data, data); | ||
101 | + } | ||
102 | + | ||
103 | + function dataError(error) { | ||
104 | + for (var key in scope.$data) { | ||
105 | + delete scope.$data[key]; | ||
106 | + } | ||
107 | + scope.$data.$loading = false; | ||
108 | + scope.$data.$error = error; | ||
109 | + } | ||
110 | + | ||
111 | + function dataNotified(dataLength) { | ||
112 | + scope.$paging.totalItems = dataLength; | ||
113 | + } | ||
114 | + | ||
115 | + transcludeFn(scope, function (clone, scope) { | ||
116 | + element.find('table').append(clone); | ||
117 | + }); | ||
118 | + | ||
119 | + function generateLocalDatasource(initialData) { | ||
120 | + var data = initialData; | ||
121 | + return function (filtering, sorting, grouping, paging, existing) { | ||
122 | + var deferred = $q.defer(); | ||
123 | + | ||
124 | + setTimeout(function () { | ||
125 | + var filter = $filter('filter'); | ||
126 | + var orderBy = $filter('orderBy'); | ||
127 | + var groupBy = $filter('groupBy'); | ||
128 | + var pageGroup = $filter('pageGroup'); | ||
129 | + | ||
130 | + deferred.notify(filter(data, filtering).length); | ||
131 | + | ||
132 | + var amendedSorting = [grouping.value]; | ||
133 | + [].push.apply(amendedSorting, sorting); | ||
134 | + | ||
135 | + var result = pageGroup(groupBy(orderBy(filter(data, filtering), amendedSorting), grouping.value), paging); | ||
136 | + | ||
137 | + deferred.resolve(result); | ||
138 | + }, 0); | ||
139 | + | ||
140 | + return deferred.promise; | ||
141 | + } | ||
142 | + } | ||
143 | + | ||
144 | + function generateModelDatasource(modelQuery) { | ||
145 | + var queryBase = modelQuery; | ||
146 | + return function (filtering, sorting, grouping, paging, existing) { | ||
147 | + var deferred = $q.defer(); | ||
148 | + | ||
149 | + query = queryBase(); | ||
150 | + if (grouping.value) { | ||
151 | + query.orderBy(grouping.value); | ||
152 | + } | ||
153 | + | ||
154 | + angular.forEach(ordering, function (o) { query.orderBy(o); }); | ||
155 | + | ||
156 | + | ||
157 | + setTimeout(function () { | ||
158 | + var filter = $filter('filter'); | ||
159 | + var groupBy = $filter('groupBy'); | ||
160 | + var pageGroup = $filter('pageGroup'); | ||
161 | + | ||
162 | + deferred.notify(filter(data, filtering).length); | ||
163 | + | ||
164 | + var amendedSorting = [grouping.value]; | ||
165 | + [].push.apply(amendedSorting, sorting); | ||
166 | + | ||
167 | + var result = pageGroup(groupBy(orderBy(filter(data, filtering), amendedSorting), grouping.value), paging); | ||
168 | + | ||
169 | + deferred.resolve(result); | ||
170 | + }, 0); | ||
171 | + | ||
172 | + return deferred.promise; | ||
173 | + } | ||
174 | + } | ||
175 | + | ||
176 | + function generateColumns(modelSchema) { | ||
177 | + var columns = []; | ||
178 | + angular.forEach(modelSchema, function (value, key) { | ||
179 | + var config = angular.extend({}, value, value.table || {}); | ||
180 | + if (config.hidden) { | ||
181 | + return; | ||
182 | + } | ||
183 | + if (!angular.isDefined(config.visible)) { | ||
184 | + config.visible = true; | ||
185 | + } | ||
186 | + if (!angular.isDefined(config.binding) && config.type === moment) { | ||
187 | + config.binding = key + ".toDate() | date:'dd/MM/yyyy'"; | ||
188 | + } | ||
189 | + columns.push({ key: key, title: config.display || key, accessor: angular.isFunction(config.binding) ? config.binding : buildAccessor(config.binding || key), binding: config.binding || key, visible: config.visible, filters: config.filters }); | ||
190 | + }); | ||
191 | + return columns; | ||
192 | + } | ||
193 | + | ||
194 | + function toggleSelectAll() { | ||
195 | + scope.$table.allSelected = !scope.$table.allSelected; | ||
196 | + angular.forEach(scope.$data, function (group) { | ||
197 | + toggleGroupSelection(group, scope.$table.allSelected); | ||
198 | + }); | ||
199 | + } | ||
200 | + | ||
201 | + function toggleRowSelection(group, row, force) { | ||
202 | + row.$selected = angular.isDefined(force) ? force : !row.$selected; | ||
203 | + var selected = group.filter(function (d) { return d.$selected; }); | ||
204 | + group.$selected = selected.length === group.length; | ||
205 | + | ||
206 | + var groups = 0; | ||
207 | + var selectedGroups = 0; | ||
208 | + angular.forEach(scope.$data, function (group, title) { | ||
209 | + if (title[0] == '$') { | ||
210 | + return; | ||
211 | + } | ||
212 | + groups++; | ||
213 | + if (group.$selected) selectedGroups++; | ||
214 | + }); | ||
215 | + scope.$table.allSelected = groups === selectedGroups; | ||
216 | + } | ||
217 | + | ||
218 | + function toggleGroupSelection(group, force) { | ||
219 | + if (angular.isDefined(force)) { | ||
220 | + group.$selected = force; | ||
221 | + } else { | ||
222 | + group.$selected = !group.$selected; | ||
223 | + } | ||
224 | + angular.forEach(group, function (row) { | ||
225 | + row.$selected = group.$selected; | ||
226 | + }); | ||
227 | + | ||
228 | + if (!angular.isDefined(force)) { | ||
229 | + var groups = 0; | ||
230 | + var selectedGroups = 0; | ||
231 | + angular.forEach(scope.$data, function (group, title) { | ||
232 | + if (title[0] == '$') { | ||
233 | + return; | ||
234 | + } | ||
235 | + groups++; | ||
236 | + if (group.$selected) selectedGroups++; | ||
237 | + }); | ||
238 | + debugger; | ||
239 | + scope.$table.allSelected = groups === selectedGroups; | ||
240 | + } | ||
241 | + } | ||
242 | + | ||
243 | + function setAreAllSelected() { | ||
244 | + scope.$table.allSelected = false; | ||
245 | + } | ||
246 | + | ||
247 | + function sort(col) { | ||
248 | + //multisort | ||
249 | + var currentSort = scope.$sorting[0]; | ||
250 | + if (col == currentSort) { | ||
251 | + scope.$sorting[0] = '-' + col; | ||
252 | + } else if ('-' + col == currentSort) { | ||
253 | + scope.$sorting[0] = col; | ||
254 | + } else { | ||
255 | + scope.$sorting.length = 0; | ||
256 | + scope.$sorting.push(col); | ||
257 | + } | ||
258 | + } | ||
259 | + | ||
260 | + function getSortingClass(col) { | ||
261 | + if (col == scope.$sorting[0]) { | ||
262 | + return 'icon-Arrow-Down2 brand-primary'; | ||
263 | + } | ||
264 | + else if ('-' + col == scope.$sorting[0]) { | ||
265 | + return 'icon-Arrow-Up2 brand-primary'; | ||
266 | + } else { | ||
267 | + return 'icon-Arrow-Down'; | ||
268 | + } | ||
269 | + } | ||
270 | + | ||
271 | + function reset() { | ||
272 | + scope.$filtering = externalSearch || { | ||
273 | + $: '' | ||
274 | + } | ||
275 | + scope.$sorting = []; | ||
276 | + | ||
277 | + //TODO: Deselect ALL | ||
278 | + | ||
279 | + scope.$columns.length = 0; | ||
280 | + [].push.apply(scope.$columns, generateColumns(scope.$schema)); | ||
281 | + } | ||
282 | + | ||
283 | + function buildAccessor(fieldName) { | ||
284 | + console.log('return row.' + fieldName + ';'); | ||
285 | + window.count = window.count || 0; | ||
286 | + return new Function('row', 'return row.' + fieldName + ';'); | ||
287 | + } | ||
288 | + | ||
289 | + function configureColumns() { | ||
290 | + $modal.open({ | ||
291 | + template: '' + | ||
292 | + '<div class="modal-header">' + | ||
293 | + '<button class="close" type="button" ng-click="$close()"><i class="icon-Close"></i></button>' + | ||
294 | + '<h3 class="modal-title">Customize Columns</h3>' + | ||
295 | + '</div>' + | ||
296 | + '<div class="modal-body">' + | ||
297 | + '<div ng-repeat="column in columns">' + | ||
298 | + '<a ng-click="moveUp(column)" ng-hide="$first"><i class="icon-Arrow-UpinCircle brand-primary"></i></a>' + | ||
299 | + ' {{column.title}}' + | ||
300 | + ' <a ng-click="moveDown(column)" ng-hide="$last"><i class="icon-Arrow-DowninCircle brand-primary"></i></a>' + | ||
301 | + '<div class="checkbox pull-right m0">' + | ||
302 | + '<input type="checkbox" id="columncustomise{{::$index}}" ng-model="column.visible" ng-checked="column.visible" />' + | ||
303 | + '<label for="columncustomise{{::$index}}"></label>' + | ||
304 | + '</div><br class="clearfix">' + | ||
305 | + '</div>' + | ||
306 | + '</div>', | ||
307 | + controller: function ($scope, columns) { | ||
308 | + $scope.columns = columns; | ||
309 | + $scope.moveUp = function (column) { | ||
310 | + var index = $scope.columns.indexOf(column); | ||
311 | + move(index, index - 1); | ||
312 | + } | ||
313 | + $scope.moveDown = function (column) { | ||
314 | + var index = $scope.columns.indexOf(column); | ||
315 | + move(index, index + 1); | ||
316 | + } | ||
317 | + | ||
318 | + function move(old_index, new_index) { | ||
319 | + $scope.columns.splice(new_index, 0, $scope.columns.splice(old_index, 1)[0]); | ||
320 | + } | ||
321 | + }, | ||
322 | + size: 'sm', | ||
323 | + resolve: { | ||
324 | + columns: function () { | ||
325 | + return scope.$columns | ||
326 | + } | ||
327 | + } | ||
328 | + }); | ||
329 | + } | ||
330 | + } | ||
331 | + | ||
332 | + function compileFn(element, attrs) { | ||
333 | + return linkFn; | ||
334 | + } | ||
335 | + | ||
336 | + return { | ||
337 | + scope: true, | ||
338 | + transclude: true, | ||
339 | + template: function (element, attrs) { | ||
340 | + return '<div class="' + (attrs.wrapperClass || defaults.wrapperClass) + '"><table class="' + (attrs.tableClass || defaults.tableClass) + ' module-table" style="min-width:' + (attrs.minWidth || defaults.minWidth) + '"></table></div>' | ||
341 | + }, | ||
342 | + compile: function (element, attrs) { | ||
343 | + return linkFn; | ||
344 | + } | ||
345 | + }; | ||
346 | + } | ||
347 | + | ||
348 | + function tableTitlebarDirective() { | ||
349 | + return { | ||
350 | + restrict: 'E', | ||
351 | + scope: true, | ||
352 | + replace: true, | ||
353 | + template: function (element, attrs) { | ||
354 | + var template = '' + | ||
355 | + '<thead><tr><th colspan="100" class="table-arrange">'; | ||
356 | + if (attrs.title) { | ||
357 | + template += '<h3 class="table-title">' + attrs.title + '</h3>'; | ||
358 | + } | ||
359 | + if (attrs.showCount) { | ||
360 | + template += '<h3 class="table-title brand-primary">({{$visible.length}} / {{ $data.length }})</h3>'; | ||
361 | + } | ||
362 | + if (attrs.columnsOptions) { | ||
363 | + template += '<div class="columns-options">' + | ||
364 | + '<a href="" ng-click="$table.reset()"><i class="icon-Reset"></i>Reset</a>' + | ||
365 | + '<a href="" ng-click="$table.configureColumns()"><i class="icon-Receipt-2"></i>Arrange</a>' + | ||
366 | + '</div>'; | ||
367 | + } | ||
368 | + template += '<div class="pull-right">' + | ||
369 | + '<pagination class="pagination-sm" style="margin: 0;" total-items="$paging.totalItems" ng-model="$paging.currentPage" items-per-page="$paging.maxPerPage" boundary-links="true" max-size="5"></pagination>' + | ||
370 | + '</div>'; | ||
371 | + if (attrs.search) { | ||
372 | + template += '<input type="text" class="form-control pull-right" style="width:300px" placeholder="Search.." ng-model="$filtering.$" />'; | ||
373 | + } | ||
374 | + template += '</th></tr></thead>' | ||
375 | + return template; | ||
376 | + } | ||
377 | + } | ||
378 | + } | ||
379 | + | ||
380 | + function tableHeadingDirective() { | ||
381 | + var defaults = { | ||
382 | + } | ||
383 | + return { | ||
384 | + restrict: 'E', | ||
385 | + scope: true, | ||
386 | + replace: true, | ||
387 | + template: function (element, attrs) { | ||
388 | + var tmpl = '' + | ||
389 | + '<thead><tr>' + | ||
390 | + '<th ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
391 | + '<div class="checkbox"><input type="checkbox" id="table-group-check" ng-click="$table.toggleSelectAll()" ng-checked="$table.allSelected"/><label for="table-group-check"></label></div>' + | ||
392 | + | ||
393 | + '</th>' + | ||
394 | + '<th ng-repeat="$column in $columns | filter: { visible: true }" class="module-table-head">' + | ||
395 | + '<div><i ng-class="$column.icon"></i> {{ ::$column.title }}' + | ||
396 | + '<span class="table-sort"><a href="" ng-click="$table.sort($column.key)"><i ng-class="$table.getSortingClass($column.key)"></i></a></span>' + | ||
397 | + '</div>' + //add filter and search menu | ||
398 | + '</th>' + | ||
399 | + '<th ng-if="::$table.actionColumn" style="text-align:center;">' + | ||
400 | + 'Actions' + | ||
401 | + '</th>' + | ||
402 | + '</tr>'; | ||
403 | + tmpl += '</thead>'; | ||
404 | + return tmpl; | ||
405 | + } | ||
406 | + }; | ||
407 | + } | ||
408 | + | ||
409 | + tableDataRowsDirective.$inject = ['$parse', 'Model']; | ||
410 | + function tableDataRowsDirective($parse, Model) { | ||
411 | + return { | ||
412 | + restrict: 'E', | ||
413 | + scope: true, | ||
414 | + replace: true, | ||
415 | + template: function (element, attrs) { | ||
416 | + var tmp = '' + | ||
417 | + '<tbody ng-repeat="(title, group) in $data track by title">' + | ||
418 | + '<tr ng-hide="title == \'undefined\'">' + | ||
419 | + '<td ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
420 | + '<div class="checkbox"><input id="group-check-{{::title}}" type="checkbox" ng-click="$table.toggleGroupSelection(group)" ng-checked="group.$selected"/><label for="group-check-{{::title}}"></label></div>' + | ||
421 | + '</td>' + | ||
422 | + '<td colspan="1000"><b><u>{{ title }}</u></b></td>' + | ||
423 | + '</tr>' + | ||
424 | + '<tr ng-repeat="$row in group track by $row.Id">' + | ||
425 | + '<td ng-if="::$table.selectionColumn" style="width:40px;text-align:center;">' + | ||
426 | + '<div class="checkbox"><input id="table-check-{{::title}}{{::$index}}" type="checkbox" ng-click="$table.toggleRowSelection(group, $row)" ng-checked="$row.$selected"/><label for="table-check-{{::title}}{{::$index}}"></label></div>' + | ||
427 | + '</td>' + | ||
428 | + '<td ng-repeat="$column in $columns | filter: { visible: true } track by $column.key">' + | ||
429 | + '{{$column.accessor($row)}}' + | ||
430 | + '</td>' + | ||
431 | + '<td ng-if="::$table.actionColumn" style="text-align:center;" bind-html-compile="$table.actionColumn.html">' + | ||
432 | + '</td>' + | ||
433 | + '</tr>' + | ||
434 | + '</tbody>'; | ||
435 | + return tmp; | ||
436 | + }, | ||
437 | + compile: function (element, attrs) { | ||
438 | + var selectionElement = _findSelectionColumn(element); | ||
439 | + var actionsElement = _findActionColumn(element); | ||
440 | + | ||
441 | + return link; | ||
442 | + | ||
443 | + function link(scope, element, attrs) { | ||
444 | + scope.$table.actionColumn = actionsElement; | ||
445 | + scope.$table.selectionColumn = selectionElement; | ||
446 | + scope.$table.getCellValue = getCellValue; | ||
447 | + | ||
448 | + function getCellValue(row, col) { | ||
449 | + console.log('GetCellValue is depreciated for performance, please use "$column.accessor($row)" instead, functions are now precompilied;'); | ||
450 | + if (typeof col.binding === 'string') | ||
451 | + return $parse(col.binding)(row); | ||
452 | + else if (angular.isFunction(col.binding)) | ||
453 | + return col.binding(row, col); | ||
454 | + else | ||
455 | + return ''; | ||
456 | + } | ||
457 | + } | ||
458 | + } | ||
459 | + } | ||
460 | + | ||
461 | + function _findActionColumn(element) { | ||
462 | + var actionsElement = jQuery(element.context).find('table-actions'); | ||
463 | + if (actionsElement.length) { | ||
464 | + return { | ||
465 | + html: actionsElement.html() | ||
466 | + }; | ||
467 | + } | ||
468 | + return false; | ||
469 | + } | ||
470 | + | ||
471 | + function _findSelectionColumn(element) { | ||
472 | + var selectionElement = jQuery(element.context).find('table-selection'); | ||
473 | + if (selectionElement.length) { | ||
474 | + return { | ||
475 | + html: selectionElement.html() | ||
476 | + }; | ||
477 | + } | ||
478 | + return false; | ||
479 | + } | ||
480 | + } | ||
481 | + | ||
482 | + function tableFooterDirective() { | ||
483 | + return { | ||
484 | + restrict: 'E', | ||
485 | + scope: true, | ||
486 | + replace: true, | ||
487 | + template: function (element, attrs) { | ||
488 | + var template = '' + | ||
489 | + '<tfoot><tr><th colspan="100" class="table-arrange">'; | ||
490 | + if (attrs.title) { | ||
491 | + template += '<h3 class="table-title">' + attrs.title + '</h3>'; | ||
492 | + } | ||
493 | + if (attrs.showCount) { | ||
494 | + template += '<b class="brand-primary">(showing {{$paging.maxPerPage}} from {{ $paging.totalItems }})</b>'; | ||
495 | + } | ||
496 | + if (attrs.columnsOptions) { | ||
497 | + template += '<div class="columns-options">' + | ||
498 | + '<a href="" ng-click="$table.reset()"><i class="icon-Reset"></i>Reset</a>' + | ||
499 | + '<a href="" ng-click="$table.configureColumns()"><i class="icon-Receipt-2"></i>Arrange</a>' + | ||
500 | + '</div>'; | ||
501 | + } | ||
502 | + template += '<div class="pull-right">' + | ||
503 | + '<pagination class="pagination-sm" style="margin: 0;" total-items="$paging.totalItems" ng-model="$paging.currentPage" items-per-page="$paging.maxPerPage" boundary-links="true" max-size="5"></pagination>' + | ||
504 | + '</div>'; | ||
505 | + if (attrs.search) { | ||
506 | + template += '<input type="text" class="form-control pull-right" style="width:300px" placeholder="Search.." ng-model="$filtering.$" />'; | ||
507 | + } | ||
508 | + template += '</th></tr></tfoot>' | ||
509 | + return template; | ||
510 | + } | ||
511 | + } | ||
512 | + } | ||
513 | + | ||
514 | + softFilter.$inject = ['$filter']; | ||
515 | + function softFilter($filter) { | ||
516 | + return function (array, filteringConfig) { | ||
517 | + var filterFn = $filter('filter'); | ||
518 | + var filtered = filterFn(array, filteringConfig); | ||
519 | + for (var i = 0; i < array.length; i++) { | ||
520 | + var target = array[i]; | ||
521 | + if (filtered.indexOf(target) > -1) { | ||
522 | + target.$filtered = true; | ||
523 | + } else { | ||
524 | + target.$filtered = false; | ||
525 | + } | ||
526 | + } | ||
527 | + return array; | ||
528 | + } | ||
529 | + } | ||
530 | + | ||
531 | + function pageGroupFilter() { | ||
532 | + return function (groups, pagingConfig) { | ||
533 | + var newGroups = {}; | ||
534 | + var skip = (pagingConfig.currentPage - 1) * pagingConfig.maxPerPage; | ||
535 | + var take = pagingConfig.maxPerPage; | ||
536 | + | ||
537 | + if (angular.isArray(groups)) { | ||
538 | + newGroups.undefined = groups.slice(skip, skip + take); | ||
539 | + } else { | ||
540 | + var groupNames = []; | ||
541 | + for (var key in groups) { | ||
542 | + if (groups.hasOwnProperty(key) && key[0] != '$') { | ||
543 | + groupNames.push(key); | ||
544 | + } | ||
545 | + } | ||
546 | + groupNames.sort(); | ||
547 | + | ||
548 | + angular.forEach(groupNames, function (title) { | ||
549 | + var values = groups[title]; | ||
550 | + if (take <= 0) { | ||
551 | + return; | ||
552 | + } else if (skip > values.length) { | ||
553 | + skip -= values.length; | ||
554 | + return; | ||
555 | + } else if (skip > 0) { | ||
556 | + values.splice(0, skip); | ||
557 | + skip = 0; | ||
558 | + } | ||
559 | + | ||
560 | + if (take >= values.length) { | ||
561 | + newGroups[title] = values; | ||
562 | + take -= values.length; | ||
563 | + } else { | ||
564 | + newGroups[title] = values.slice(0, take); | ||
565 | + take = 0; | ||
566 | + } | ||
567 | + }); | ||
568 | + } | ||
569 | + return newGroups; | ||
570 | + }; | ||
571 | + } | ||
572 | + | ||
573 | + function pagingFilter() { | ||
574 | + return function (array, pagingConfig) { | ||
575 | + if (array.length > pagingConfig.minimum) { | ||
576 | + | ||
577 | + } else { | ||
578 | + return array; | ||
579 | + } | ||
580 | + } | ||
581 | + } | ||
582 | + | ||
583 | + function publishFilter() { | ||
584 | + return function (array, target) { | ||
585 | + if (angular.isArray(target)) { | ||
586 | + target.length = 0; | ||
587 | + [].push.apply(target, array); | ||
588 | + } | ||
589 | + return array; | ||
590 | + } | ||
591 | + } | ||
592 | +})(angular); | ||
0 | \ No newline at end of file | 593 | \ No newline at end of file |
@@ -0,0 +1,110 @@ | @@ -0,0 +1,110 @@ | ||
1 | +(function(angular){ | ||
2 | + var module = angular.module('framework.filters.utility',[]); | ||
3 | + | ||
4 | + module.filter('RemoveSpaces', removeSpaces); | ||
5 | + module.filter('Truncate', truncate); | ||
6 | + module.filter('AbbrValue', abbrValue); | ||
7 | + module.filter('Countdown', countdown); | ||
8 | + | ||
9 | + | ||
10 | + function removeSpaces() { | ||
11 | + return function (text) { | ||
12 | + return text.replace(/\s/g, ''); | ||
13 | + } | ||
14 | + } | ||
15 | + | ||
16 | + function truncate () { | ||
17 | + return function (text, length, end) { | ||
18 | + if (isNaN(length)) | ||
19 | + length = 10; | ||
20 | + if (end === undefined) | ||
21 | + end = "..."; | ||
22 | + if (text.length <= length || text.length - end.length <= length) | ||
23 | + { return text; } | ||
24 | + else | ||
25 | + { return String(text).substring(0, length - end.length) + end; } | ||
26 | + } | ||
27 | + } | ||
28 | + | ||
29 | + function abbrValue() { | ||
30 | + return function (val) { | ||
31 | + | ||
32 | + return Math.abs(Number(val)) >= 1.0e+9 | ||
33 | + | ||
34 | + ? Math.round(Math.abs((Number(val)) / 1.0e+9)*10)/10 + "b" | ||
35 | + // Six Zeroes for Millions | ||
36 | + : Math.abs(Number(val)) >= 1.0e+6 | ||
37 | + | ||
38 | + ? Math.round(Math.abs((Number(val)) / 1.0e+6)*10)/10 + "m" | ||
39 | + // Three Zeroes for Thousands | ||
40 | + : Math.abs(Number(val)) >= 1.0e+3 | ||
41 | + | ||
42 | + ? Math.round(Math.abs((Number(val)) / 1.0e+3)*10)/10 + "k" | ||
43 | + | ||
44 | + : Math.abs(Number(val)); | ||
45 | + } | ||
46 | + } | ||
47 | + | ||
48 | + function countdown() { | ||
49 | + return function (input) { | ||
50 | + var substitute = function (stringOrFunction, number, strings) { | ||
51 | + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, dateDifference) : stringOrFunction; | ||
52 | + var value = (strings.numbers && strings.numbers[number]) || number; | ||
53 | + return string.replace(/%d/i, value); | ||
54 | + }, | ||
55 | + nowTime = (new Date()).getTime(), | ||
56 | + date = (new Date(input)).getTime(), | ||
57 | + allowFuture = true, | ||
58 | + strings = { | ||
59 | + prefixAgo: null, | ||
60 | + prefixFromNow: null, | ||
61 | + suffixAgo: "ago", | ||
62 | + suffixFromNow: "",//"from now" | ||
63 | + seconds: "less than a minute", | ||
64 | + minute: "a minute", | ||
65 | + minutes: "%d minutes", | ||
66 | + hour: "an hour", | ||
67 | + hours: "%d hours", | ||
68 | + day: "a day", | ||
69 | + days: "%d days", | ||
70 | + month: "a month", | ||
71 | + months: "%d months", | ||
72 | + year: "a year", | ||
73 | + years: "%d years" | ||
74 | + }, | ||
75 | + dateDifference = nowTime - date, | ||
76 | + words, | ||
77 | + seconds = Math.abs(dateDifference) / 1000, | ||
78 | + minutes = seconds / 60, | ||
79 | + hours = minutes / 60, | ||
80 | + days = hours / 24, | ||
81 | + years = days / 365, | ||
82 | + separator = strings.wordSeparator === undefined ? " " : strings.wordSeparator, | ||
83 | + prefix = strings.prefixAgo, | ||
84 | + suffix = strings.suffixAgo; | ||
85 | + | ||
86 | + if (allowFuture) { | ||
87 | + if (dateDifference < 0) { | ||
88 | + prefix = strings.prefixFromNow; | ||
89 | + suffix = strings.suffixFromNow; | ||
90 | + } | ||
91 | + } | ||
92 | + | ||
93 | + words = seconds < 45 && substitute(strings.seconds, Math.round(seconds), strings) || | ||
94 | + seconds < 90 && substitute(strings.minute, 1, strings) || | ||
95 | + minutes < 45 && substitute(strings.minutes, Math.round(minutes), strings) || | ||
96 | + minutes < 90 && substitute(strings.hour, 1, strings) || | ||
97 | + hours < 24 && substitute(strings.hours, Math.round(hours), strings) || | ||
98 | + hours < 42 && substitute(strings.day, 1, strings) || | ||
99 | + days < 30 && substitute(strings.days, Math.round(days), strings) || | ||
100 | + days < 45 && substitute(strings.month, 1, strings) || | ||
101 | + days < 365 && substitute(strings.months, Math.round(days / 30), strings) || | ||
102 | + years < 1.5 && substitute(strings.year, 1, strings) || | ||
103 | + substitute(strings.years, Math.round(years), strings); | ||
104 | + | ||
105 | + return $.trim([prefix, words, suffix].join(separator)); | ||
106 | + } | ||
107 | + } | ||
108 | + | ||
109 | + | ||
110 | +})(angular); | ||
0 | \ No newline at end of file | 111 | \ No newline at end of file |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +(function (window, angular) { | ||
2 | + var app = angular.module("framework.UI.breadcrumb", []); | ||
3 | + | ||
4 | + app.controller('BarController', barController); | ||
5 | + | ||
6 | + barController.$inject = ['$scope', '$state', '$modal', '$rootScope']; | ||
7 | + function barController($scope, $state, $modal, $rootScope) { | ||
8 | + $scope.breadcrumbs = []; | ||
9 | + $scope.helpAvailable = null; | ||
10 | + $scope.showHelp = showHelp; | ||
11 | + | ||
12 | + function showHelp() { | ||
13 | + if ($scope.helpAvailable) | ||
14 | + $modal.open({ | ||
15 | + templateUrl: $scope.helpAvailable, | ||
16 | + }); | ||
17 | + } | ||
18 | + | ||
19 | + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { | ||
20 | + _parseStateName(toState.name); | ||
21 | + $scope.helpAvailable = toState.hasHelp; | ||
22 | + }); | ||
23 | + | ||
24 | + $scope.helpAvailable = $state.current.hasHelp; | ||
25 | + _parseStateName($state.current.name); | ||
26 | + | ||
27 | + function _parseStateName(stateName) { | ||
28 | + var parts = stateName.split('.'); | ||
29 | + var breadcrumbs = []; | ||
30 | + for (var i = 0; i < parts.length; i++) { | ||
31 | + var p = parts[i]; | ||
32 | + if (p === "root") | ||
33 | + continue; | ||
34 | + var full = parts.slice(0, i + 1).join('.'); | ||
35 | + breadcrumbs.push({ | ||
36 | + name: parts[i], | ||
37 | + $html: _generateBreadcrumbHtml(p, full) | ||
38 | + }); | ||
39 | + } | ||
40 | + $scope.breadcrumbs = breadcrumbs; | ||
41 | + } | ||
42 | + | ||
43 | + function _generateBreadcrumbHtml(name, state) { | ||
44 | + var template = '<a ui-sref="' + state + '" >' + name + '</a>'; | ||
45 | + return template; | ||
46 | + } | ||
47 | + }; | ||
48 | +})(window, angular); | ||
0 | \ No newline at end of file | 49 | \ No newline at end of file |
@@ -0,0 +1,8 @@ | @@ -0,0 +1,8 @@ | ||
1 | +<div ng-controller="BarController"> | ||
2 | + <ol class="breadcrumb"> | ||
3 | + <li ng-repeat="item in breadcrumbs" ui-sref-active="active" bind-html-compile="item.$html"></li> | ||
4 | + </ol> | ||
5 | + <span class="module-help" ng-if="helpAvailable"> | ||
6 | + <a href="" ng-click="showHelp()"><i class="icon-Assistant"></i>Help</a> | ||
7 | + </span> | ||
8 | +</div> |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.documents',[]); | ||
3 | + | ||
4 | + module.controller('DocumentsController', DocumentsController); | ||
5 | + | ||
6 | + DocumentsController.$inject = ['$scope', 'rData', '$state']; | ||
7 | + function DocumentsController($scope, rData, $state) { | ||
8 | + $scope.documents = rData; | ||
9 | + $scope.selectedDocument=rData[0]; | ||
10 | + } | ||
11 | + | ||
12 | +})(angular); | ||
0 | \ No newline at end of file | 13 | \ No newline at end of file |
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +<div class="document-options"> | ||
2 | + <a href="" class="btn btn-xs btn-primary"><i class="icon-Add-File"></i> Add New</a> | ||
3 | +</div> | ||
4 | +<div class="row"> | ||
5 | + <div class="col-md-4"> | ||
6 | + <div class="panel panel-default"> | ||
7 | + <div class="panel-heading"> | ||
8 | + <h3 class="panel-title">Documents</h3> | ||
9 | + </div> | ||
10 | + <div class="panel-body"> | ||
11 | + <div ng-repeat="doc in documents"> | ||
12 | + <div class="document" ng-click="$parent.selectedDocument=doc" ng-class="(selectedDocument==doc)?'active':''"> | ||
13 | + <small class="pull-right grey">{{doc.ExpiryDate | countdown}}</small> | ||
14 | + <strong>{{doc.Name}}</strong><br /> | ||
15 | + {{doc.IdentificationNo}} | ||
16 | + <small class="pull-right grey mt5"><i class="icon-Pencil"></i></small> | ||
17 | + </div> | ||
18 | + </div> | ||
19 | + </div> | ||
20 | + </div> | ||
21 | + </div> | ||
22 | + <div class="col-md-8"> | ||
23 | + <div class="panel panel-default"> | ||
24 | + <div class="panel-heading"> | ||
25 | + <h3 class="panel-title">Viewer</h3> | ||
26 | + </div> | ||
27 | + <div class="panel-body document-viewer"> | ||
28 | + <div class="document-viewer-options"> | ||
29 | + <a href="" class="btn-icon"><i class="icon-Download"></i>Save</a> | ||
30 | + <a href="" class="btn-icon"><i class="icon-Close-Window"></i>Delete</a> | ||
31 | + </div> | ||
32 | + <img src="{{selectedDocument.DocumentURL}}" width="500px" /> | ||
33 | + </div> | ||
34 | + </div> | ||
35 | + </div> | ||
36 | +</div> | ||
0 | \ No newline at end of file | 37 | \ No newline at end of file |
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +<div class="module"> | ||
2 | + <div ui-view name="options-area"></div> | ||
3 | + <div class="row"> | ||
4 | + <div class="col-md-12 col-lg-9 module-primary"> | ||
5 | + <div ui-view name="view-area"></div> | ||
6 | + </div> | ||
7 | + <div class="visible-lg col-lg-3 module-secondary"> | ||
8 | + <div ui-view name="stats-area"></div> | ||
9 | + </div> | ||
10 | + </div> | ||
11 | +</div> | ||
0 | \ No newline at end of file | 12 | \ No newline at end of file |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.UI.module',[]); | ||
3 | + | ||
4 | + module.controller('ModuleCardsController', moduleCardsController); | ||
5 | + | ||
6 | + moduleCardsController.$inject = ['$scope', 'rData', 'rNavTo','rAccessors', '$state', '$interval', '$timeout']; | ||
7 | + function moduleCardsController($scope, rData, rNavTo, rAccessors, $state, $interval, $timeout) { | ||
8 | + $scope.rawItems = rData; | ||
9 | + $scope.accessors = rAccessors; | ||
10 | + $scope.rNavTo = rNavTo; | ||
11 | + $scope.showScore = false; | ||
12 | + $scope.chosenGroup = null; | ||
13 | + $scope.cardLimit = 2; | ||
14 | + | ||
15 | + $scope.groups = {}; | ||
16 | + rData = rData.sort(function(a,b){ | ||
17 | + var valA = rAccessors.Title(a), valB = rAccessors.Title(b); | ||
18 | + if(valA < valB) { | ||
19 | + return -1; | ||
20 | + } else if (valA > valB){ | ||
21 | + return 1; | ||
22 | + } else | ||
23 | + return 0; | ||
24 | + }); | ||
25 | + | ||
26 | + var i; | ||
27 | + | ||
28 | + for(i = 0; i < rData.length; i++) { | ||
29 | + var title = rAccessors.Group(rData[i]); | ||
30 | + if($scope.groups[title]) | ||
31 | + $scope.groups[title].push(rData[i]); | ||
32 | + else | ||
33 | + $scope.groups[title] = [rData[i]]; | ||
34 | + } | ||
35 | + } | ||
36 | + | ||
37 | +})(angular); | ||
0 | \ No newline at end of file | 38 | \ No newline at end of file |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +<div class="cards-wrapper"> | ||
2 | + <div class="cards-view-options"> | ||
3 | + <div class="row"> | ||
4 | + <div class="col-sm-8 col-xs-8"> | ||
5 | + <div class="group-filters"> | ||
6 | + <a class="group-options" ng-click="chosenGroup = null" ng-class="(chosenGroup == null)?'active':''">All</a> | ||
7 | + <a class="group-options" ng-click="$parent.chosenGroup = title" ng-class="($parent.chosenGroup == title)?'active':''" ng-repeat="(title, items) in groups">{{title}}({{(items | filter:searchTerm).length }})</a> | ||
8 | + </div> | ||
9 | + </div> | ||
10 | + <div class="col-sm-4 col-xs-4 text-right"> | ||
11 | + <a class="btn btn-primary btn-xs" ng-click="showScore=!showScore" ng-bind="(showScore)? 'Hide Scores':'Show Scores'" ng-class="(showScore)?'active':''">Show Scores</a> | ||
12 | + </div> | ||
13 | + </div> | ||
14 | + </div> | ||
15 | + <div ng-repeat="(title, items) in ::groups track by title" ng-if="!chosenGroup || chosenGroup==title"> | ||
16 | + <h3 class="section-title" ng-show="results.length > 0">{{title}}</h3> | ||
17 | + | ||
18 | + <card ng-repeat="item in items | filter:searchTerm as results track by item.Id" showscore="{{showScore}}" ></card> | ||
19 | + | ||
20 | + <br class="clearfix" ng-show="results.length > 0" /> | ||
21 | + </div> | ||
22 | + <div ng-if="rawItems.length === 0"> | ||
23 | + No Items Added Yet. | ||
24 | + </div> | ||
25 | + <br class="clearfix" /> | ||
26 | +</div> | ||
0 | \ No newline at end of file | 27 | \ No newline at end of file |
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.UI.module'); | ||
3 | + | ||
4 | + module.controller('ModuleItemViewController', moduleItemViewController); | ||
5 | + | ||
6 | + moduleItemViewController.$inject = ['$scope', 'rTabs', 'rData', 'rAccessors']; | ||
7 | + | ||
8 | + function moduleItemViewController($scope, rTabs, rData, rAccessors) { | ||
9 | + $scope.item = rData[0]; | ||
10 | + $scope.accessors = rAccessors; | ||
11 | + $scope.tabDefs = rTabs; | ||
12 | + } | ||
13 | + | ||
14 | +})(angular); | ||
0 | \ No newline at end of file | 15 | \ No newline at end of file |
@@ -0,0 +1,21 @@ | @@ -0,0 +1,21 @@ | ||
1 | +<div class="module-item"> | ||
2 | + <div class="module-item-cover"></div> | ||
3 | + <div class="module-item-nav-bar"> | ||
4 | + <card class="module-item-card" allow-click="false" show-score="false" class="single pull-left" show-title="false" show-subtitle="false"></card> | ||
5 | + <div class="module-item-brief"> | ||
6 | + <h3>{{accessors.Title(item)}}</h3> | ||
7 | + <h4>{{accessors.SubTitle(item)}}</h4> | ||
8 | + </div> | ||
9 | + <tabs data="tabDefs" type="tabs" justified="false"></tabs> | ||
10 | + </div> | ||
11 | + <div class="module-item-options"> | ||
12 | + <div ui-view name="options-area"></div> | ||
13 | + </div> | ||
14 | + <div class="module-item-content"> | ||
15 | + <div class="row"> | ||
16 | + <div class="col-md-12"> | ||
17 | + <ui-view class="tab-content"></ui-view> | ||
18 | + </div> | ||
19 | + </div> | ||
20 | + </div> | ||
21 | +</div> | ||
0 | \ No newline at end of file | 22 | \ No newline at end of file |
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.UI.module'); | ||
3 | + | ||
4 | + module.controller('ModuleTableController', moduleCardsController); | ||
5 | + | ||
6 | + moduleCardsController.$inject = ['$scope', 'rData', 'rNavTo', 'rSchema', '$state', '$q']; | ||
7 | + function moduleCardsController($scope, rData, rNavTo, rSchema, $state, $q) { | ||
8 | + $scope.items = rData; | ||
9 | + | ||
10 | + function n() { | ||
11 | + console.log(arguments); | ||
12 | + return $q.when(rData); | ||
13 | + }; | ||
14 | + | ||
15 | + $scope.viewItem = viewItem; | ||
16 | + $scope.Schema = rSchema; | ||
17 | + function viewItem(item) { | ||
18 | + $state.go(rNavTo, { Id: 11 }); | ||
19 | + } | ||
20 | + } | ||
21 | + | ||
22 | +})(angular); | ||
0 | \ No newline at end of file | 23 | \ No newline at end of file |
@@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
1 | +<table-for datasource="items" class="table table-condensed table-hover" schema="{{Schema}}" filtering="searchTerm" sorting="" paging="" grouping="grouping" wrapper-class="" table-class=""> | ||
2 | + <table-titlebar columns-options="true" paging="true"></table-titlebar> | ||
3 | + <table-heading sorting="true"> | ||
4 | + <!--<table-cell column=""></table-cell>--> <!-- for overriding --> | ||
5 | + </table-heading> | ||
6 | + <table-data-rows> | ||
7 | + <table-selection></table-selection> | ||
8 | + <!--<table-cell column=""></table-cell>--> <!-- for overriding --> | ||
9 | + <!--<table-expand-template></table-expand-template>--> <!-- for expanding --> | ||
10 | + <table-actions> | ||
11 | + <a class="btn btn-xs btn-primary" ng-click="viewItem(item)"><i class="icon-D-Eyeglasses2"></i>View</a> | ||
12 | + </table-actions> | ||
13 | + </table-data-rows> | ||
14 | + <table-footer paging="true"> | ||
15 | + | ||
16 | + </table-footer> | ||
17 | +</table-for> | ||
0 | \ No newline at end of file | 18 | \ No newline at end of file |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +(function (window, angular) { | ||
2 | + var app = angular.module("framework.UI.structure", []); | ||
3 | + | ||
4 | + app.controller('PageController', pageController); | ||
5 | + | ||
6 | + pageController.$inject = ['$scope', '$interval']; | ||
7 | + | ||
8 | + function pageController($scope, $interval) { | ||
9 | + setupUIElements(); | ||
10 | + }; | ||
11 | + | ||
12 | +})(window, angular); | ||
0 | \ No newline at end of file | 13 | \ No newline at end of file |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<div id="application-layout" ng-controller="PageController"> | ||
2 | + <div id="sidebar-left" ui-view name="sidebar-left"></div> | ||
3 | + <div id="topbar" ui-view name="topbar"></div> | ||
4 | + <div id="content-wrapper"> | ||
5 | + <div id="breadcrumb-bar" ng-include="'/common_components/layouts/breadcrumb/breadcrumb.partial.html'"> | ||
6 | + | ||
7 | + </div> | ||
8 | + <div ui-view name="content-wrapper"> | ||
9 | + | ||
10 | + </div> | ||
11 | + </div> | ||
12 | + <div id="sidebar-toggle"> | ||
13 | + <i class="icon-Align-JustifyAll"></i> | ||
14 | + </div> | ||
15 | + <div id="sidebar-right" ui-view name="sidebar-right"></div> | ||
16 | +</div> | ||
0 | \ No newline at end of file | 17 | \ No newline at end of file |
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<div class="container-fluid tablepage-layout"> | ||
2 | + <div class="row"> | ||
3 | + <div class="col-md-12"> | ||
4 | + <div ui-view name="table-options"></div> | ||
5 | + </div> | ||
6 | + </div> | ||
7 | + <div class="row"> | ||
8 | + <div class="col-md-12"> | ||
9 | + <div ui-view name="table-content"></div> | ||
10 | + </div> | ||
11 | + </div> | ||
12 | +</div> |
@@ -0,0 +1,67 @@ | @@ -0,0 +1,67 @@ | ||
1 | +(function () { | ||
2 | + var app = angular.module('framework.services.logging'); | ||
3 | + | ||
4 | + app.service('ConsoleLoggingProvider', ['$window', consoleLoggingProvider]); | ||
5 | + | ||
6 | + function consoleLoggingProvider($window) { | ||
7 | + this.log = log; | ||
8 | + this.debug = debug; | ||
9 | + this.info = info; | ||
10 | + this.warning = warning; | ||
11 | + this.error = error; | ||
12 | + | ||
13 | + function log(level, catagory, msg, others) { | ||
14 | + switch (level) { | ||
15 | + case 1: | ||
16 | + debug(catagory, msg, others); | ||
17 | + break; | ||
18 | + case 2: | ||
19 | + info(catagory, msg, others); | ||
20 | + break; | ||
21 | + case 3: | ||
22 | + warning(catagory, msg, others); | ||
23 | + break; | ||
24 | + case 4: | ||
25 | + error(catagory, msg, exception, others); | ||
26 | + break; | ||
27 | + default: | ||
28 | + debug(catagory, msg, others); | ||
29 | + break; | ||
30 | + } | ||
31 | + } | ||
32 | + | ||
33 | + function debug(catagory, msg, others) { | ||
34 | + var date = new Date(); | ||
35 | + console.debug(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
36 | + angular.forEach(others, function (val, ind) { | ||
37 | + console.debug('additional info ' + ind + ': ', val); | ||
38 | + }); | ||
39 | + } | ||
40 | + | ||
41 | + function info(catagory, msg, others) { | ||
42 | + var date = new Date(); | ||
43 | + console.info(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
44 | + angular.forEach(others, function (val, ind) { | ||
45 | + console.info('additional info ' + ind + ': ', val); | ||
46 | + }); | ||
47 | + } | ||
48 | + | ||
49 | + function warning(catagory, msg, others) { | ||
50 | + var date = new Date(); | ||
51 | + console.warn(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
52 | + angular.forEach(others, function (val, ind) { | ||
53 | + console.warn('additional info ' + ind + ': ', val); | ||
54 | + }); | ||
55 | + } | ||
56 | + | ||
57 | + function error(catagory, msg, exception, others) { | ||
58 | + var date = new Date(); | ||
59 | + console.error(date.toISOString() + ' - ' + catagory.toUpperCase() + ' - ' + msg); | ||
60 | + console.error('original exception: ' + exception); | ||
61 | + angular.forEach(others, function (val, ind) { | ||
62 | + console.error('additional info ' + ind + ': ', val); | ||
63 | + }); | ||
64 | + } | ||
65 | + } | ||
66 | + | ||
67 | +})(); | ||
0 | \ No newline at end of file | 68 | \ No newline at end of file |
@@ -0,0 +1,139 @@ | @@ -0,0 +1,139 @@ | ||
1 | +(function (window, angular) { | ||
2 | + var app = angular.module("framework.services.logging", []); | ||
3 | + | ||
4 | + app.provider('Logger', function () { | ||
5 | + var providers = []; | ||
6 | + var hiddenCatagorys = []; | ||
7 | + var loggingLevel = 1; | ||
8 | + | ||
9 | + this.DEBUG = 1; | ||
10 | + this.INFO = 2; | ||
11 | + this.WARNING = 3; | ||
12 | + this.ERROR = 4; | ||
13 | + | ||
14 | + this.setGlobalLoggingLevel = setGlobalLoggingLevel; | ||
15 | + this.addProvider = addProvider; | ||
16 | + this.hideCatagory = hideCatagory; | ||
17 | + | ||
18 | + function setGlobalLoggingLevel(level) { | ||
19 | + loggingLevel = level; | ||
20 | + } | ||
21 | + | ||
22 | + function addProvider(provider) { | ||
23 | + providers.push(provider); | ||
24 | + } | ||
25 | + | ||
26 | + function hideCatagory(catagory) { | ||
27 | + hiddenCatagorys.push(catagory); | ||
28 | + } | ||
29 | + | ||
30 | + this.$get = buildLoggerService; | ||
31 | + | ||
32 | + buildLoggerService.$inject = ['$injector']; | ||
33 | + function buildLoggerService($injector) { | ||
34 | + var instance = createLogger('Default'); | ||
35 | + this.createLogger = createLogger; | ||
36 | + this.log = instance.log; | ||
37 | + this.debug = instance.debug; | ||
38 | + this.info = instance.info; | ||
39 | + this.warning = instance.warning; | ||
40 | + this.error = instance.error; | ||
41 | + this.DEBUG = 1; | ||
42 | + this.INFO = 2; | ||
43 | + this.WARNING = 3; | ||
44 | + this.ERROR = 4; | ||
45 | + var concreteProviders = []; | ||
46 | + angular.forEach(providers, function (value) { | ||
47 | + if (angular.isObject(value)) { | ||
48 | + concreteProviders.push(value); | ||
49 | + } else if (angular.isFunction(value)) { | ||
50 | + var pro = { | ||
51 | + log: value, | ||
52 | + debug: log.bind(null, 1), | ||
53 | + info: log.bind(null, 2), | ||
54 | + warning: log.bind(null, 3), | ||
55 | + error: log.bind(null, 4) | ||
56 | + }; | ||
57 | + concreteProviders.push(pro); | ||
58 | + } else if (angular.isArray(value)) { | ||
59 | + var pro = $injector.invoke(value, null, { | ||
60 | + Levels: { | ||
61 | + DEBUG: 1, | ||
62 | + INFO: 2, | ||
63 | + WARNING: 3, | ||
64 | + ERROR: 4 | ||
65 | + } | ||
66 | + }); | ||
67 | + concreteProviders.push(pro); | ||
68 | + } else if (typeof value === 'string') { | ||
69 | + var pro = $injector.get(value); | ||
70 | + concreteProviders.push(pro); | ||
71 | + } | ||
72 | + }); | ||
73 | + | ||
74 | + function createLogger(catagory) { | ||
75 | + return new Logger(catagory, concreteProviders, loggingLevel, hiddenCatagorys); | ||
76 | + } | ||
77 | + | ||
78 | + return this; | ||
79 | + } | ||
80 | + }); | ||
81 | + | ||
82 | + function Logger(catagory, providers, loggingLevel, hiddenCatagorys) { | ||
83 | + this.log = log; | ||
84 | + this.debug = debug; | ||
85 | + this.info = info; | ||
86 | + this.warning = warning; | ||
87 | + this.error = error; | ||
88 | + | ||
89 | + function log(level, msg) { | ||
90 | + if (level < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
91 | + return; | ||
92 | + | ||
93 | + var args = Array.prototype.slice.call(arguments, 2); | ||
94 | + angular.forEach(providers, function (provider) { | ||
95 | + provider.log(level, catagory, msg, args); | ||
96 | + }); | ||
97 | + } | ||
98 | + | ||
99 | + function debug(msg) { | ||
100 | + if (1 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
101 | + return; | ||
102 | + | ||
103 | + var args = Array.prototype.slice.call(arguments, 1); | ||
104 | + angular.forEach(providers, function (provider) { | ||
105 | + provider.debug(catagory, msg, args); | ||
106 | + }); | ||
107 | + } | ||
108 | + | ||
109 | + function info(msg) { | ||
110 | + if (2 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
111 | + return; | ||
112 | + | ||
113 | + var args = Array.prototype.slice.call(arguments, 1); | ||
114 | + angular.forEach(providers, function (provider) { | ||
115 | + provider.info(catagory, msg, args); | ||
116 | + }); | ||
117 | + } | ||
118 | + | ||
119 | + function warning(msg) { | ||
120 | + if (3 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
121 | + return; | ||
122 | + | ||
123 | + var args = Array.prototype.slice.call(arguments, 1); | ||
124 | + angular.forEach(providers, function (provider) { | ||
125 | + provider.warning(catagory, msg, args); | ||
126 | + }); | ||
127 | + } | ||
128 | + | ||
129 | + function error(msg, exception) { | ||
130 | + if (4 < loggingLevel || hiddenCatagorys.indexOf(catagory) != -1) | ||
131 | + return; | ||
132 | + | ||
133 | + var args = Array.prototype.slice.call(arguments, 2); | ||
134 | + angular.forEach(providers, function (provider) { | ||
135 | + provider.error(catagory, msg, exception, args); | ||
136 | + }); | ||
137 | + } | ||
138 | + } | ||
139 | +})(window, angular); | ||
0 | \ No newline at end of file | 140 | \ No newline at end of file |
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +(function (window, angular) { | ||
2 | + var app = angular.module("framework.services.menu", []); | ||
3 | + | ||
4 | + app.provider('MenuService', MenuServiceProvider); | ||
5 | + | ||
6 | + function MenuServiceProvider() { | ||
7 | + var menuItems = []; | ||
8 | + var defaultIcon = 'icon-Align-JustifyAll'; | ||
9 | + var provider = { | ||
10 | + registerMenuItem: registerMenuItem, | ||
11 | + setDefaultIcon: setDefaultIcon, | ||
12 | + $get: getService | ||
13 | + }; | ||
14 | + | ||
15 | + return provider; | ||
16 | + | ||
17 | + function registerMenuItem(menuItem) { | ||
18 | + menuItems.push(menuItem); | ||
19 | + } | ||
20 | + | ||
21 | + function setDefaultIcon(icon) { | ||
22 | + defaultIcon = icon; | ||
23 | + } | ||
24 | + | ||
25 | + function getService() { | ||
26 | + angular.forEach(menuItems, function (mi) { | ||
27 | + mi.$html = _buildTemplate(mi); | ||
28 | + }); | ||
29 | + var service = { | ||
30 | + menuItems: menuItems, | ||
31 | + defaultIcon: defaultIcon | ||
32 | + }; | ||
33 | + return service; | ||
34 | + } | ||
35 | + | ||
36 | + function _buildTemplate(menuItem) { | ||
37 | + var template = '<a ui-sref="' + menuItem.state + '" style="color:white;">' + | ||
38 | + '<i class="{{item.icon ? item.icon : menu.defaultIcon}}"></i>' + | ||
39 | + '{{item.title}}' + | ||
40 | + '</a>'; | ||
41 | + return template; | ||
42 | + } | ||
43 | + | ||
44 | + }; | ||
45 | +})(window, angular); | ||
0 | \ No newline at end of file | 46 | \ No newline at end of file |
@@ -0,0 +1,300 @@ | @@ -0,0 +1,300 @@ | ||
1 | +(function (window, angular) { | ||
2 | + var module = angular.module('framework.services.model', []); | ||
3 | + | ||
4 | + module.provider('Model', modelsProvider); | ||
5 | + //module.service('DataContext', dataService); | ||
6 | + | ||
7 | + function modelsProvider() { | ||
8 | + var schemas = { | ||
9 | + | ||
10 | + }; | ||
11 | + | ||
12 | + this.registerSchema = registerSchema; | ||
13 | + this.$get = buildService; | ||
14 | + | ||
15 | + function registerSchema(name, path, schema) { | ||
16 | + schemas[name] = [path, schema]; | ||
17 | + return this; | ||
18 | + } | ||
19 | + | ||
20 | + buildService.$inject = ['$config', '$http', '$q']; | ||
21 | + function buildService($config, $http, $q) { | ||
22 | + var models = {}; | ||
23 | + | ||
24 | + angular.forEach(schemas, function (value, key) { | ||
25 | + var modelName = key; | ||
26 | + var modelPath = value[0]; | ||
27 | + var modelSchema = value[1]; | ||
28 | + | ||
29 | + models[modelName] = BuildConstructor(modelPath, modelSchema); | ||
30 | + }); | ||
31 | + | ||
32 | + return models; | ||
33 | + | ||
34 | + function Entity(apiEndpoint, schema, values) { | ||
35 | + this.$$apiLocation = apiEndpoint; | ||
36 | + this.$$schema = schema; | ||
37 | + this.$$originalValues = {}; | ||
38 | + this.$$changedValues = {}; | ||
39 | + this.$$foreignModels = {}; | ||
40 | + | ||
41 | + this.$getChanges = getChanges; | ||
42 | + this.$validate = validateEntity; | ||
43 | + this.$save = saveEntity; | ||
44 | + this.$update = updateEntity; | ||
45 | + this.$patch = patchEntity; | ||
46 | + this.$delete = deleteEntity; | ||
47 | + this.$commit = commitEntity; | ||
48 | + this.$rollback = rollbackEntity; | ||
49 | + | ||
50 | + angular.forEach(schema, function (value, key) { | ||
51 | + var fieldName = key, | ||
52 | + fieldDef = value; | ||
53 | + | ||
54 | + if (values[fieldName] !== undefined) { | ||
55 | + if (typeof fieldDef.type === 'string' && values[fieldName] !== null) { | ||
56 | + this.$$originalValues[fieldName] = new models[fieldDef.type](values[fieldName]); | ||
57 | + this.$$foreignModels[fieldName] = fieldDef.type; | ||
58 | + } else { | ||
59 | + this.$$originalValues[fieldName] = values[fieldName]; | ||
60 | + } | ||
61 | + } else { | ||
62 | + this.$$originalValues[fieldName] = fieldDef.defaultValue; | ||
63 | + } | ||
64 | + | ||
65 | + Object.defineProperty(this, fieldName, { | ||
66 | + configurable: false, | ||
67 | + enumerable: true, | ||
68 | + get: fieldDef.calculated || function () { | ||
69 | + return this.$$changedValues.hasOwnProperty(fieldName) ? | ||
70 | + this.$$changedValues[fieldName] : this.$$originalValues[fieldName]; | ||
71 | + }, | ||
72 | + set: function (value) { | ||
73 | + if (angular.isUndefined(fieldDef.editable) || fieldDef.editable) { | ||
74 | + | ||
75 | + this.$$changedValues[fieldName] = value; //CHECK: Cast to correct type?? | ||
76 | + } | ||
77 | + } | ||
78 | + }); | ||
79 | + }, this); | ||
80 | + | ||
81 | + function getChanges() { | ||
82 | + return this.$$changedValues; | ||
83 | + } | ||
84 | + function validateEntity() { | ||
85 | + } //TODO | ||
86 | + function saveEntity() { | ||
87 | + return $http.post($config.API_ENDPOINT + this.$$apiLocation, this); | ||
88 | + } | ||
89 | + function updateEntity() { | ||
90 | + var config = { | ||
91 | + params: { | ||
92 | + id: this.Id | ||
93 | + } | ||
94 | + }; | ||
95 | + return $http.put($config.API_ENDPOINT + this.$$apiLocation, this, config); | ||
96 | + } | ||
97 | + function patchEntity(skipSubObjects) { | ||
98 | + var self = this; | ||
99 | + var delta = angular.extend({ Id: this.Id }, this.$getChanges()); | ||
100 | + var config = { | ||
101 | + params: { | ||
102 | + id: this.Id | ||
103 | + } | ||
104 | + }; | ||
105 | + var request = $http.patch($config.API_ENDPOINT + this.$$apiLocation, delta, config); | ||
106 | + request.success(function () { | ||
107 | + self.$commit(true); | ||
108 | + }); | ||
109 | + return request; | ||
110 | + } | ||
111 | + function deleteEntity() { | ||
112 | + var config = { | ||
113 | + params: { | ||
114 | + id: this.Id | ||
115 | + } | ||
116 | + }; | ||
117 | + return $http.delete($config.API_ENDPOINT + this.$$apiLocation, config); | ||
118 | + } | ||
119 | + function commitEntity(skipSubObjects) { | ||
120 | + angular.forEach(this.$$changedValues, function (value, key) { | ||
121 | + var fieldName = key, | ||
122 | + fieldValue = value; | ||
123 | + this.$$originalValues[fieldName] = fieldValue | ||
124 | + }, this); | ||
125 | + this.$$changedValues = {}; | ||
126 | + | ||
127 | + if (skipSubObjects) return; | ||
128 | + angular.forEach(this.$$foreignModels, function (value, key) { | ||
129 | + this[key].$commit(); | ||
130 | + }, this); | ||
131 | + } | ||
132 | + function rollbackEntity(skipSubObjects) { | ||
133 | + this.$$changedValues = {}; | ||
134 | + | ||
135 | + if (skipSubObjects) return; | ||
136 | + angular.forEach(this.$$foreignModels, function (value, key) { | ||
137 | + this[key].$rollback(); | ||
138 | + }, this); | ||
139 | + } | ||
140 | + } | ||
141 | + | ||
142 | + function Query(apiEndpoint, ctor) { | ||
143 | + var includes = []; | ||
144 | + var selects = []; | ||
145 | + var filters = []; | ||
146 | + var order = []; | ||
147 | + var modelCtor = ctor; | ||
148 | + this.include = include; | ||
149 | + this.select = select; | ||
150 | + this.filter = filter; | ||
151 | + this.where = filter; | ||
152 | + this.parseAs = parseAs; | ||
153 | + this.execute = execute; | ||
154 | + this.orderBy = orderBy; | ||
155 | + | ||
156 | + function parseAs(parser) { | ||
157 | + modelCtor = parser; | ||
158 | + } | ||
159 | + | ||
160 | + function include() { | ||
161 | + if (arguments.length === 2) { | ||
162 | + if (angular.isObject(arguments[1])) { | ||
163 | + //TODO: Process subquery | ||
164 | + } else if (angular.isFunction(arguments[1])) { | ||
165 | + //TODO: Process subquery | ||
166 | + } | ||
167 | + } else { | ||
168 | + [].push.apply(includes, arguments); | ||
169 | + } | ||
170 | + return this; | ||
171 | + } | ||
172 | + | ||
173 | + function orderBy(prop) { | ||
174 | + this.order.push(prop); | ||
175 | + //todo add dir and aliases | ||
176 | + } | ||
177 | + | ||
178 | + function select() { | ||
179 | + [].push.apply(selects, arguments); | ||
180 | + modelCtor = null; | ||
181 | + return this; | ||
182 | + } | ||
183 | + | ||
184 | + function filter(key, op, value) { | ||
185 | + if (arguments.length === 1) { | ||
186 | + filters.push(key); | ||
187 | + } else if (arguments.length === 3) { | ||
188 | + switch (op) { | ||
189 | + case '&&': | ||
190 | + op = 'and'; | ||
191 | + break; | ||
192 | + case '||': | ||
193 | + op = 'or'; | ||
194 | + break; | ||
195 | + case '=': | ||
196 | + case '==': | ||
197 | + case '===': | ||
198 | + op = 'eq'; | ||
199 | + break; | ||
200 | + case '!=': | ||
201 | + case '!==': | ||
202 | + case '!===': | ||
203 | + op = 'ne'; | ||
204 | + break; | ||
205 | + case '>': | ||
206 | + op = 'gt'; | ||
207 | + break; | ||
208 | + case '>=': | ||
209 | + op = 'ge'; | ||
210 | + break; | ||
211 | + case '<': | ||
212 | + op = 'lt'; | ||
213 | + break; | ||
214 | + case '<=': | ||
215 | + op = 'le'; | ||
216 | + break; | ||
217 | + default: | ||
218 | + break; | ||
219 | + } | ||
220 | + filters.push(key + ' ' + op + ' ' + value); | ||
221 | + } | ||
222 | + return this; | ||
223 | + } | ||
224 | + | ||
225 | + function execute() { | ||
226 | + var config = {}; | ||
227 | + config.params = _buildParams(); | ||
228 | + apiCall = $config.API_ENDPOINT + apiEndpoint; | ||
229 | + return $http.get(apiCall, config).then(function (response) { | ||
230 | + if (!modelCtor) { | ||
231 | + return response.data; | ||
232 | + } else { | ||
233 | + if (angular.isArray(response.data)) { | ||
234 | + var results = []; | ||
235 | + angular.forEach(response.data, function (d) { | ||
236 | + results.push(new modelCtor(d)); | ||
237 | + }); | ||
238 | + return results; | ||
239 | + } else { | ||
240 | + return new modelCtor(response.data); | ||
241 | + } | ||
242 | + } | ||
243 | + }); | ||
244 | + } | ||
245 | + | ||
246 | + function _buildParams() { | ||
247 | + var params = {}; | ||
248 | + if (includes.length) { | ||
249 | + params.$expand = includes.join(','); | ||
250 | + } | ||
251 | + if (filters.length) { | ||
252 | + params.$filter = filters.join(' and '); | ||
253 | + } | ||
254 | + if (selects.length) { | ||
255 | + params.$select = selects.join(','); | ||
256 | + } | ||
257 | + return params; | ||
258 | + } | ||
259 | + } | ||
260 | + | ||
261 | + function ModelCache() { | ||
262 | + | ||
263 | + } | ||
264 | + | ||
265 | + function BuildConstructor(apiEndpoint, schema) { | ||
266 | + function ModelCtor(values) { | ||
267 | + var values = values || {}; | ||
268 | + | ||
269 | + this.base = Entity; | ||
270 | + this.base(apiEndpoint, schema, values); | ||
271 | + } | ||
272 | + | ||
273 | + ModelCtor.prototype = new Entity; | ||
274 | + ModelCtor.$schema = schema; | ||
275 | + ModelCtor.query = query; | ||
276 | + ModelCtor.getById = getById; | ||
277 | + | ||
278 | + var passon = ModelCtor; | ||
279 | + | ||
280 | + function query() { | ||
281 | + return new Query(apiEndpoint, passon); | ||
282 | + } | ||
283 | + | ||
284 | + function getById(id) { | ||
285 | + return new Query(apiEndpoint) | ||
286 | + .filter('Id', 'eq', id); | ||
287 | + } | ||
288 | + | ||
289 | + return ModelCtor; | ||
290 | + } | ||
291 | + } | ||
292 | + } | ||
293 | + | ||
294 | + dataService.$inject = ['$config', '$http', '$q', 'Models']; | ||
295 | + function dataService($config, $http, $q, Models) { | ||
296 | + var entityIdMaps = {}; | ||
297 | + var entityArrays = {}; | ||
298 | + | ||
299 | + } | ||
300 | +})(window, angular); | ||
0 | \ No newline at end of file | 301 | \ No newline at end of file |
@@ -0,0 +1,73 @@ | @@ -0,0 +1,73 @@ | ||
1 | +(function () { | ||
2 | + var module = angular.module('framework.services.storage', []) | ||
3 | + | ||
4 | + module.factory('$localStorage', _storageFactory('localStorage')); | ||
5 | + module.factory('$sessionStorage', _storageFactory('sessionStorage')); | ||
6 | + | ||
7 | + function _storageFactory(storageType) { | ||
8 | + return ['$rootScope', '$window', '$log', | ||
9 | + function ($rootScope, $window, $log) { | ||
10 | + // #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app | ||
11 | + var webStorage = $window[storageType] || ($log.warn('This browser does not support Web Storage!'), {}), | ||
12 | + $storage = { | ||
13 | + $default: function (items) { | ||
14 | + for (var k in items) { | ||
15 | + angular.isDefined($storage[k]) || ($storage[k] = items[k]); | ||
16 | + } | ||
17 | + | ||
18 | + return $storage; | ||
19 | + }, | ||
20 | + $reset: function (items) { | ||
21 | + for (var k in $storage) { | ||
22 | + '$' === k[0] || delete $storage[k]; | ||
23 | + } | ||
24 | + | ||
25 | + return $storage.$default(items); | ||
26 | + } | ||
27 | + }, | ||
28 | + _last$storage, | ||
29 | + _debounce; | ||
30 | + | ||
31 | + for (var i = 0, k; i < webStorage.length; i++) { | ||
32 | + // #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty) | ||
33 | + (k = webStorage.key(i)) && 'ngStorage-' === k.slice(0, 10) && ($storage[k.slice(10)] = angular.fromJson(webStorage.getItem(k))); | ||
34 | + } | ||
35 | + | ||
36 | + _last$storage = angular.copy($storage); | ||
37 | + | ||
38 | + $rootScope.$watch(function () { | ||
39 | + _debounce || (_debounce = setTimeout(function () { | ||
40 | + _debounce = null; | ||
41 | + | ||
42 | + if (!angular.equals($storage, _last$storage)) { | ||
43 | + angular.forEach($storage, function (v, k) { | ||
44 | + angular.isDefined(v) && '$' !== k[0] && webStorage.setItem('ngStorage-' + k, angular.toJson(v)); | ||
45 | + | ||
46 | + delete _last$storage[k]; | ||
47 | + }); | ||
48 | + | ||
49 | + for (var k in _last$storage) { | ||
50 | + webStorage.removeItem('ngStorage-' + k); | ||
51 | + } | ||
52 | + | ||
53 | + _last$storage = angular.copy($storage); | ||
54 | + } | ||
55 | + }, 100)); | ||
56 | + }); | ||
57 | + | ||
58 | + // #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent` | ||
59 | + 'localStorage' === storageType && $window.addEventListener && $window.addEventListener('storage', function (event) { | ||
60 | + if ('ngStorage-' === event.key.slice(0, 10)) { | ||
61 | + event.newValue ? $storage[event.key.slice(10)] = angular.fromJson(event.newValue) : delete $storage[event.key.slice(10)]; | ||
62 | + | ||
63 | + _last$storage = angular.copy($storage); | ||
64 | + | ||
65 | + $rootScope.$apply(); | ||
66 | + } | ||
67 | + }); | ||
68 | + | ||
69 | + return $storage; | ||
70 | + } | ||
71 | + ]; | ||
72 | + } | ||
73 | +})() | ||
0 | \ No newline at end of file | 74 | \ No newline at end of file |
@@ -0,0 +1,157 @@ | @@ -0,0 +1,157 @@ | ||
1 | +(function (angular) { | ||
2 | + var module = angular.module('framework.table', []); | ||
3 | + | ||
4 | + var table_defaults = { | ||
5 | + table: 'table table-bordered' | ||
6 | + }; | ||
7 | + | ||
8 | + /* | ||
9 | + * Defines Table defaults and settings | ||
10 | + */ | ||
11 | + module.constant("$table_config", table_defaults); | ||
12 | + | ||
13 | + /* | ||
14 | + * Injectable Base Class for Inhertence | ||
15 | + * Functions: | ||
16 | + * Lays out rows / columns | ||
17 | + * Sets heading title | ||
18 | + * Parses cell values | ||
19 | + * Column Sizing | ||
20 | + */ | ||
21 | + module.service('BasicTableControllerBase', function () { | ||
22 | + return BasicTableControllerBase; | ||
23 | + }); | ||
24 | + | ||
25 | + /* | ||
26 | + * Injectable Base Class for Inhertence | ||
27 | + * Functions: | ||
28 | + * As Basic Table Plus: | ||
29 | + * Sortable Columns | ||
30 | + */ | ||
31 | + module.service('SortableTableControllerBase', function () { | ||
32 | + return SortableTableControllerBase; | ||
33 | + }); | ||
34 | + | ||
35 | + /* | ||
36 | + * Default Implementations | ||
37 | + */ | ||
38 | + module.controller('BasicTableController', basicTableController); | ||
39 | + module.controller('SortableTableController', sortableTableController); | ||
40 | + | ||
41 | + //#region BaseClasses | ||
42 | + | ||
43 | + function BasicTableControllerBase($scope, columns, data) { | ||
44 | + var $injector = angular.element('*[ng-app]').injector(); | ||
45 | + var $parse = $injector.get('$parse'); | ||
46 | + | ||
47 | + $scope.rows = data.data; | ||
48 | + $scope.columns = columns; | ||
49 | + $scope.getValue = getValue; | ||
50 | + | ||
51 | + var _totalWidths = columns.reduce(function (prev, current) { | ||
52 | + return prev += (current.width || '*').length; | ||
53 | + }, 0); | ||
54 | + | ||
55 | + angular.forEach(columns, function (value) { | ||
56 | + value.$$parser = angular.isFunction(value.mapping) ? value.mapping : $parse(value.mapping || value.name); | ||
57 | + value.$$width = 100.00 / _totalWidths * (value.width || '*').length + '%'; | ||
58 | + }); | ||
59 | + | ||
60 | + function getValue(row, col) { | ||
61 | + return col.$$parser(row); | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | + function SortableTableControllerBase($scope, columns, data) { | ||
66 | + this.base = BasicTableControllerBase; | ||
67 | + this.base($scope, columns, data); | ||
68 | + | ||
69 | + $scope.currentSort = { | ||
70 | + value: '', | ||
71 | + column: null, | ||
72 | + reverse: false | ||
73 | + }; | ||
74 | + $scope.currentSearch = searchFunction; | ||
75 | + $scope.sortBy = sort; | ||
76 | + $scope.searchTerm = null; | ||
77 | + | ||
78 | + function sort(column, $event) { | ||
79 | + var newSort = { | ||
80 | + value: '', | ||
81 | + column: null | ||
82 | + }; | ||
83 | + | ||
84 | + if (angular.isObject(column)) { | ||
85 | + newSort.column = column; | ||
86 | + newSort.value = column.$$parser; | ||
87 | + } else if (typeof column === "string") { | ||
88 | + angular.forEach($scope.columns, function (colDef) { | ||
89 | + if ((colDef.mapping || colDef.name) === column) { | ||
90 | + newSort.column = colDef; | ||
91 | + } | ||
92 | + }); | ||
93 | + newSort.value = column; | ||
94 | + } else if (angular.isFunction(column)) { | ||
95 | + newSort.value = column; | ||
96 | + newSort.column = null; | ||
97 | + } | ||
98 | + | ||
99 | + if ($scope.currentSort.value === newSort.value) { | ||
100 | + $scope.currentSort.reverse = !$scope.currentSort.reverse; | ||
101 | + } else { | ||
102 | + $scope.currentSort.reverse = false; | ||
103 | + } | ||
104 | + | ||
105 | + $scope.currentSort.value = newSort.value; | ||
106 | + $scope.currentSort.column = newSort.column; | ||
107 | + }; | ||
108 | + | ||
109 | + function searchFunction(row) { | ||
110 | + if (!$scope.searchTerm) { | ||
111 | + return true; | ||
112 | + } | ||
113 | + var found = false; | ||
114 | + for (var i = 0; i < columns.length; i++) { | ||
115 | + var column = $scope.columns[i]; | ||
116 | + if (angular.isUndefined(column.searchable) || column.searchable) { | ||
117 | + var value = column.$$parser(row); | ||
118 | + if (angular.isFunction(column.comparator)) { | ||
119 | + found = column.comparator(value, $scope.searchTerm); | ||
120 | + } else if (typeof value === 'string') { | ||
121 | + found = value.toLowerCase().indexOf($scope.searchTerm.toLowerCase()) >= 0; | ||
122 | + } | ||
123 | + } | ||
124 | + if (found) { | ||
125 | + break; | ||
126 | + } | ||
127 | + } | ||
128 | + return found; | ||
129 | + }; | ||
130 | + } | ||
131 | + SortableTableControllerBase.prototype = BasicTableControllerBase; | ||
132 | + | ||
133 | + //#endregion | ||
134 | + | ||
135 | + //#region Default Implementations | ||
136 | + | ||
137 | + basicTableController.$inject = ['$scope', 'classes', 'columns', 'data']; | ||
138 | + function basicTableController($scope, classes, columns, data) { | ||
139 | + this.base = BasicTableControllerBase; | ||
140 | + this.base($scope, columns, data); | ||
141 | + | ||
142 | + $scope.classes = angular.extend({}, table_defaults, classes); | ||
143 | + } | ||
144 | + basicTableController.prototype = BasicTableControllerBase; | ||
145 | + | ||
146 | + | ||
147 | + sortableTableController.$inject = ['$scope', 'classes', 'columns', 'data']; | ||
148 | + function sortableTableController($scope, classes, columns, data) { | ||
149 | + this.base = SortableTableControllerBase; | ||
150 | + this.base($scope, columns, data); | ||
151 | + | ||
152 | + $scope.classes = angular.extend({}, table_defaults, classes); | ||
153 | + } | ||
154 | + sortableTableController.prototype = SortableTableControllerBase; | ||
155 | + | ||
156 | + //#endregion | ||
157 | +})(angular); | ||
0 | \ No newline at end of file | 158 | \ No newline at end of file |
@@ -0,0 +1,18 @@ | @@ -0,0 +1,18 @@ | ||
1 | +<div class="basic-table"> | ||
2 | + <table ng-class="classes.table"> | ||
3 | + <thead ng-class="classes.head"> | ||
4 | + <tr> | ||
5 | + <th ng-repeat="col in columns" width="{{col.$$width}}" ng-class="col.classes.heading"> | ||
6 | + {{ col.name }} | ||
7 | + </th> | ||
8 | + </tr> | ||
9 | + </thead> | ||
10 | + <tbody ng-class="classes.body"> | ||
11 | + <tr ng-repeat="row in rows"> | ||
12 | + <td ng-repeat="col in columns"> | ||
13 | + {{ ::getValue(row, col) }} | ||
14 | + </td> | ||
15 | + </tr> | ||
16 | + </tbody> | ||
17 | + </table> | ||
18 | +</div> |
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +<div class="basic-table"> | ||
2 | + <input type="text" ng-model="searchTerm" /> | ||
3 | + <table ng-class="classes.table"> | ||
4 | + <thead> | ||
5 | + <tr> | ||
6 | + <th ng-repeat="col in columns" width="{{::col.$$width}}"> | ||
7 | + {{ ::col.name }} | ||
8 | + <i class="fa" ng-class="currentSort.column === col ? (currentSort.reverse ? 'fa-sort-amount-desc' : 'fa-sort-amount-asc') : 'fa-sort-amount-asc text-muted' " ng-click="sortBy(col, $event)"></i> | ||
9 | + </th> | ||
10 | + </tr> | ||
11 | + </thead> | ||
12 | + <tbody> | ||
13 | + <tr ng-repeat="row in rows | filter:currentSearch | orderBy:currentSort.value:currentSort.reverse"> | ||
14 | + <td ng-repeat="col in columns"> | ||
15 | + {{ ::getValue(row, col) }} | ||
16 | + </td> | ||
17 | + </tr> | ||
18 | + </tbody> | ||
19 | + </table> | ||
20 | +</div> |