From 62d5afb483d7ed3ffe1b2b1a9c597a73b920890d Mon Sep 17 00:00:00 2001 From: Rafael Chaves Date: Wed, 14 Jun 2017 15:07:53 -0300 Subject: [PATCH] support for UI customization abstratt/kirra-angular##47 --- images/empty-basket.png | Bin 0 -> 9331 bytes images/empty-cart-bg.jpg | Bin 0 -> 88374 bytes index.html | 1 - js/kirra-ng.js | 602 +++++++++++++++++------ templates/account-menu.html | 13 + templates/dashboard.html | 5 +- templates/edit-instance.html | 1 - templates/embedded-instance.html | 41 +- templates/entity-footer.html | 0 templates/entity-header.html | 0 templates/execute-action.html | 1 - templates/footer.html | 0 templates/header.html | 33 ++ templates/instance-list.html | 25 +- templates/instance-table-desktop.html | 6 +- templates/instance-table-mobile.html | 4 +- templates/instance-table-with-image.html | 2 +- templates/ka-data-missing-slot.html | 1 + templates/ka-data.html | 34 +- templates/ka-edit.html | 6 +- templates/login.html | 16 +- templates/main.html | 9 +- templates/menu.html | 5 + templates/nav-bar.html | 45 -- templates/product-list-custom.html | 33 ++ templates/product-list-item.html | 0 templates/product-list.html | 93 +++- templates/registration.html | 8 +- templates/shopping-cart.html | 93 ++++ templates/show-instance.html | 1 - 30 files changed, 762 insertions(+), 316 deletions(-) create mode 100644 images/empty-basket.png create mode 100644 images/empty-cart-bg.jpg create mode 100644 templates/account-menu.html create mode 100644 templates/entity-footer.html create mode 100644 templates/entity-header.html create mode 100644 templates/footer.html create mode 100644 templates/ka-data-missing-slot.html create mode 100644 templates/menu.html delete mode 100644 templates/nav-bar.html create mode 100644 templates/product-list-custom.html create mode 100644 templates/product-list-item.html create mode 100644 templates/shopping-cart.html diff --git a/images/empty-basket.png b/images/empty-basket.png new file mode 100644 index 0000000000000000000000000000000000000000..767867dddd252922c30cb8a361f32aff9f7da6c5 GIT binary patch literal 9331 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 literal 0 HcmV?d00001 diff --git a/images/empty-cart-bg.jpg b/images/empty-cart-bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..690f65801bbcbbac5a1a8b5ca3c661bfa83d43dc GIT binary patch literal 88374 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�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 a`wSobpU{Qm&Do@8(U literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 593f9af..67586c4 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,6 @@ Loading Kirra application... - diff --git a/js/kirra-ng.js b/js/kirra-ng.js index d44243b..1d96aa8 100644 --- a/js/kirra-ng.js +++ b/js/kirra-ng.js @@ -1,11 +1,7 @@ var kirraApplicationUri; var kirraApplicationPath; -var kirraTemplateMappings; -kirraTemplateMappings = kirraTemplateMappings || {}; -var kirraCustomInstanceActions; -kirraCustomInstanceActions = kirraCustomInstanceActions || {}; -var kirraCustomSlots; -kirraCustomSlots = kirraCustomSlots || {}; +var kirraUIMappings; +kirraUIMappings = kirraUIMappings || {}; var uriMatches = window.location.search.match("[?&]?app-uri\=([^&]+)"); var pathMatches = window.location.search.match("[?&]?app-path\=([^&]+)"); @@ -47,23 +43,187 @@ var entityNames; var kirraModule; var encodedCredentials = undefined; -var kirraGetTemplateUrl = function(templateName, hierarchy) { - hierarchy = hierarchy || []; - var hierarchySuffix = hierarchy.join('/'); - var found = kirraTemplateMappings[templateName + "/" + hierarchySuffix] || kirraTemplateMappings[templateName]; - return found || 'templates/' + templateName + '.html'; +var kirraUIMappings; +kirraUIMappings = kirraUIMappings || {}; + +var kirraCheckRoles = function(object, roles) { + if (object.roles && roles) { + return kirraNG.intersect(roles, object.roles).length > 0; + } + return true; +}; + +var kirraGetCustomSettings = function(viewName, hierarchy, itemName, roles) { + var entityMappings = hierarchy ? kirraUIMappings[hierarchy[0]] : kirraUIMappings['_global']; + if (entityMappings && kirraCheckRoles(entityMappings, roles)) { + if (viewName && entityMappings.views && entityMappings.views[viewName] && entityMappings.views[viewName][itemName]) { + return entityMappings.views[viewName][itemName]; + } + return entityMappings.defaults && entityMappings.defaults[itemName]; + } + return undefined; +}; + +var kirraGetDefaultTemplateUrl = function(viewName) { + return 'templates/' + viewName + '.html'; +}; + +var kirraGetTemplateUrl = function(viewName, hierarchy, roles) { + var found = kirraGetCustomSettings(viewName, hierarchy, 'template', roles); + return found ? found : kirraGetDefaultTemplateUrl(viewName); +}; + +var kirraGetCustomSlots = function(viewName, entity) { + var slotMapping = kirraGetCustomSettings(viewName, [entity.fullName], 'slotMapping'); + var result = {}; + if (slotMapping) { + angular.forEach(slotMapping, function(actual, expected) { + var asProperty = entity.properties[actual]; + var asRelationship = entity.relationships[actual]; + result[expected] = asProperty || asRelationship; + }); + } + return result; +}; + +var kirraGetCustomEdges = function(viewName, entity) { + var edgeMapping = kirraGetCustomSettings(viewName, [entity.fullName], 'edgeMapping'); + var result = {}; + if (edgeMapping) { + angular.forEach(edgeMapping, function(edgeMappingDetails, expectedEdgeName) { + var actualEdgeName = edgeMappingDetails.relationship; + var relationship = entity.relationships[actualEdgeName]; + if (!relationship) { + console.error("Unknown relationship " + entity.fullName + '.' + actualEdgeName); + return; + } + var relatedEntity = entitiesByName[relationship.typeRef.fullName]; + var edgeSlots = {}; + var slotMapping = edgeMappingDetails.slotMapping; + if (slotMapping) { + angular.forEach(slotMapping, function(actual, expected) { + var asProperty = relatedEntity.properties[actual]; + var asRelationship = relatedEntity.relationships[actual]; + edgeSlots[expected] = asProperty || asRelationship; + }); + } + var actions = edgeMappingDetails.actions; + var edgeActions = {}; + if (actions) { + angular.forEach(actions, function(actualActionName, expectedActionName) { + var operation = relatedEntity.operations[actualActionName]; + if (operation.kind == "Action" && operation.instanceOperation) { + edgeActions[expectedActionName] = operation; + } + }); + } + result[expectedEdgeName] = { + relationship: relationship, + slots: edgeSlots, + edgeActions: edgeActions, + name: expectedEdgeName + }; + }); + } + return result; +}; + + +var kirraBuildCustomMetadata = function(viewName, entity) { + var customMetadata = { + slots: kirraGetCustomSlots(viewName, entity), + edges: kirraGetCustomEdges(viewName, entity), + instanceActions: kirraGetCustomInstanceActions(viewName, entity) + } + customMetadata.dataLoader = kirraGetCustomViewData(entity, customMetadata.slots, customMetadata.instanceActions); + return customMetadata; +}; + +var kirraGetCustomInstanceActions = function(viewName, entity) { + var actions = kirraGetCustomSettings(viewName, [entity.fullName], 'actions'); + var result = {}; + if (actions) { + angular.forEach(actions, function(actualActionName, expectedActionName) { + var operation = entity.operations[actualActionName]; + if (operation.kind == "Action" && operation.instanceOperation) { + result[expectedActionName] = operation; + } + }); + } + return result; }; -var kirraGetCustomSlots = function(entityName) { - var found = kirraCustomSlots[entityName]; - return found || {}; +var kirraBuildCustomInfo = function(viewName, entity) { + var customMetadata = kirraBuildCustomMetadata(viewName, entity); + return { + metadata: customMetadata, + data: [], + edgeData: {}, + loadEdgeData: function(relationship, instances) { + var edgeMapping = kirraNG.find(this.metadata.edges, function(edgeMapping) { + return edgeMapping.relationship.name == relationship.name; + }); + var relatedEntity = entitiesByName[relationship.typeRef.fullName]; + if (edgeMapping) { + var edgeDataLoader = kirraGetCustomViewData(relatedEntity, edgeMapping.slots, edgeMapping.edgeActions); + this.edgeData[edgeMapping.name] = edgeDataLoader(instances); + } + } + }; +}; + +var kirraGetCustomViewData = function(entity, slots, instanceActions) { + var singleMapper = function(instance, idx, array) { + if (!instance) { + return undefined; + } + var result = { + objectId: instance.objectId, + shorthand: instance.shorthand + }; + angular.forEach(slots, function(slot, expected) { + if (slot.style){ + kirraNG.setViewDataForRelationship(result, instance, slot, expected); + } else { + kirraNG.setViewDataForProperty(result, instance, slot, expected); + } + }); + angular.forEach(instanceActions, function(action, expected) { + result[expected] = function(scope) { + var injector = angular.element(document.body).injector(); + var instanceService = injector.get('instanceService'); + var $state = injector.get('$state'); + kirraNG.handleInstanceAction($state, instanceService, entity, instance, action) + .then(function(reloadedInstance) { + var mapped = scope.mapped; + angular.merge(mapped, singleMapper(reloadedInstance, idx, array)); + }); + }; + }); + return result; + }; + var arrayMapper = function(instances) { + return kirraNG.map(instances, singleMapper); + }; + var mappingFunction = function(instances) { + var isArray = angular.isArray(instances); + return arrayMapper(isArray ? instances : [instances]); + }; + return mappingFunction; }; -var kirraGetCustomInstanceActions = function(entityName) { - var found = kirraCustomInstanceActions[entityName]; - return found || {}; +var kirraGetCustomEdgeViewData = function(viewName, entity, customViewMetadata) { + var edgeMapping = customViewMetadata.edgeMapping; + var singleMapper = function(genericEdgeViewData) { + return {}; + }; + var arrayMapper = function(genericViewData) { + return kirraNG.map(genericViewData, singleMapper); + }; + return arrayMapper; }; + kirraNG.capitalize = function(str) { return str.charAt(0).toUpperCase() + str.slice(1); }; @@ -71,14 +231,26 @@ kirraNG.capitalize = function(str) { kirraNG.filter = function(arrayOrMap, filter, mapping) { var result = []; mapping = mapping || function(it) { return it; }; - angular.forEach(arrayOrMap, function(it) { - if (filter(it)) { - result.push(mapping(it)); + angular.forEach(arrayOrMap, function(value, key, object) { + if (filter(value, key, object)) { + result.push(mapping(value, key, object)); } }); return result; }; +var kirraSetCustomData = function(scope, instances) { + if (scope.custom) { + scope.custom.data = scope.custom.metadata.dataLoader(instances); + } +}; + +kirraNG.intersect = function(array1, array2) { + return $.grep(array1, function(element) { + return $.inArray(element, array2) !== -1; + }); +}; + kirraNG.find = function(arrayOrMap, filter) { var found = undefined; angular.forEach(arrayOrMap, function(it, it2) { @@ -206,24 +378,7 @@ kirraNG.getEnabledActions = function(instance, instanceActions) { // the basic buildViewData does) would cause all sorts of problems kirraNG.buildViewDataAsArray = function(entity, instance) { // need to preserve order to allow retrieval by index - var fieldValuesByName = {}; - angular.forEach(entity.properties, function(property) { - if (property.userVisible) { - fieldValuesByName[property.name] = instance.values[property.name]; - } - }); - angular.forEach(entity.relationships, function(relationship) { - if (relationship.userVisible && !relationship.multiple) { - if (instance.links[relationship.name]) { - fieldValuesByName[relationship.name] = { - shorthand: instance.links[relationship.name].shorthand, - objectId: instance.links[relationship.name].objectId - }; - } else { - fieldValuesByName[relationship.name] = {}; - } - } - }); + var fieldValuesByName = kirraNG.buildViewData(entity, instance); var orderedDataElements = kirraNG.getOrderedDataElements(entity); var fieldValues = []; angular.forEach(orderedDataElements, function(name) { @@ -254,23 +409,46 @@ kirraNG.getOrderedDataElements = function(entity) { kirraNG.buildViewData = function(entity, instance) { var data = {}; - angular.forEach(entity.properties, function(property, name) { - if (property.userVisible && instance.values[name] != undefined) { - data[name] = instance.values[name]; - } + angular.forEach(entity.properties, function(property) { + kirraNG.setViewDataForProperty(data, instance, property); }); - angular.forEach(entity.relationships, function(relationship, name) { - if (relationship.userVisible && !relationship.multiple) { - var link = instance.links[name]; - data[name] = link ? { - shorthand: link.shorthand, - objectId: link.objectId - } : {} - } + angular.forEach(entity.relationships, function(relationship) { + kirraNG.setViewDataForRelationship(data, instance, relationship); }); return data; }; +kirraNG.handleInstanceAction = function($state, instanceService, entity, instanceRef, action, arguments) { + if (action.parameters.length > 0 && !arguments) { + $state.go(kirraNG.toState(entity.fullName, 'performInstanceAction'), { objectId: instanceRef.objectId, shorthand: instanceRef.shorthand, actionName: action.name } ); + // we don't call back in this case... + return { then: function(it) { return it; } }; + } + return instanceService.performInstanceAction(entity, instanceRef.objectId, action.name, arguments).then( + function() { + return instanceService.get(entity, instanceRef.objectId); + } + ); +}; + +kirraNG.setViewDataForProperty = function(data, instance, property, alternativeSlotName) { + var slotName = alternativeSlotName || property.name; + if (property.userVisible) { + data[slotName] = instance.values[property.name]; + } +}; + +kirraNG.setViewDataForRelationship = function(data, instance, relationship, alternativeSlotName) { + var slotName = alternativeSlotName || relationship.name; + if (relationship.userVisible && !relationship.multiple) { + var link = instance.links[relationship.name]; + data[slotName] = link ? { + shorthand: link.shorthand, + objectId: link.objectId + } : {} + } +}; + kirraNG.loadEntityCapabilities = function(loadedCallback) { repository.loadEntityCapabilities(function(loadedEntityCapabilities) { entityCapabilitiesByName = loadedEntityCapabilities; @@ -278,7 +456,6 @@ kirraNG.loadEntityCapabilities = function(loadedCallback) { }); }; - kirraNG.buildRowData = function(entity, instance, instanceActions) { var data = kirraNG.buildViewData(entity, instance); var row = { @@ -377,9 +554,9 @@ kirraNG.buildInstanceListController = function(entity) { $scope.actions = kirraNG.getInstanceActions(entity); $scope.anyListCapability = true; $scope.instances = undefined; + $scope.rows = undefined; $scope.queries = kirraNG.getQueries(entity); $scope.entityActions = kirraNG.getEntityActions(entity); - $scope.togglePickerStatus = function($event, propertyName) { kirraNG.togglePickerStatus($event, $scope, propertyName); }; $scope.applyFilter = function() { var newStateParams = angular.merge({}, $state.params, { arguments: $scope.parameterValues, forceFetch: true }); $state.go($state.current.name, newStateParams, { reload: true }); @@ -395,8 +572,7 @@ kirraNG.buildInstanceListController = function(entity) { }; $scope.maxSize = 5; $scope.totalItems = 34; - $scope.customSlots = kirraGetCustomSlots(entity.fullName); - $scope.customInstanceActions = kirraGetCustomInstanceActions(entity.fullName); + $scope.custom = kirraBuildCustomInfo('instance-list', entity); angular.forEach(finderArguments, function (arg, name) { if (typeof(arg) == 'object' && arg instanceof Date) { finderArguments[name] = moment(arg).format("YYYY/MM/DD"); @@ -404,8 +580,6 @@ kirraNG.buildInstanceListController = function(entity) { }); var performQuery = function(arguments, forceFetch) { - $scope.instances = undefined; - $scope.rows = undefined; var missingArguments = kirraNG.filter(finder.parameters, function(p) { return p.required; }, function (p) { return p.name; } ); angular.forEach(arguments, function(value, name) { var index = missingArguments.indexOf(name); @@ -418,6 +592,7 @@ kirraNG.buildInstanceListController = function(entity) { .then(function(instances) { $scope.instances = instances; $scope.rows = kirraNG.buildTableData(instances, entity); + setCustomData($scope, instances); $scope.resultMessage = instances.length > 0 ? "" : "No data found"; }).catch(function(error) { $scope.resultMessage = error.data.message; @@ -429,17 +604,23 @@ kirraNG.buildInstanceListController = function(entity) { return parameter.label; }); $scope.instances = []; + $scope.rows = []; + kirraSetCustomData($scope, []); $scope.resultMessage = "Before you can apply this filter, you must fill in: " + parameterLabels; } }; var populate = function() { + $scope.instances = undefined; + $scope.rows = undefined; + kirraSetCustomData($scope, undefined); if (finder) { performQuery(finderArguments, forceFetch); } else { instanceService.extent(entity).then(function(instances) { $scope.instances = instances; $scope.rows = kirraNG.buildTableData(instances, entity); + kirraSetCustomData($scope, instances); $scope.resultMessage = instances.length > 0 ? "" : "No data found"; }); } @@ -499,24 +680,21 @@ kirraNG.buildInstanceListController = function(entity) { $state.go(kirraNG.toState(entity.fullName, 'list')); }; - $scope.performInstanceActionOnRow = function(row, action) { - var objectId = row.raw.objectId; - var shorthand = row.raw.shorthand; - - if (action.parameters.length > 0) { - $state.go(kirraNG.toState(entity.fullName, 'performInstanceAction'), { objectId: objectId, shorthand: shorthand, actionName: action.name } ); - return; - } + $scope.performInstanceActionOnRow = function(instance, action) { + var objectId = instance.objectId; + var shorthand = instance.shorthand; - var performResult = instanceService.performInstanceAction(entity, objectId, action.name); - if (finder) { - // better reload as the row may no longer satisfy the filter - performResult.then(populate); - } else { - // when showing all, update only the row affected - performResult.then( - populate - ); + var performResult = kirraNG.handleInstanceAction($state, instanceService, entity, { objectId: objectId, shorthand: shorthand }, action); + if (performResult) { + if (finder) { + // better reload as the row may no longer satisfy the filter + performResult.then(populate); + } else { + // when showing all, update only the row affected + performResult.then( + populate + ); + } } }; @@ -578,12 +756,12 @@ kirraNG.buildInstanceEditController = function(entity, mode) { $scope.objectId = objectId; $scope.actionEnablement = kirraNG.buildActionEnablement(kirraNG.getInstanceActions(actualEntity)); $scope.entityName = actualEntity.fullName; - $scope.togglePickerStatus = function($event, propertyName) { kirraNG.togglePickerStatus($event, $scope, propertyName); }; $scope.propertyValues = {}; $scope.linkValues = {}; $scope.loadInstanceCallback = function(instance) { $scope.formLabel = creation ? ('Creating ' + actualEntity.label) : (childCreation ? ('Adding ' + actualEntity.label) : ('Editing ' + actualEntity.label + ': ' + instance.shorthand)); $scope.raw = instance; + kirraSetCustomData($scope, instance); $scope.actionEnablement.load(instance); angular.merge($scope.propertyValues, angular.copy(instance.values)); angular.merge($scope.linkValues, angular.copy(instance.links)); @@ -668,7 +846,6 @@ kirraNG.buildActionController = function(entity) { $scope.action = action; $scope.inputFields = action.parameters; $scope.parameterValues = {}; - $scope.togglePickerStatus = function($event, propertyName) { kirraNG.togglePickerStatus($event, $scope, propertyName); }; if (objectId) { instanceService.get(entity, objectId).then(function(instance) { @@ -700,11 +877,12 @@ kirraNG.buildActionController = function(entity) { $scope.performAction = function() { var arguments = angular.copy($scope.parameterValues); var objectId = $scope.objectId; - var actionName = $scope.actionName; + var shorthand = $scope.shorthand; if (objectId == undefined) { - instanceService.performEntityAction(entity, actionName, arguments).then(kirraNG.handleActionResponse($state, entity, actionName)); + instanceService.performEntityAction(entity, action.name, arguments).then(kirraNG.handleActionResponse($state, entity, action.name)); } else { - instanceService.performInstanceAction(entity, objectId, actionName, arguments).then(kirraNG.handleActionResponse($state, entity, actionName)); + kirraNG.handleInstanceAction($state, instanceService, entity, { objectId: objectId, shorthand: shorthand }, action, arguments) + .then(kirraNG.handleActionResponse($state, entity, actionName)); } }; }; @@ -716,7 +894,7 @@ kirraNG.handleActionResponse = function ($state, entity, actionName) { return function(response) { var action = actionName && entity.operations[actionName]; if (action.typeRef && action.typeRef.kind == 'Entity') { - var resultInstance = response.data[0]; + var resultInstance = response; var resultEntity = entitiesByName[action.typeRef.fullName]; $state.go(kirraNG.toState(resultEntity.fullName, 'show'), { objectId: resultInstance.objectId } ); } else { @@ -826,7 +1004,7 @@ kirraNG.mergeEdgeRowDatas = function(rows, newRows) { }; kirraNG.buildInstanceShowController = function(entity) { - var controller = function($scope, $state, $stateParams, instanceService, $q, $modal) { + var controller = function($scope, $state, $stateParams, instanceService, instanceViewService, $q, $modal) { var objectId = $stateParams.objectId; @@ -846,6 +1024,7 @@ kirraNG.buildInstanceShowController = function(entity) { $scope.loadInstanceCallback = function(instance) { var instanceActions = kirraNG.getInstanceActions(entity); $scope.raw = instance; + kirraSetCustomData($scope, instance); $scope.actionEnablement = kirraNG.buildActionEnablement(instanceActions).load(instance); $scope.instanceActions = instanceActions; $scope.fieldValues = kirraNG.buildViewDataAsArray(entity, instance); @@ -864,6 +1043,7 @@ kirraNG.buildInstanceShowController = function(entity) { }; $scope.viewFields = kirraNG.buildViewFields(entity); + $scope.custom = kirraBuildCustomInfo('show-instance', entity); $scope.edit = function() { console.log(entity); @@ -886,7 +1066,7 @@ kirraNG.buildInstanceShowController = function(entity) { var objectId = this.objectId; var modal = $modal.open({ animation: true, - templateUrl: kirraGetTemplateUrl('link-instance'), + templateUrl: kirraGetTemplateUrl('link-instance', undefined, $scope.currentUserRoles), size: 'lg', controller: entity.fullName + 'InstanceLinkCtrl', resolve: { @@ -906,12 +1086,8 @@ kirraNG.buildInstanceShowController = function(entity) { }; $scope.performAction = function(action) { - if (action.parameters.length > 0) { - $state.go(kirraNG.toState(entity.fullName, 'performInstanceAction'), { objectId: objectId, actionName: action.name } ); - return; - } - instanceService.performInstanceAction(entity, objectId, action.name).then( - function() { return instanceService.get(entity, objectId); } + kirraNG.handleInstanceAction($state, instanceService, entity, + { objectId: objectId, shorthand: undefined }, action ).then($scope.loadInstanceCallback).then($scope.loadInstanceRelatedCallback); }; @@ -923,13 +1099,6 @@ kirraNG.buildInstanceShowController = function(entity) { */ var buildEdgeData = function(relationship) { var relatedEntity = entitiesByName[relationship.typeRef.fullName]; - /* - * Data for multivalued relationships is kept in the form of - * edgeDatas. An edgeData is meant to be bound to a scope, and is - * the basis for dynamic UI rendering. The edgeData includes both - * metadata about the relationship, and the data for that - * relationship (rows). - */ var newArrayWithTimestamp = []; newArrayWithTimestamp.timestamp = new Date(); var edgeData = { @@ -940,16 +1109,12 @@ kirraNG.buildInstanceShowController = function(entity) { relatedViewFields: kirraNG.buildViewFields(relatedEntity), relatedInstanceActions: kirraNG.getInstanceActions(relatedEntity), performInstanceActionOnRow: function(row, action) { - var relatedObjectId = row.raw.objectId; - var shorthand = row.raw.shorthand; + var relatedInstance = row.raw; + var relatedObjectId = relatedInstance.objectId; + var shorthand = relatedInstance.shorthand; - if (action.parameters.length > 0) { - $state.go(kirraNG.toState(relatedEntity.fullName, 'performInstanceAction'), { objectId: relatedObjectId, shorthand: shorthand, actionName: action.name } ); - return; - } - - instanceService.performInstanceAction(relatedEntity, relatedObjectId, action.name).then( - function() { return instanceService.get(entity, objectId); } + kirraNG.handleInstanceAction($state, instanceService, relatedEntity, + { objectId: relatedObjectId, shorthand: shorthand }, action ).then($scope.loadInstanceCallback).then($scope.loadInstanceRelatedCallback); }, rows: [] @@ -993,11 +1158,12 @@ kirraNG.buildInstanceShowController = function(entity) { // to find the proper edgeData object to inject the results // into var tableData = kirraNG.map(relatedInstances, function(relatedInstance) { - return { - data: kirraNG.buildViewDataAsArray(relatedEntity, relatedInstance), - raw: relatedInstance - }; - }); + return { + data: kirraNG.buildViewDataAsArray(relatedEntity, relatedInstance), + raw: relatedInstance + }; + }); + $scope.custom.loadEdgeData(relationship, relatedInstances); kirraNG.mergeEdgeRowDatas(edgeData.rows, tableData); }); relationshipTasks.push(next); @@ -1007,10 +1173,78 @@ kirraNG.buildInstanceShowController = function(entity) { instanceService.get(entity, objectId).then($scope.loadInstanceCallback).then($scope.loadInstanceRelatedCallback); }; - controller.$inject = ['$scope', '$state', '$stateParams', 'instanceService', '$q', '$modal']; + controller.$inject = ['$scope', '$state', '$stateParams', 'instanceService', 'instanceViewService', '$q', '$modal']; return controller; }; +kirraNG.buildInstanceViewService = function() { + var serviceFactory = function(instanceService, $q) { + + var InstanceView = function () { + + this.loadAllRelatedInstances = function(loadedInstance) { + var entity = entitiesByName[loadedInstance.typeRef.fullName]; + var objectId = loadedInstance.objectId; + var childRelationships = kirraNG.getMultiChildRelationships(entity); + var regularRelationships = kirraNG.getMultiRegularRelationships(entity); + var multipleRelationships = childRelationships.concat(regularRelationships); + return this.loadRelatedInstancesForRelationships(entity, objectId, multipleRelationships); + }; + + this.loadRelatedInstancesForRelationships = function(entity, objectId, multipleRelationships) { + var relationshipTasks = []; + + angular.forEach(multipleRelationships, function(relationship) { + var relatedEntity = entitiesByName[relationship.typeRef.fullName]; + var edgeData = kirraNG.find(edgeDatas, function (edgeData) { return edgeData.relationship == relationship }); + // take subtyping into account (every concrete subtype gets its own edgeData + if (edgeData.relatedEntity.subTypes && edgeData.relatedEntity.subTypes.length > 0) { + angular.forEach(edgeData.relatedEntity.subTypes, function (subType) { + var subEntity = entitiesByName[subType.fullName]; + if (subEntity.concrete) { + // TODO-RC this is inconsistent - use a single function to build edgeData + edgeDatas.push({ + relationshipLabel: relationship.label + " (" + subType.typeName + ")", + relationship: relationship, + relatedEntity: subEntity, + rows: [] + }); + } + }); + } + + var next = instanceService.getRelated(entity, objectId, relationship.name).then( + function(relatedInstances) { + // the list of related instances may be heterogeneous - need + // to find the proper edgeData object to inject the results + // into + var tableData = kirraNG.map(relatedInstances, function(relatedInstance) { + return { + data: kirraNG.buildViewDataAsArray(relatedEntity, relatedInstance), + raw: relatedInstance + }; + }); + // TODO: should we try to convert to custom instances here? + //$scope.custom.loadEdgeData(relationship, relatedInstances); + kirraNG.mergeEdgeRowDatas(edgeData.rows, tableData); + } + ); + relationshipTasks.push(next); + }); + return $q.all(relationshipTasks); + }; + + this.loadInstanceAndAllEdges = function(entity, objectId) { + return instanceService.get(entity, objectId) + .then(this.loadAllRelatedInstances); + }; + }; + return InstanceView; + }; + return serviceFactory; +}; + + kirraNG.buildInstanceService = function() { var serviceFactory = function($rootScope, $http) { var Instance = function (data) { @@ -1204,7 +1438,6 @@ kirraModule.service('loginDialog', function($rootScope, $modal, $http, $state, k this.modal = $modal.open({ animation: true, templateUrl: kirraGetTemplateUrl('login'), - size: 'sm', controller: 'LoginCtrl' }); this.modal.result.then(function(credentials) { @@ -1257,7 +1490,6 @@ kirraModule.service('registrationDialog', function($rootScope, $modal, $http, $s this.modal = $modal.open({ animation: true, templateUrl: kirraGetTemplateUrl('registration'), - size: 'sm', controller: 'RegistrationCtrl', resolve: { registrationEntity: function () { @@ -1390,6 +1622,7 @@ repository.loadApplication(function(loadedApp, status) { $scope.applicationOptions = application.options; $scope.kirraNG = kirraNG; $scope.currentUser = undefined; + $scope.currentUserRoles = undefined; console.log(entityCapabilities); $scope.logout = function() { console.log("Logging out"); @@ -1409,7 +1642,11 @@ repository.loadApplication(function(loadedApp, status) { }; $scope.getTemplateUrl = function(templateName, hierarchy) { - return kirraGetTemplateUrl(templateName, hierarchy); + return kirraGetTemplateUrl(templateName, hierarchy, $scope.currentUserRoles); + }; + + $scope.getDefaultTemplateUrl = function(templateName) { + return kirraGetDefaultTemplateUrl(templateName); }; $scope.canChangeTheme = canChangeTheme; @@ -1428,12 +1665,67 @@ repository.loadApplication(function(loadedApp, status) { $http.get(application.currentUser).then(function(loaded) { $scope.currentUser = loaded.data; }); + } else { + $scope.currentUser = undefined; } + $scope.currentUserRoles = application.currentUserRoles == undefined ? undefined : kirraNG.map(application.currentUserRoles, function (uri, role) { + return role; + }); if (status != 200 || (!application.currentUser && application.options && application.options.isLoginRequired)) { loginDialog.show(); } }); + + kirraModule.directive('lazyScript', function() { + return { + restrict: 'E', + scope: false, + link: function(scope, elem, attr) { + var s = document.createElement("script"); + s.type = "text/javascript"; + var src = elem.attr('src'); + if(src!==undefined) { + s.src = src; + } else { + var code = elem.text(); + s.text = code; + } + document.head.appendChild(s); + elem.remove(); } + }; + }); + + kirraModule.directive('kaSingleton', function(instanceService, $state) { + return { + transclude: true, + scope: { + // these are set at the directive call site + entityName: '@', + queryName: '@' + }, + link: function (scope, element, attrs, ctrl, transclude) { + var entityName = scope.entityName; + var queryName = scope.queryName; + var entity = entitiesByName[entityName]; + scope.custom = kirraBuildCustomInfo(undefined, entity); + transclude(scope, function(clone, scope) { + element.append(clone); + }); + instanceService.performQuery(entity, queryName) + .then(function(instances) { + var singletonInstance = (instances && instances[0]); + scope.singletonStateHref = $state.href(kirraNG.toState(entity.fullName, 'show'), {objectId: singletonInstance.objectId }); + kirraSetCustomData(scope, singletonInstance); + scope.custom.edgeData = scope.custom.metadata.edgeDataLoader(singletonInstance); + scope.singletonInstance = singletonInstance; + }); + }, + template: "
" + }; + }); + + kirraModule.directive('instanceDetails', [function() { return { scope: { @@ -1450,7 +1742,7 @@ repository.loadApplication(function(loadedApp, status) { }, template: '
', link: function (scope) { - scope.templateUrl = kirraGetTemplateUrl("embedded-instance", [scope.embeddedEntity.name]); + scope.templateUrl = kirraGetTemplateUrl("embedded-instance", [scope.embeddedEntity.name], scope.currentUserRoles); } }; }]); @@ -1467,14 +1759,11 @@ repository.loadApplication(function(loadedApp, status) { }, template: '
', link: function (scope) { - scope.templateUrl = kirraGetTemplateUrl("embedded-instance-actions", [scope.embeddedEntity.name]); + scope.templateUrl = kirraGetTemplateUrl("embedded-instance-actions", [scope.embeddedEntity.name], scope.currentUserRoles); } }; }]); - - - kirraModule.directive('instanceTable', ['$window', function($window) { return { restrict: 'E', @@ -1490,9 +1779,9 @@ repository.loadApplication(function(loadedApp, status) { function changeTemplate() { var screenWidth = $window.innerWidth; if (screenWidth < 768) { - scope.templateUrl = kirraGetTemplateUrl('instance-table-mobile', [scope.entity.fullName]); + scope.templateUrl = kirraGetTemplateUrl('instance-table-mobile', [scope.entity.fullName], scope.currentUserRoles); } else { - scope.templateUrl = kirraGetTemplateUrl('instance-table-desktop', [scope.entity.fullName]); + scope.templateUrl = kirraGetTemplateUrl('instance-table-desktop', [scope.entity.fullName], scope.currentUserRoles); } } } @@ -1533,25 +1822,25 @@ repository.loadApplication(function(loadedApp, status) { scope.targetObjectId = slotData && slotData.objectId ; scope.targetStateName = kirraNG.toState(slot.typeRef.fullName, 'show'); } - + if (slot.typeRef.typeName == 'Date' || slot.typeRef.typeName == 'DateTime') { + scope.togglePickerStatus = function(event) { + kirraNG.togglePickerStatus(event, scope, slot.name); + }; + } }, templateUrl: 'templates/ka-edit.html' }; }); + - kirraModule.directive('kaData', function(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox) { + var kaDirectiveFunction = function(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox) { return { - restrict: 'E', - scope: { - // these are set at the directive call site - slot: '=', - slotData: '=', - objectId: '=', - table: '=', - grid: '=' - }, - link: function (scope, element) { + link: function (scope, element, attributes, controller, transcludeFn) { var slot = scope.slot; + if (!slot) { + // bad mapping? + return; + } var slotData = scope.slotData; var objectId = scope.objectId; var isTable = scope.table; @@ -1598,12 +1887,12 @@ repository.loadApplication(function(loadedApp, status) { scope.files = undefined; }; scope.attachmentRemove = function(slot, slotData, files) { - instanceService.deleteBlob(entitiesByName[slot.owner.fullName], slot.name, objectId || scope.$parent.$parent.objectId, slotData.token).then(function() { + instanceService.deleteBlob(entitiesByName[slot.owner.fullName], slot.name, scope.objectId, slotData.token).then(function() { $state.go($state.current.name, $state.params, { reload: true }); }); }; scope.getAttachmentDownloadUri = function(slot, slotData) { - return instanceService.getBlobUri(entitiesByName[slot.owner.fullName], slot.name, objectId || scope.$parent.$parent.objectId, slotData.token); + return instanceService.getBlobUri(entitiesByName[slot.owner.fullName], slot.name, scope.objectId, slotData.token); }; scope.attachmentShow = function (slot, slotData) { Lightbox.openModal([{ @@ -1792,12 +2081,50 @@ repository.loadApplication(function(loadedApp, status) { setPositionTo(slot, position.coords, false); }); }; - }; + } + if (transcludeFn) { + transcludeFn(scope, function(clone, scope) { + element.append(clone); + }); + } + } + }; + }; + + kirraModule.directive('kaData', function(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox) { + var directive = kaDirectiveFunction(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox); + angular.merge(directive, { + restrict: 'E', + scope: { + // these are set at the directive call site + slot: '=', + slotData: '=', + objectId: '=', + table: '=', + grid: '=', + size: "=" }, templateUrl: 'templates/ka-data.html' - }; + }); + return directive; }); - + + kirraModule.directive('kaWrapper', function(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox) { + var directive = kaDirectiveFunction(uiUploader, instanceService, kirraNotification, $state, $sce, Lightbox); + angular.merge(directive, { + restrict: 'E', + transclude: true, + scope: { + // these are set at the directive call site + slot: '=', + slotData: '=', + objectId: '=' + }, + template: '
' + }); + return directive; + }); + kirraModule.controller('DashboardCtrl', kirraNG.buildDashboardController()); angular.forEach(entitiesByName, function (entity, entityName) { @@ -1816,6 +2143,7 @@ repository.loadApplication(function(loadedApp, status) { kirraModule.controller('RegistrationCtrl', kirraNG.registrationController); kirraModule.factory('instanceService', kirraNG.buildInstanceService()); + kirraModule.factory('instanceViewService', kirraNG.buildInstanceViewService()); kirraModule.config(function($stateProvider, $urlRouterProvider) { var first = entityNames.find(function(name) { return entitiesByName[name].topLevel }); @@ -1825,7 +2153,7 @@ repository.loadApplication(function(loadedApp, status) { url: "/dashboard/", controller: 'DashboardCtrl', templateUrl: function(context) { - return kirraGetTemplateUrl('dashboard'); + return kirraGetTemplateUrl('dashboard', undefined); } }); diff --git a/templates/account-menu.html b/templates/account-menu.html new file mode 100644 index 0000000..4504994 --- /dev/null +++ b/templates/account-menu.html @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/templates/dashboard.html b/templates/dashboard.html index 8f72d57..be0900b 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -17,16 +17,13 @@
-
- {{metric.query.description}} -
-
{{metric.result}}
-
{{metric.query.label}}
+
{{metric.query.label}}
diff --git a/templates/edit-instance.html b/templates/edit-instance.html index df0e20e..cbba88f 100644 --- a/templates/edit-instance.html +++ b/templates/edit-instance.html @@ -1,4 +1,3 @@ -
diff --git a/templates/embedded-instance.html b/templates/embedded-instance.html index 2b0ef70..59bf7ba 100644 --- a/templates/embedded-instance.html +++ b/templates/embedded-instance.html @@ -1,4 +1,4 @@ -
+
@@ -10,41 +10,4 @@
-
- - - - - - - - - - - - - - - - \ No newline at end of file +
\ No newline at end of file diff --git a/templates/entity-footer.html b/templates/entity-footer.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/entity-header.html b/templates/entity-header.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/execute-action.html b/templates/execute-action.html index 67fc520..ef0eab3 100644 --- a/templates/execute-action.html +++ b/templates/execute-action.html @@ -1,4 +1,3 @@ -
diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/header.html b/templates/header.html index e69de29..953104b 100644 --- a/templates/header.html +++ b/templates/header.html @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/templates/instance-list.html b/templates/instance-list.html index 22f6c43..6d84ae3 100644 --- a/templates/instance-list.html +++ b/templates/instance-list.html @@ -1,13 +1,16 @@ -
-
+
+
{{entity.label}}: {{finder ? finder.label : 'All'}}
-
-
+
+
+
+ +
-
-
-

