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   -(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 0 \ No newline at end of file
common_components/directives/Card.directive.js
... ... @@ -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 0 \ No newline at end of file
common_components/directives/FieldFor.directive.js
... ... @@ -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 0 \ No newline at end of file
common_components/directives/Score.directive.js
... ... @@ -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 0 \ No newline at end of file
common_components/directives/TableFor.directive.js
... ... @@ -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 0 \ No newline at end of file
common_components/filters/utility.filter.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/breadcrumb/breadcrumb.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/breadcrumb/breadcrumb.partial.html
... ... @@ -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   -(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 0 \ No newline at end of file
common_components/layouts/documentsview/documents-view.partial.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-base.layout.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-cards.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-cards.partial.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-item.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-item.layout.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-table.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/module/module-table.partial.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/structure/page.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/structure/page.layout.html
... ... @@ -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 0 \ No newline at end of file
common_components/layouts/table-page/table-page.layout.html
... ... @@ -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   -(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 0 \ No newline at end of file
common_components/services/Logger.service.js
... ... @@ -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 0 \ No newline at end of file
common_components/services/Menu.service.js
... ... @@ -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 0 \ No newline at end of file
common_components/services/Model.service.js
... ... @@ -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 0 \ No newline at end of file
common_components/services/Storage.service.js
... ... @@ -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 0 \ No newline at end of file
common_components/tables/Table.controller.js
... ... @@ -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 0 \ No newline at end of file
common_components/tables/basic-table.layout.html
... ... @@ -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   -<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 @@
  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 22 \ No newline at end of file
... ...
directives/Card.directive.js 0 → 100644
... ... @@ -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 49 \ No newline at end of file
... ...
directives/FieldFor.directive.js 0 → 100644
... ... @@ -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 219 \ No newline at end of file
... ...
directives/Score.directive.js 0 → 100644
... ... @@ -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 54 \ No newline at end of file
... ...
directives/TableFor.directive.js 0 → 100644
... ... @@ -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 593 \ No newline at end of file
... ...
filters/utility.filter.js 0 → 100644
... ... @@ -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 111 \ No newline at end of file
... ...
layouts/breadcrumb/breadcrumb.controller.js 0 → 100644
... ... @@ -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 49 \ No newline at end of file
... ...
layouts/breadcrumb/breadcrumb.partial.html 0 → 100644
... ... @@ -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 @@
  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 13 \ No newline at end of file
... ...
layouts/documentsview/documents-view.partial.html 0 → 100644
... ... @@ -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 37 \ No newline at end of file
... ...
layouts/module/module-base.layout.html 0 → 100644
... ... @@ -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 12 \ No newline at end of file
... ...
layouts/module/module-cards.controller.js 0 → 100644
... ... @@ -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 38 \ No newline at end of file
... ...
layouts/module/module-cards.partial.html 0 → 100644
... ... @@ -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 27 \ No newline at end of file
... ...
layouts/module/module-item.controller.js 0 → 100644
... ... @@ -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 15 \ No newline at end of file
... ...
layouts/module/module-item.layout.html 0 → 100644
... ... @@ -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 22 \ No newline at end of file
... ...
layouts/module/module-table.controller.js 0 → 100644
... ... @@ -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 23 \ No newline at end of file
... ...
layouts/module/module-table.partial.html 0 → 100644
... ... @@ -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 18 \ No newline at end of file
... ...
layouts/structure/page.controller.js 0 → 100644
... ... @@ -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 13 \ No newline at end of file
... ...
layouts/structure/page.layout.html 0 → 100644
... ... @@ -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 17 \ No newline at end of file
... ...
layouts/table-page/table-page.layout.html 0 → 100644
... ... @@ -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 @@
  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 68 \ No newline at end of file
... ...
services/Logger.service.js 0 → 100644
... ... @@ -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 140 \ No newline at end of file
... ...
services/Menu.service.js 0 → 100644
... ... @@ -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 46 \ No newline at end of file
... ...
services/Model.service.js 0 → 100644
... ... @@ -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 301 \ No newline at end of file
... ...
services/Storage.service.js 0 → 100644
... ... @@ -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 74 \ No newline at end of file
... ...
tables/Table.controller.js 0 → 100644
... ... @@ -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 158 \ No newline at end of file
... ...
tables/basic-table.layout.html 0 → 100644
... ... @@ -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 @@
  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>
... ...