Commit 67aeaf4e5fedcaca23c45f1cf0869380941588a3

Authored by Tarpit Grover
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 - ' &nbsp; {{column.title}}' +  
300 - ' &nbsp; <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>  
directives/BindHtmlCompile.directive.js 0 → 100644
@@ -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
directives/Card.directive.js 0 → 100644
@@ -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
directives/FieldFor.directive.js 0 → 100644
@@ -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
directives/Score.directive.js 0 → 100644
@@ -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
directives/TableFor.directive.js 0 → 100644
@@ -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 + ' &nbsp; {{column.title}}' +
  300 + ' &nbsp; <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
filters/utility.filter.js 0 → 100644
@@ -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
layouts/breadcrumb/breadcrumb.controller.js 0 → 100644
@@ -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
layouts/breadcrumb/breadcrumb.partial.html 0 → 100644
@@ -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>
layouts/documentsview/documents-view.controller.js 0 → 100644
@@ -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
layouts/documentsview/documents-view.partial.html 0 → 100644
@@ -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
layouts/module/module-base.layout.html 0 → 100644
@@ -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
layouts/module/module-cards.controller.js 0 → 100644
@@ -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
layouts/module/module-cards.partial.html 0 → 100644
@@ -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
layouts/module/module-item.controller.js 0 → 100644
@@ -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
layouts/module/module-item.layout.html 0 → 100644
@@ -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
layouts/module/module-table.controller.js 0 → 100644
@@ -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
layouts/module/module-table.partial.html 0 → 100644
@@ -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
layouts/structure/page.controller.js 0 → 100644
@@ -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
layouts/structure/page.layout.html 0 → 100644
@@ -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
layouts/table-page/table-page.layout.html 0 → 100644
@@ -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>
services/ConsoleLoggingProvider.service.js 0 → 100644
@@ -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
services/Logger.service.js 0 → 100644
@@ -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
services/Menu.service.js 0 → 100644
@@ -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
services/Model.service.js 0 → 100644
@@ -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
services/Storage.service.js 0 → 100644
@@ -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
tables/Table.controller.js 0 → 100644
@@ -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
tables/basic-table.layout.html 0 → 100644
@@ -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>
tables/sortable-table.layout.html 0 → 100644
@@ -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>