-
-
-
-
-
-
-
-
+
+
+
diff --git a/templates/instance-table-desktop.html b/templates/instance-table-desktop.html index 57ffcb8..b2f6f4c 100644 --- a/templates/instance-table-desktop.html +++ b/templates/instance-table-desktop.html @@ -25,21 +25,21 @@
- +
diff --git a/templates/instance-table-mobile.html b/templates/instance-table-mobile.html index 1c2067b..7694599 100644 --- a/templates/instance-table-mobile.html +++ b/templates/instance-table-mobile.html @@ -31,14 +31,14 @@
- + diff --git a/templates/instance-table-with-image.html b/templates/instance-table-with-image.html index f82d72c..4939af7 100644 --- a/templates/instance-table-with-image.html +++ b/templates/instance-table-with-image.html @@ -15,7 +15,7 @@

- +

diff --git a/templates/ka-data-missing-slot.html b/templates/ka-data-missing-slot.html new file mode 100644 index 0000000..338dab6 --- /dev/null +++ b/templates/ka-data-missing-slot.html @@ -0,0 +1 @@ +
?
\ No newline at end of file diff --git a/templates/ka-data.html b/templates/ka-data.html index de3ae8e..4f2e47b 100644 --- a/templates/ka-data.html +++ b/templates/ka-data.html @@ -7,7 +7,7 @@
-
+
{{slotData}}
@@ -35,22 +35,20 @@
{{slot.enumerationLiterals[slotData]}}
-
- + + +
@@ -77,20 +75,8 @@
- - -
-
diff --git a/templates/ka-edit.html b/templates/ka-edit.html index 80b3d5e..7976e75 100644 --- a/templates/ka-edit.html +++ b/templates/ka-edit.html @@ -20,12 +20,14 @@ off="No">

