From ae9d5da3296cf0b13a51ab43b0296ab6bbbb4731 Mon Sep 17 00:00:00 2001 From: Julius Haertl Date: Sun, 5 Jun 2016 23:39:15 +0200 Subject: [PATCH] Some more stuff --- .gitignore | 2 + controller/stackcontroller.php | 8 +- css/style.css | 9 +- js/.jshintrc | 49 +++ js/Gruntfile.js | 130 ++++++++ js/Makefile | 6 + js/controller/BoardController.js | 121 +++----- js/controller/ListController.js | 11 +- js/gulpfile.js | 88 ++++++ js/package.json | 34 ++ js/public/app.js | 496 ++++++++++++++++++++++++++++++ js/service/apiservice.js | 119 ++++++- js/service/factory.board.js | 12 +- js/service/factory.stack.js | 83 +---- service/stackservice.php | 4 +- templates/main.php | 10 +- templates/part.board.mainView.php | 24 +- templates/part.navigation.php | 6 +- 18 files changed, 1027 insertions(+), 185 deletions(-) create mode 100644 .gitignore create mode 100644 js/.jshintrc create mode 100644 js/Gruntfile.js create mode 100644 js/Makefile create mode 100644 js/gulpfile.js create mode 100644 js/package.json create mode 100644 js/public/app.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..abc6ba3c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +js/node_modules/* +js/vendor/ diff --git a/controller/stackcontroller.php b/controller/stackcontroller.php index 5c2c07893..0aeb545ba 100644 --- a/controller/stackcontroller.php +++ b/controller/stackcontroller.php @@ -41,13 +41,13 @@ class StackController extends Controller { /** * @NoAdminRequired */ - public function update($id, $title, $color) { - return $this->stackService->update($id, $title, $this->userId, $color); + public function update($id, $title, $boardId, $order) { + return $this->stackService->update($id, $title, $boardId, $order); } /** * @NoAdminRequired */ - public function delete($boardId) { - return $this->stackService->delete($this->userId, $boardId); + public function delete($stackId) { + return $this->stackService->delete($this->userId, $stackId); } } diff --git a/css/style.css b/css/style.css index e8c131c8b..f263403d1 100644 --- a/css/style.css +++ b/css/style.css @@ -84,6 +84,7 @@ li:hover .app-navigation-entry-utils-counter { margin: 0; font-size:12pt; font-weight:700; + overflow:hidden; } .stack h2 input { padding: 0px; @@ -94,16 +95,22 @@ li:hover .app-navigation-entry-utils-counter { font-weight:700; border: 0; background-color: transparent; + float:left; } .stack h2 button, .stack .stack-actions{ float:right; } +.stack h2 span { + float: left; + margin-bottom:3px; +} .stack h2 .stack-actions { display: none; } .stack h2:hover .stack-actions { - display: block; + display: inline-block; + float:right; } .card { background-color:#fff; diff --git a/js/.jshintrc b/js/.jshintrc new file mode 100644 index 000000000..44b7643ee --- /dev/null +++ b/js/.jshintrc @@ -0,0 +1,49 @@ +{ + "globals": { + "jasmine" : false, + "spyOn" : false, + "it" : false, + "describe" : false, + "expect" : false, + "beforeEach" : false, + "waits" : false, + "waitsFor" : false, + "runs" : false, + "require" : false, + "module": true + }, + + "asi" : true, + "boss" : true, + "browser" : true, + "curly" : true, + "debug" : true, + "devel" : true, + "eqeqeq" : true, + "eqnull" : false, + "es5" : true, + "evil" : false, + "forin" : true, + "immed" : true, + "indent" : 4, + "jquery" : true, + "latedef" : true, + "laxbreak" : false, + "newcap" : true, + "noarg" : true, + "node" : false, + "noempty" : false, + "nomen" : false, + "nonew" : true, + "onevar" : true, + "plusplus" : false, + "quotmark" : "single", + "regexp" : false, + "strict" : true, + "sub" : true, + "trailing" : true, + "undef" : true, + "unused" : true, + "white" : false, + "scripturl" : true +} diff --git a/js/Gruntfile.js b/js/Gruntfile.js new file mode 100644 index 000000000..822242591 --- /dev/null +++ b/js/Gruntfile.js @@ -0,0 +1,130 @@ +/** + * ownCloud - Calendar App + * + * @author Raghu Nayyar + * @copyright 2014 Raghu Nayyar + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ + + +module.exports = function(grunt) { + 'use strict'; + + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-wrap'); + grunt.loadNpmTasks('grunt-ng-annotate'); + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-phpunit'); + + grunt.initConfig({ + + meta: { + pkg: grunt.file.readJSON('package.json'), + version: '<%= meta.pkg.version %>', + configJS: 'config/', + buildJS: [ + 'app/**/*.js', + 'controller/**/*.js', + 'directive/**/*.js', + 'service/**/*.js' + ], + productionJS: 'public/', + testsJS: '../tests/js/' + }, + + concat: { + options: { + stripBanners: true + }, + dist: { + src: ['<%= meta.buildJS %>'], + dest: '<%= meta.productionJS %>app.js' + } + }, + + wrap: { + app: { + src: ['<%= meta.productionJS %>app.js'], + dest: '<%= meta.productionJS %>app.js', + option: { + wrapper: [ + '(function(angular, $, oc_requesttoken, undefined){\n\n\'use strict\';\n\n', + '\n})(angular, jQuery, oc_requesttoken);' + ] + } + } + }, + + jshint: { + files: [ + 'Gruntfile.js', + '<%= meta.buildJS %>**/*.js', + '<%= meta.testsJS %>**/*.js' + ], + options: { + jshintrc: '.jshintrc', + reporter: require('jshint-stylish') + } + }, + + watch: { + concat: { + files: ['<%=meta.buildJS%>'], + options: { + livereload: true + }, + tasks: ['build'] + } + }, + + phpunit: { + classes: { + dir: '../tests/unit' + }, + options: { + bootstrap: '../tests/bootstrap.php', + colors: true + } + }, + + karma: { + unit: { + configFile: '<%= meta.testsJS %>config/karma.js' + }, + continuous: { + configFile: '<%= meta.testsJS %>config/karma.js', + browsers: ['Firefox'], + singleRun: true, + reporters: ['progress'] + } + }, + + ngAnnotate: { + app: { + src: ['<%= meta.productionJS %>app.js'], + dest: '<%= meta.productionJS %>app.js' + } + } + + }); + + // make tasks available under simpler commands + grunt.registerTask('build', ['jshint', 'concat', 'wrap', 'ngAnnotate']); + grunt.registerTask('js-unit', ['karma:continuous']); + +}; diff --git a/js/Makefile b/js/Makefile new file mode 100644 index 000000000..e12ae8f13 --- /dev/null +++ b/js/Makefile @@ -0,0 +1,6 @@ +default: + grunt build + +watch: + grunt watch + diff --git a/js/controller/BoardController.js b/js/controller/BoardController.js index 8488779f8..7768549d3 100644 --- a/js/controller/BoardController.js +++ b/js/controller/BoardController.js @@ -1,16 +1,40 @@ -app.controller('BoardController', function ($rootScope, $scope, $location, $http, $route, $stateParams, boardFactory, stackFactory, StackService) { +app.controller('BoardController', function ($rootScope, $scope, $location, $http, $route, $stateParams, BoardService, StackService) { + $scope.sidebar = $rootScope.sidebar; - $scope.newCard = {}; - $scope.stackservice = StackService; $scope.id = $stateParams.boardId; + $scope.stackservice = StackService; + $scope.boardservice = BoardService; + + // fetch data + StackService.clear(); + + StackService.fetchAll($scope.id).then(function(data) { + console.log($scope.stackservice.data) + $scope.releaseWaiting(); + }, function(error) { + $scope.setError('Error occured', error); + }); + + BoardService.fetchOne($scope.id).then(function(data) { + $scope.releaseWaiting(); + }, function(error) { + $scope.setError('Error occured', error); + }); + + $scope.newStack = { 'boardId': $scope.id}; + $scope.newCard = {}; + + + // Status Helper $scope.status = { 'active': true, 'icon': 'loading', 'title': 'Bitte warten', - 'text': 'Es dauert noch einen kleinen Moment' + 'text': 'Es dauert noch einen kleinen Moment', + 'counter': 2, }; $scope.setStatus = function($icon, $title, $text='') { @@ -20,45 +44,38 @@ app.controller('BoardController', function ($rootScope, $scope, $location, $http $scope.status.text = $text; } + $scope.setError = function($title, $text) { + $scope.status.active = true; + $scope.status.icon = 'error'; + $scope.status.title = $title; + $scope.status.text = $text; + $scope.status.counter = 0; + } + + $scope.releaseWaiting = function() { + if($scope.status.counter>0) + $scope.status.counter--; + if($scope.status.counter==0) { + $scope.status = { + 'active': false + } + } + } + $scope.unsetStatus = function() { $scope.status = { 'active': false } } - $scope.getBoard = function() { - boardFactory.getBoard($scope.id) - .then(function (response) { - $scope.board = response.data; - $scope.unsetStatus(); - }, function (error) { - $scope.setStatus('error','Unable to load board data', error); - }); - } - - $scope.getStacks = function() { - stackFactory.getStacks($scope.id) - .then(function (response) { - - $scope.stacks = response.data; - $scope.unsetStatus(); - }, function (error) { - $scope.setStatus('error','Unable to load board data', error); - }); - } - + // Create a new Stack $scope.createStack = function () { - $scope.newStack.boardId = $scope.id; - stackFactory.createStack($scope.newStack) - .then(function (response) { - $scope.stacks.push(response.data); - $scope.newStack = {}; - $scope.status.addStack=false; - }, function(error) { - $scope.status.createBoard = 'Unable to insert board: ' + error.message; - }); + StackService.create($scope.newStack).then(function (data) { + $scope.newStack.title=""; + }); }; + // Lighten Color of the board for background usage $scope.rgblight = function (hex) { var result = /^([A-Fa-f\d]{2})([A-Fa-f\d]{2})([A-Fa-f\d]{2})$/i.exec(hex); var color = result ? { @@ -107,40 +124,4 @@ app.controller('BoardController', function ($rootScope, $scope, $location, $http } }; - $scope.sortStackOptions = { - itemMoved: function (event) { - event.source.itemScope.modelValue.status = event.dest.sortableScope.$parent.column; - console.log(event.dest.sortableScope.$parent); - }, - orderChanged: function (event) { - }, - scrollableContainer: '#board', - containerPositioning: 'relative', - containment: '#board', - // auto scroll on drag - dragMove: function (itemPosition, containment, eventObj) { - if (eventObj) { - var container = $("#board"); - var offset = container.offset(); - targetX = eventObj.pageX - (offset.left || container.scrollLeft()); - targetY = eventObj.pageY - (offset.top || container.scrollTop()); - if (targetX < offset.left) { - container.scrollLeft(container.scrollLeft() - 50); - } else if (targetX > container.width()) { - container.scrollLeft(container.scrollLeft() + 50); - } - if (targetY < offset.top) { - container.scrollTop(container.scrollTop() - 50); - } else if (targetY > container.height()) { - container.scrollTop(container.scrollTop() + 50); - } - } - } - }; - - - $scope.getBoard(); - $scope.getStacks(); - - }); diff --git a/js/controller/ListController.js b/js/controller/ListController.js index c75220924..5b7fe7bf7 100644 --- a/js/controller/ListController.js +++ b/js/controller/ListController.js @@ -1,10 +1,17 @@ -app.controller('ListController', function ($scope, $location, boardFactory, StackService) { +app.controller('ListController', function ($scope, $location, boardFactory, BoardService) { $scope.boards = null; $scope.newBoard = {}; $scope.status = {}; $scope.colors = ['31CC7C', '317CCC', 'FF7A66', 'F1DB50', '7C31CC', 'CC317C', '3A3B3D', 'CACBCD']; - $scope.stackservice = StackService; + + $scope.boardservice = BoardService; + BoardService.fetchAll().then(function(data) { + console.log($scope.boardservice); + console.log(data); + }, function(error) { + //$scope.setStatus('error','Error occured', error); + }); $scope.getBoards = function() { boardFactory.getBoards() diff --git a/js/gulpfile.js b/js/gulpfile.js new file mode 100644 index 000000000..9dece784b --- /dev/null +++ b/js/gulpfile.js @@ -0,0 +1,88 @@ +/** + * ownCloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2012, 2014 + */ + +/*jslint node: true */ +'use strict'; + +const gulp = require('gulp'), + ngAnnotate = require('gulp-ng-annotate'), + uglify = require('gulp-uglify'), + jshint = require('gulp-jshint'), + KarmaServer = require('karma').Server, + phpunit = require('gulp-phpunit'), + concat = require('gulp-concat'), + sourcemaps = require('gulp-sourcemaps'); + +// Configuration +const buildTarget = 'app.min.js'; +const phpunitConfig = __dirname + '/../phpunit.xml'; +const karmaConfig = __dirname + '/karma.conf.js'; +const destinationFolder = __dirname + '/build/'; +const sources = [ + 'app/App.js', 'app/Config.js', 'app/Run.js', + 'controller/**/*.js', + 'filter/**/*.js', + 'service/**/*.js', + 'gui/**/*.js', + 'plugin/**/*.js', + 'utility/**/*.js', + 'directive/**/*.js' +]; +const testSources = ['tests/**/*.js']; +const phpSources = ['../**/*.php', '!../js/**', '!../vendor/**']; +const watchSources = sources.concat(testSources).concat(['*.js']); +const lintSources = watchSources; + +// tasks +gulp.task('default', ['lint'], () => { + return gulp.src(sources) + .pipe(ngAnnotate()) + .pipe(sourcemaps.init()) + .pipe(concat(buildTarget)) + .pipe(uglify()) + .pipe(sourcemaps.write()) + .pipe(gulp.dest(destinationFolder)); +}); + +gulp.task('lint', () => { + return gulp.src(lintSources) + .pipe(jshint()) + .pipe(jshint.reporter('default')) + .pipe(jshint.reporter('fail')); +}); + +gulp.task('watch', () => { + gulp.watch(watchSources, ['default']); +}); + +gulp.task('karma', (done) => { + new KarmaServer({ + configFile: karmaConfig, + singleRun: true + }, done).start(); +}); + +gulp.task('watch-karma', (done) => { + new KarmaServer({ + configFile: karmaConfig, + autoWatch: true + }, done).start(); +}); + +gulp.task('phpunit', () => { + return gulp.src(phpSources) + .pipe(phpunit('phpunit', { + configurationFile: phpunitConfig + })); +}); + +gulp.task('watch-phpunit', () => { + gulp.watch(phpSources, ['phpunit']); +}); diff --git a/js/package.json b/js/package.json new file mode 100644 index 000000000..e3d858e10 --- /dev/null +++ b/js/package.json @@ -0,0 +1,34 @@ +{ + "name": "deck", + "description": "Deck owncloud app", + "version": "0.1.0", + "private": true, + "homepage": "https://github.com/juliushaertl/deck", + "repository": { + "type": "git", + "url": "git@github.com:juliushaertl/deck.git" + }, + "dependencies": {}, + "devDependencies": { + "bower": "*", + "grunt": "*", + "grunt-cli": "*", + "grunt-contrib-concat": "*", + "grunt-contrib-jshint": "*", + "grunt-contrib-watch": "*", + "grunt-karma": "*", + "grunt-ng-annotate": "^1.0.1", + "grunt-phpunit": "*", + "grunt-wrap": "*", + "jasmine-core": "*", + "jshint-stylish": "^2.1.0", + "karma": "*", + "karma-chrome-launcher": "*", + "karma-coverage": "*", + "karma-firefox-launcher": "*", + "karma-jasmine": "*", + "karma-phantomjs-launcher": "*", + "phantomjs": "*" + }, + "engine": "node >= 0.8" +} diff --git a/js/public/app.js b/js/public/app.js new file mode 100644 index 000000000..4c48bddc5 --- /dev/null +++ b/js/public/app.js @@ -0,0 +1,496 @@ + +var app = angular.module('Deck', ['ngRoute', 'ngSanitize', 'ui.router', 'as.sortable']); + +app.config(function ($provide, $routeProvider, $interpolateProvider, $httpProvider, $urlRouterProvider, $stateProvider) { + 'use strict'; + $httpProvider.defaults.headers.common.requesttoken = oc_requesttoken; + + $urlRouterProvider.otherwise("/"); + + $stateProvider + .state('list', { + url: "/", + templateUrl: "/boardlist.mainView.html", + controller: 'ListController', + }) + .state('board', { + url: "/board/:boardId", + templateUrl: "/board.html", + controller: 'BoardController' + }) + .state('board.card', { + url: "/card/:cardId", + views: { + "sidebarView": { + templateUrl: "/card.sidebarView.html", + controller: 'CardController' + } + } + }) + .state('board.settings', {}) + .state('board.sharing', {}); +}); + +// OwnCloud Click Handling +// https://doc.owncloud.org/server/8.0/developer_manual/app/css.html +app.directive('appNavigationEntryUtils', function () { + 'use strict'; + return { + restrict: 'C', + link: function (scope, elm) { + + var menu = elm.siblings('.app-navigation-entry-menu'); + var button = $(elm) + .find('.app-navigation-entry-utils-menu-button button'); + + button.click(function () { + menu.toggleClass('open'); + }); + scope.$on('documentClicked', function (scope, event) { + if (event.target !== button[0]) { + menu.removeClass('open'); + } + }); + } + }; +}); + +app.directive('autofocusOnInsert', function () { + 'use strict'; + return function (scope, elm) { + elm.focus(); + }; +}); + +app.run(function ($document, $rootScope, $transitions) { + 'use strict'; + $document.click(function (event) { + $rootScope.$broadcast('documentClicked', event); + }); + $transitions.onEnter({to: 'board.card'}, function ($state, $transition$) { + $rootScope.sidebar.show = true; + }); + $transitions.onEnter({to: 'board'}, function ($state) { + $rootScope.sidebar.show = false; + }); + $transitions.onExit({from: 'board.card'}, function ($state) { + $rootScope.sidebar.show = false; + }); +}); + +app.controller('AppController', function ($scope, $location, $http, $route, $log, $rootScope, $stateParams) { + $rootScope.sidebar = { + show: false + }; + $scope.sidebar = $rootScope.sidebar; +}); + +app.controller('BoardController', function ($rootScope, $scope, $location, $http, $route, $stateParams, BoardService, StackService) { + + + $scope.sidebar = $rootScope.sidebar; + $scope.id = $stateParams.boardId; + + $scope.stackservice = StackService; + $scope.boardservice = BoardService; + + // fetch data + StackService.clear(); + + StackService.fetchAll($scope.id).then(function(data) { + console.log($scope.stackservice.data) + $scope.releaseWaiting(); + }, function(error) { + $scope.setError('Error occured', error); + }); + + BoardService.fetchOne($scope.id).then(function(data) { + $scope.releaseWaiting(); + }, function(error) { + $scope.setError('Error occured', error); + }); + + $scope.newStack = { 'boardId': $scope.id}; + $scope.newCard = {}; + + + // Status Helper + $scope.status = { + 'active': true, + 'icon': 'loading', + 'title': 'Bitte warten', + 'text': 'Es dauert noch einen kleinen Moment', + 'counter': 2, + }; + + $scope.setStatus = function($icon, $title, $text='') { + $scope.status.active = true; + $scope.status.icon = $icon; + $scope.status.title = $title; + $scope.status.text = $text; + } + + $scope.setError = function($title, $text) { + $scope.status.active = true; + $scope.status.icon = 'error'; + $scope.status.title = $title; + $scope.status.text = $text; + $scope.status.counter = 0; + } + + $scope.releaseWaiting = function() { + if($scope.status.counter>0) + $scope.status.counter--; + if($scope.status.counter==0) { + $scope.status = { + 'active': false + } + } + } + + $scope.unsetStatus = function() { + $scope.status = { + 'active': false + } + } + + // Create a new Stack + $scope.createStack = function () { + StackService.create($scope.newStack).then(function (data) { + $scope.newStack.title=""; + }); + }; + + // Lighten Color of the board for background usage + $scope.rgblight = function (hex) { + var result = /^([A-Fa-f\d]{2})([A-Fa-f\d]{2})([A-Fa-f\d]{2})$/i.exec(hex); + var color = result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; + if(result !== null) { + var rgba = "rgba(" + color.r + "," + color.g + "," + color.b + ",0.7)"; + return rgba; + } else { + return "#"+hex; + } + }; + + + // settings for card sorting + $scope.sortOptions = { + itemMoved: function (event) { + event.source.itemScope.modelValue.status = event.dest.sortableScope.$parent.column; + console.log(event.dest.sortableScope.$parent); + }, + orderChanged: function (event) { + }, + scrollableContainer: '#board', + containerPositioning: 'relative', + containment: '#board', + // auto scroll on drag + dragMove: function (itemPosition, containment, eventObj) { + if (eventObj) { + var container = $("#board"); + var offset = container.offset(); + targetX = eventObj.pageX - (offset.left || container.scrollLeft()); + targetY = eventObj.pageY - (offset.top || container.scrollTop()); + if (targetX < offset.left) { + container.scrollLeft(container.scrollLeft() - 50); + } else if (targetX > container.width()) { + container.scrollLeft(container.scrollLeft() + 50); + } + if (targetY < offset.top) { + container.scrollTop(container.scrollTop() - 50); + } else if (targetY > container.height()) { + container.scrollTop(container.scrollTop() + 50); + } + } + } + }; + +}); + + + +app.controller('CardController', function ($scope, $rootScope, $routeParams, $location, $stateParams) { + $scope.sidebar = $rootScope.sidebar; + + $scope.location = $location; + $scope.card = {'id': 1, 'title': 'We should implement all the useful things, that a kanban like project managemnt system needs for having success', 'description': 'Non et quibusdam officiis expedita excepturi. Tenetur ea et dignissimos qui. Rerum quis commodi aperiam amet dolorum suscipit asperiores. Enim dolorem ea nisi voluptate. \ + Consequatur enim iste dolore autem est unde voluptatum. Aut sit et iure. Suscipit deserunt nisi repellat in officiis alias. Nihil beatae ea ut laudantium at.\ + Doloribus nihil ipsa consequatur laudantium qui enim eveniet quo. Voluptatum tenetur sunt quis sint aliquam et molestias. Quae voluptatem tempora qui eaque qui esse possimus magni. Animi dolorem maiores iste.\ + Totam ut tempora officiis ipsam dolorem modi. Dolores hic aut itaque. Earum in est voluptas voluptatum. Cumque pariatur qui omnis placeat. Eius sed sunt corrupti dolorem quo.'}; + $scope.cardId = $stateParams.cardId; + + console.log($stateParams); + + + + /*var menu = $('#app-content'); + menu.click(function(event){ + $scope.location.path('/board/'+$scope.boardId); + $scope.$apply(); + + });*/ +}); + + +app.controller('ListController', function ($scope, $location, boardFactory, BoardService) { + $scope.boards = null; + $scope.newBoard = {}; + $scope.status = {}; + $scope.colors = ['31CC7C', '317CCC', 'FF7A66', 'F1DB50', '7C31CC', 'CC317C', '3A3B3D', 'CACBCD']; + + $scope.boardservice = BoardService; + BoardService.fetchAll().then(function(data) { + console.log($scope.boardservice); + console.log(data); + }, function(error) { + //$scope.setStatus('error','Error occured', error); + }); + + $scope.getBoards = function() { + boardFactory.getBoards() + .then(function (response) { + $scope.boards = response.data; + for (var i = 0; i < $scope.boards.length; i++) { + $scope.boards[i].status = { + 'edit': false, + } + } + }, function (error) { + $scope.status.getBoards = 'Unable to load customer data: ' + error.message; + }); + } + + $scope.createBoard = function () { + boardFactory.createBoard($scope.newBoard) + .then(function (response) { + $scope.boards.push(response.data); + $scope.newBoard = {}; + $scope.status.addBoard=false; + }, function(error) { + $scope.status.createBoard = 'Unable to insert board: ' + error.message; + }); + }; + + $scope.updateBoard = function(board) { + boardFactory.updateBoard(board) + .then(function (response) { + board = response.data; + }, function(error) { + $scope.status.createBoard = 'Unable to insert board: ' + error.message; + }); + board.status.edit = false; + $scope.$apply(); + }; + + $scope.selectColor = function(color) { + $scope.newBoard.color = color; + }; + + $scope.deleteBoard = function (index) { + var board = $scope.boards[index]; + boardFactory.deleteBoard(board.id) + .then(function (response) { + $scope.status.deleteBoard = 'Deleted Board'; + $scope.boards.splice( index, 1 ); + + }, function(error) { + $scope.status.deleteBoard = 'Unable to insert board: ' + error.message; + }); + }; + $scope.getBoards(); + + +}); + + +app.factory('ApiService', function($http, $q){ + var ApiService = function(http, endpoint) { + this.endpoint = endpoint; + this.baseUrl = OC.generateUrl('/apps/deck/' + endpoint); + this.http = http; + this.q = $q; + this.data = {}; + this.id = null; + }; + + // TODO: Unify error messages + ApiService.prototype.fetchAll = function(){ + var deferred = $q.defer(); + var self = this; + $http.get(this.baseUrl).then(function (response) { + var objects = response.data; + objects.forEach(function (obj) { + self.data[obj.id] = obj; + }); + deferred.resolve(self.data); + }, function (error) { + deferred.reject('Error while ' + self.getName() + '.fetchAll() '); + + }); + return deferred.promise; + } + + ApiService.prototype.fetchOne = function (id) { + this.id = id; + var deferred = $q.defer(); + var self = this; + $http.get(this.baseUrl + '/' + id).then(function (response) { + data = response.data; + self.data[data.id] = response.data; + deferred.resolve(response.data); + + }, function (error) { + deferred.reject('Error in ' + self.endpoint + ' fetchAll() '); + }); + return deferred.promise; + }; + + ApiService.prototype.create = function (entity) { + var deferred = $q.defer(); + var self = this; + $http.post(this.baseUrl, entity).then(function (response) { + self.add(response.data); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error in ' + self.endpoint + ' create() '); + }); + return deferred.promise; + }; + + ApiService.prototype.update = function (entity) { + var deferred = $q.defer(); + var self = this; + $http.put(this.baseUrl, entity).then(function (response) { + self.add(response.data); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error while update ' + self.endpoint); + }); + return deferred.promise; + + }; + + ApiService.prototype.delete = function (id) { + var deferred = $q.defer(); + var self = this; + + $http.delete(this.baseUrl + '/' + id).then(function (response) { + self.remove(id); + deferred.resolve(response.data); + + }, function (error) { + deferred.reject('Error while delete ' + self.endpoint); + }); + return deferred.promise; + + }; + + // methods for managing data + ApiService.prototype.clear = function() { + this.data = {}; + } + ApiService.prototype.add = function (entity) { + var element = this.data[entity.id]; + if(element===undefined) { + this.data[entity.id] = entity; + } else { + Object.keys(entity).forEach(function (key) { + element[key] = entity[key]; + element[key].status = {}; + }); + } + }; + ApiService.prototype.remove = function(id) { + if (this.data[id] !== undefined) { + delete this.data[id]; + } + }; + ApiService.prototype.addAll = function (entities) { + var self = this; + angular.forEach(entities, function(entity) { + self.add(entity); + }); + }; + + ApiService.prototype.getCurrent = function () { + return this.data[this.id]; + } + + ApiService.prototype.getAll = function () { + return this.data; + } + + ApiService.prototype.getName = function() { + var funcNameRegex = /function (.{1,})\(/; + var results = (funcNameRegex).exec((this).constructor.toString()); + return (results && results.length > 1) ? results[1] : ""; + }; + + return ApiService; + +}); + +app.factory('boardFactory', function($http){ + var service = {}; + var baseUrl = OC.generateUrl('/apps/deck/boards'); + + service.getBoards = function(){ + return $http.get(baseUrl); + } + + service.getBoard = function (id) { + board = $http.get(baseUrl + '/' + id); + return board; + }; + + service.createBoard = function (board) { + + return $http.post(baseUrl, board); + }; + + service.updateBoard = function (board) { + return $http.put(baseUrl, board) + }; + + service.deleteBoard = function (id) { + return $http.delete(baseUrl + '/' + id); + }; + + return service; +}); + +app.factory('BoardService', function(ApiService, $http, $q){ + var BoardService = function($http, ep, $q) { + ApiService.call(this, $http, ep, $q); + }; + BoardService.prototype = angular.copy(ApiService.prototype); + service = new BoardService($http, 'boards', $q) + return service; +}); +app.factory('StackService', function(ApiService, $http, $q){ + var StackService = function($http, ep, $q) { + ApiService.call(this, $http, ep, $q); + }; + StackService.prototype = angular.copy(ApiService.prototype); + StackService.prototype.fetchAll = function(boardId) { + var deferred = $q.defer(); + var self=this; + $http.get(this.baseUrl +'/'+boardId).then(function (response) { + self.addAll(response.data); + deferred.resolve(self.data); + }, function (error) { + deferred.reject('Error while loading stacks'); + }); + return deferred.promise; + + } + service = new StackService($http, 'stacks', $q) + return service; +}); + + diff --git a/js/service/apiservice.js b/js/service/apiservice.js index 10259c1f4..2c173ab3f 100644 --- a/js/service/apiservice.js +++ b/js/service/apiservice.js @@ -1,31 +1,126 @@ -app.factory('ApiService', function($http){ - var ApiService = function(http, BASEURL,endpoint) { +app.factory('ApiService', function($http, $q){ + var ApiService = function(http, endpoint) { this.endpoint = endpoint; this.baseUrl = OC.generateUrl('/apps/deck/' + endpoint); this.http = http; - this.hashMap = {}; - this.values = []; + this.q = $q; + this.data = {}; + this.id = null; }; - ApiService.prototype.getAll = function(){ - return $http.get(baseUrl); + // TODO: Unify error messages + ApiService.prototype.fetchAll = function(){ + var deferred = $q.defer(); + var self = this; + $http.get(this.baseUrl).then(function (response) { + var objects = response.data; + objects.forEach(function (obj) { + self.data[obj.id] = obj; + }); + deferred.resolve(self.data); + }, function (error) { + deferred.reject('Error while ' + self.getName() + '.fetchAll() '); + + }); + return deferred.promise; } - ApiService.prototype.getOne = function (id) { - return $http.get(baseUrl + '/' + id); + ApiService.prototype.fetchOne = function (id) { + this.id = id; + var deferred = $q.defer(); + var self = this; + $http.get(this.baseUrl + '/' + id).then(function (response) { + data = response.data; + self.data[data.id] = response.data; + deferred.resolve(response.data); + + }, function (error) { + deferred.reject('Error in ' + self.endpoint + ' fetchAll() '); + }); + return deferred.promise; }; ApiService.prototype.create = function (entity) { - return $http.post(baseUrl, entity); + var deferred = $q.defer(); + var self = this; + $http.post(this.baseUrl, entity).then(function (response) { + self.add(response.data); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error in ' + self.endpoint + ' create() '); + }); + return deferred.promise; }; ApiService.prototype.update = function (entity) { - return $http.put(baseUrl, entity) + var deferred = $q.defer(); + var self = this; + $http.put(this.baseUrl, entity).then(function (response) { + self.add(response.data); + deferred.resolve(response.data); + }, function (error) { + deferred.reject('Error while update ' + self.endpoint); + }); + return deferred.promise; + }; ApiService.prototype.delete = function (id) { - return $http.delete(baseUrl + '/' + id); + var deferred = $q.defer(); + var self = this; + + $http.delete(this.baseUrl + '/' + id).then(function (response) { + self.remove(id); + deferred.resolve(response.data); + + }, function (error) { + deferred.reject('Error while delete ' + self.endpoint); + }); + return deferred.promise; + + }; + + // methods for managing data + ApiService.prototype.clear = function() { + this.data = {}; + } + ApiService.prototype.add = function (entity) { + var element = this.data[entity.id]; + if(element===undefined) { + this.data[entity.id] = entity; + } else { + Object.keys(entity).forEach(function (key) { + element[key] = entity[key]; + element[key].status = {}; + }); + } + }; + ApiService.prototype.remove = function(id) { + if (this.data[id] !== undefined) { + delete this.data[id]; + } + }; + ApiService.prototype.addAll = function (entities) { + var self = this; + angular.forEach(entities, function(entity) { + self.add(entity); + }); + }; + + ApiService.prototype.getCurrent = function () { + return this.data[this.id]; + } + + ApiService.prototype.getAll = function () { + return this.data; + } + + ApiService.prototype.getName = function() { + var funcNameRegex = /function (.{1,})\(/; + var results = (funcNameRegex).exec((this).constructor.toString()); + return (results && results.length > 1) ? results[1] : ""; }; return ApiService; -}); \ No newline at end of file + +}); diff --git a/js/service/factory.board.js b/js/service/factory.board.js index bc1a149be..13b00e279 100644 --- a/js/service/factory.board.js +++ b/js/service/factory.board.js @@ -1,4 +1,4 @@ -app.factory('boardFactory', function($http, stackFactory){ +app.factory('boardFactory', function($http){ var service = {}; var baseUrl = OC.generateUrl('/apps/deck/boards'); @@ -12,6 +12,7 @@ app.factory('boardFactory', function($http, stackFactory){ }; service.createBoard = function (board) { + return $http.post(baseUrl, board); }; @@ -23,5 +24,14 @@ app.factory('boardFactory', function($http, stackFactory){ return $http.delete(baseUrl + '/' + id); }; + return service; +}); + +app.factory('BoardService', function(ApiService, $http, $q){ + var BoardService = function($http, ep, $q) { + ApiService.call(this, $http, ep, $q); + }; + BoardService.prototype = angular.copy(ApiService.prototype); + service = new BoardService($http, 'boards', $q) return service; }); \ No newline at end of file diff --git a/js/service/factory.stack.js b/js/service/factory.stack.js index ad7ef5d26..424dc7939 100644 --- a/js/service/factory.stack.js +++ b/js/service/factory.stack.js @@ -1,78 +1,21 @@ -app.factory('ApiService', function($http){ - var ApiService = function(http, endpoint) { - this.endpoint = endpoint; - this.baseUrl = OC.generateUrl('/apps/deck/' + endpoint); - this.http = http; - this.hashMap = {}; - this.values = []; - this.once = null; +app.factory('StackService', function(ApiService, $http, $q){ + var StackService = function($http, ep, $q) { + ApiService.call(this, $http, ep, $q); }; - - ApiService.prototype.getAll = function(){ - return $http.get(this.baseUrl); - } - - ApiService.prototype.getOne = function (id) { - self = this; - $http.get(this.baseUrl + '/' + id).then(function (response) { - self.once = response.data; - return response.data; + StackService.prototype = angular.copy(ApiService.prototype); + StackService.prototype.fetchAll = function(boardId) { + var deferred = $q.defer(); + var self=this; + $http.get(this.baseUrl +'/'+boardId).then(function (response) { + self.addAll(response.data); + deferred.resolve(self.data); }, function (error) { + deferred.reject('Error while loading stacks'); }); - return this.once; + return deferred.promise; - }; - - ApiService.prototype.create = function (entity) { - return $http.post(this.baseUrl, entity); - }; - - ApiService.prototype.update = function (entity) { - return $http.put(this.baseUrl, entity) - }; - - ApiService.prototype.delete = function (id) { - return $http.delete(this.baseUrl + '/' + id); - }; - - return ApiService; -}); - -app.factory('stackFactory', function($http){ - var service = {}; - var baseUrl = OC.generateUrl('/apps/deck/stacks'); - - service.getStacks = function(boardId){ - return $http.get(baseUrl + '/' + boardId); } - - service.getStack = function (id) { - return $http.get(baseUrl + '/' + id); - }; - - service.createStack = function (stack) { - return $http.post(baseUrl, stack); - }; - - service.updateStack = function (stack) { - return $http.put(baseUrl, stack) - }; - - service.deleteStack = function (id) { - return $http.delete(baseUrl + '/' + id); - }; - + service = new StackService($http, 'stacks', $q) return service; }); -app.factory('StackService', function(ApiService, $http){ - var StackService = function($http, ep) { - ApiService.call(this, $http, ep); - }; - StackService.prototype = ApiService.prototype; - StackService.prototype.getAll = function(boardId) { - return $http.get(this.baseUrl + '/' + boardId); - } - service = new StackService($http, 'stacks') - return service; -}); \ No newline at end of file diff --git a/service/stackservice.php b/service/stackservice.php index 99bf40305..ea54f6564 100644 --- a/service/stackservice.php +++ b/service/stackservice.php @@ -39,11 +39,11 @@ class StackService { } public function delete($userId, $id) { - return $this->stackMapper->delete($this->find($userId, $id)); + return $this->stackMapper->delete($this->stackMapper->find($id)); } public function update($id, $title, $boardId, $order) { - $stack = $this->find($id); + $stack = $this->stackMapper->find($id); $stack->setTitle($title); $stack->setBoardId($boardId); $stack->setOrder($order); diff --git a/templates/main.php b/templates/main.php index 71cd00e6a..71cdc31d5 100644 --- a/templates/main.php +++ b/templates/main.php @@ -12,15 +12,7 @@ Util::addScript('deck', 'vendor/angular-sanitize/angular-sanitize.min'); Util::addScript('deck', 'vendor/angular-animate/angular-animate.min'); Util::addScript('deck', 'vendor/angular-ui-router/release/angular-ui-router.min'); Util::addScript('deck', 'vendor/ng-sortable/dist/ng-sortable.min'); -Util::addScript('deck', 'app/App'); -Util::addScript('deck', 'controller/AppController'); -Util::addScript('deck', 'controller/CardController'); -Util::addScript('deck', 'controller/BoardController'); -Util::addScript('deck', 'controller/ListController'); -Util::addScript('deck', 'service/factory.board'); -Util::addScript('deck', 'service/factory.stack'); - - +Util::addScript('deck', 'public/app'); ?> diff --git a/templates/part.board.mainView.php b/templates/part.board.mainView.php index d38e49e93..e99929719 100644 --- a/templates/part.board.mainView.php +++ b/templates/part.board.mainView.php @@ -4,8 +4,8 @@

{{ status.title }}

{{ status.text }}

-
-

{{ board.title }} {{ stackservice.once }} +
+

{{ boardservice.data[id].title }}

@@ -15,11 +15,15 @@
*/ ?>
-
-

{{ s.title }} +
+

{{ s.title }} +
+ + +
- - + +

    @@ -41,15 +45,15 @@
-
-

- +
+

+

- +

diff --git a/templates/part.navigation.php b/templates/part.navigation.php index 24f16715d..d57b77286 100644 --- a/templates/part.navigation.php +++ b/templates/part.navigation.php @@ -1,11 +1,9 @@