- +

diff --git a/templates/login.html b/templates/login.html index b2ca58c..e1a7ee1 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,15 +1,15 @@ -
-

+
+

-
+

{{applicationLabel}}

-

+

-
+
Please sign in @@ -25,14 +25,14 @@

{{applicationLabel}}

-

+

-
+

Register as {{entity.label}}

-

+

diff --git a/templates/main.html b/templates/main.html index 4512cf8..53edd65 100644 --- a/templates/main.html +++ b/templates/main.html @@ -1,7 +1,7 @@
-
+
- + {{alert.msg}} @@ -9,5 +9,10 @@
+ +
+
+
+ diff --git a/templates/menu.html b/templates/menu.html new file mode 100644 index 0000000..94d78cf --- /dev/null +++ b/templates/menu.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/templates/nav-bar.html b/templates/nav-bar.html deleted file mode 100644 index bff0fa5..0000000 --- a/templates/nav-bar.html +++ /dev/null @@ -1,45 +0,0 @@ - \ No newline at end of file diff --git a/templates/product-list-custom.html b/templates/product-list-custom.html new file mode 100644 index 0000000..bdfc49a --- /dev/null +++ b/templates/product-list-custom.html @@ -0,0 +1,33 @@ +
+
+
+
+ +
+
+ + + +

+ + +

+
+

+ + + +

+

+ + + +

+
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/templates/product-list-item.html b/templates/product-list-item.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/product-list.html b/templates/product-list.html index bd48b18..5581478 100644 --- a/templates/product-list.html +++ b/templates/product-list.html @@ -1,28 +1,69 @@ -
-
- - - -

- - -

-
-

- - - -

-

- - - -

-
-
- -
+ + +
+
+
-
\ No newline at end of file +
diff --git a/templates/registration.html b/templates/registration.html index 6ae5da9..0782d66 100644 --- a/templates/registration.html +++ b/templates/registration.html @@ -1,11 +1,11 @@ -
+
-
+
-
+
@@ -21,7 +21,7 @@
-
+

Already a user? Click here to sign in.

diff --git a/templates/shopping-cart.html b/templates/shopping-cart.html new file mode 100644 index 0000000..2a61248 --- /dev/null +++ b/templates/shopping-cart.html @@ -0,0 +1,93 @@ +
+
+
+
+ {{metadata.edges.cartItems.slots.productImage.label}} +
+
+ {{metadata.edges.cartItems.slots.productName.label}} +
+
+ {{metadata.edges.cartItems.slots.unitPrice.label}} +
+
+ {{metadata.edges.cartItems.slots.quantity.label}} +
+
+ {{metadata.edges.cartItems.slots.subtotal.label}} +
+
+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + +
+
+
+ + +
+
+ +
+
+ +
+
+
+ + + + + + + + + + + + + +
{{metadata.slots.subtotal.label}}{{cart.subtotal}}
{{metadata.slots.extra.label}}{{cart.extra}}
{{metadata.slots.total.label}}{{cart.total}}
+
+
+ +
+
+
+
+
+ + +
+
+
+
+ +
SHOPPING CART IS
+
EMPTY
+
+ +
+
+
\ No newline at end of file diff --git a/templates/show-instance.html b/templates/show-instance.html index 01eacf2..0cd4ed8 100644 --- a/templates/show-instance.html +++ b/templates/show-instance.html @@ -1,4 +1,3 @@ -