From a4c3d96ee4d4831b35455a976fc3bfe9cf486fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raimund=20Schl=C3=BC=C3=9Fler?= Date: Sun, 19 Aug 2018 22:18:53 +0200 Subject: [PATCH] Remove angular, add vue --- .babelrc | 14 + .editorconfig | 2 +- .jshintrc | 4 +- Makefile | 227 ++----- gulpfile.js | 89 +-- js/app/app.js | 202 ++---- .../TheRouter.js} | 36 +- js/app/controllers/appcontroller.js | 83 --- js/app/controllers/detailscontroller.js | 397 ------------ js/app/controllers/settingscontroller.js | 90 --- js/app/controllers/taskscontroller.js | 456 ------------- js/app/directives/appnavigationentryutils.js | 40 -- js/app/directives/autofocusoninsert.js | 27 - js/app/directives/avatar.js | 35 - js/app/directives/colorpickerDirective.js | 167 ----- js/app/directives/datepicker.js | 56 -- js/app/directives/occlickfocus.js | 41 -- js/app/directives/timepicker.js | 39 -- js/app/filters/counterFormatter.js | 34 - js/app/filters/dateDetails.js | 31 - js/app/filters/dateDetailsShort.js | 31 - js/app/filters/dateFromNow.js | 31 - js/app/filters/dateTaskList.js | 31 - js/app/filters/dayTaskList.js | 31 - js/app/filters/percentDetails.js | 27 - js/app/filters/reminderDetails.js | 82 --- js/app/filters/startDetails.js | 31 - js/app/filters/timeTaskList.js | 31 - js/app/{services/icalfactory.js => init.js} | 41 +- .../businesslayer/listsbusinesslayer.js | 71 --- .../businesslayer/settingsbusinesslayer.js | 56 -- .../businesslayer/tasksbusinesslayer.js | 599 ------------------ js/app/services/calendarservice.js | 461 -------------- js/app/services/davclient.js | 57 -- js/app/services/loading.js | 51 -- js/app/services/model.js | 138 ---- js/app/services/models/calendar.js | 289 --------- js/app/services/models/collectionsmodel.js | 91 --- js/app/services/models/listsmodel.js | 194 ------ js/app/services/models/settingsmodel.js | 81 --- js/app/services/models/vtodo.js | 307 --------- js/app/services/persistence.js | 131 ---- js/app/services/publisher.js | 56 -- js/app/services/randomstringservice.js | 32 - js/app/services/request.js | 147 ----- js/app/services/status.js | 43 -- js/app/services/vtodoservice.js | 212 ------- js/app/{filters/day.js => store.js} | 20 +- js/merged.json | 11 +- package.json | 75 ++- test/OC.js | 9 + test/setup.js | 3 + webpack.common.js | 57 ++ webpack.prod.js | 16 + 54 files changed, 347 insertions(+), 5266 deletions(-) create mode 100644 .babelrc rename js/app/{filters/priorityDetails.js => components/TheRouter.js} (54%) delete mode 100644 js/app/controllers/appcontroller.js delete mode 100644 js/app/controllers/detailscontroller.js delete mode 100644 js/app/controllers/settingscontroller.js delete mode 100644 js/app/controllers/taskscontroller.js delete mode 100644 js/app/directives/appnavigationentryutils.js delete mode 100644 js/app/directives/autofocusoninsert.js delete mode 100644 js/app/directives/avatar.js delete mode 100644 js/app/directives/colorpickerDirective.js delete mode 100644 js/app/directives/datepicker.js delete mode 100644 js/app/directives/occlickfocus.js delete mode 100644 js/app/directives/timepicker.js delete mode 100644 js/app/filters/counterFormatter.js delete mode 100644 js/app/filters/dateDetails.js delete mode 100644 js/app/filters/dateDetailsShort.js delete mode 100644 js/app/filters/dateFromNow.js delete mode 100644 js/app/filters/dateTaskList.js delete mode 100644 js/app/filters/dayTaskList.js delete mode 100644 js/app/filters/percentDetails.js delete mode 100644 js/app/filters/reminderDetails.js delete mode 100644 js/app/filters/startDetails.js delete mode 100644 js/app/filters/timeTaskList.js rename js/app/{services/icalfactory.js => init.js} (59%) delete mode 100644 js/app/services/businesslayer/listsbusinesslayer.js delete mode 100644 js/app/services/businesslayer/settingsbusinesslayer.js delete mode 100644 js/app/services/businesslayer/tasksbusinesslayer.js delete mode 100644 js/app/services/calendarservice.js delete mode 100644 js/app/services/davclient.js delete mode 100644 js/app/services/loading.js delete mode 100644 js/app/services/model.js delete mode 100644 js/app/services/models/calendar.js delete mode 100644 js/app/services/models/collectionsmodel.js delete mode 100644 js/app/services/models/listsmodel.js delete mode 100644 js/app/services/models/settingsmodel.js delete mode 100644 js/app/services/models/vtodo.js delete mode 100644 js/app/services/persistence.js delete mode 100644 js/app/services/publisher.js delete mode 100644 js/app/services/randomstringservice.js delete mode 100644 js/app/services/request.js delete mode 100644 js/app/services/status.js delete mode 100644 js/app/services/vtodoservice.js rename js/app/{filters/day.js => store.js} (76%) create mode 100644 test/OC.js create mode 100644 test/setup.js create mode 100644 webpack.common.js create mode 100644 webpack.prod.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..55021bc9 --- /dev/null +++ b/.babelrc @@ -0,0 +1,14 @@ +{ + "env": { + "development": { + "presets": [ + ["env", { "modules": false }] + ] + }, + "test": { + "presets": [ + ["env", { "targets": { "node": "current" }}] + ] + } + } +} diff --git a/.editorconfig b/.editorconfig index 1c47fb6e..039d0cec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ end_of_line = lf insert_final_newline = true # Set default charset and indentation -[*.{php,js}] +[*.{php,js,scss,vue}] charset = utf-8 indent_style = tab tab_width = 4 diff --git a/.jshintrc b/.jshintrc index b11d2c0a..4feb28e8 100644 --- a/.jshintrc +++ b/.jshintrc @@ -40,6 +40,8 @@ "escapeHTML": true, "possible": true, "dav": true, - "OCA": true + "OCA": true, + "Vue": true, + "VueRouter": true } } diff --git a/Makefile b/Makefile index b103f460..0f9e14ed 100644 --- a/Makefile +++ b/Makefile @@ -17,10 +17,6 @@ # * tar: for building the archive # * npm: for building and testing everything JS # -# If no composer.json is in the app root directory, the Composer step -# will be skipped. The same goes for the package.json which can be located in -# the app root or the js/ directory. -# # The npm command by launches the npm build script: # # npm run build @@ -29,26 +25,10 @@ # # npm run test # -# The idea behind this is to be completely testing and build tool agnostic. All -# build tools and additional package managers should be installed locally in -# your project, since this won't pollute people's global namespace. -# -# The following npm scripts in your package.json install and update the -# npm dependencies and use gulp as build system (notice how everything is -# run from the node_modules folder): -# -# "scripts": { -# "test": "node node_modules/gulp-cli/bin/gulp.js karma", -# "prebuild": "npm install && npm upgrade", -# "build": "node node_modules/gulp-cli/bin/gulp.js" -# }, app_name=$(notdir $(CURDIR)) -build_tools_directory=$(CURDIR)/build/tools -source_build_directory=$(CURDIR)/build/source/tasks -source_artifact_directory=$(CURDIR)/build/artifacts/source -source_package_name=$(source_artifact_directory)/$(app_name) -appstore_build_directory=$(CURDIR)/build/appstore/tasks +build_directory=$(CURDIR)/build +appstore_build_directory=$(CURDIR)/build/appstore/$(app_name) appstore_artifact_directory=$(CURDIR)/build/artifacts/appstore appstore_package_name=$(appstore_artifact_directory)/$(app_name) npm=$(shell which npm 2> /dev/null) @@ -71,12 +51,12 @@ private_key=$(HOME)/.nextcloud/$(app_name).key certificate=$(HOME)/.nextcloud/$(app_name).crt sign=php -f $(occ) integrity:sign-app --privateKey="$(private_key)" --certificate="$(certificate)" sign_skip_msg="Skipping signing, either no key and certificate found in $(private_key) and $(certificate) or occ can not be found at $(occ)" -ifneq (,$(wildcard $(private_key))) -ifneq (,$(wildcard $(certificate))) -ifneq (,$(wildcard $(occ))) - CAN_SIGN=true -endif -endif +ifneq ("$(wildcard $(private_key))","") #(,$(wildcard $(private_key))) + ifneq ("$(wildcard $(certificate))","")#(,$(wildcard $(certificate))) + ifneq ("$(wildcard $(occ))","")#(,$(wildcard $(occ))) + CAN_SIGN=true + endif + endif endif all: build @@ -86,160 +66,67 @@ all: build # is present, the npm step is skipped .PHONY: build build: - make npm - -# Installs npm dependencies -.PHONY: npm -npm: $(npm) run build -# Removes the appstore build +# Sets up the development environment +.PHONY: development +development: + $(npm) install + $(npm) update + $(npm) run development + +# Removes the build directory and the compiled files .PHONY: clean clean: - rm -rf ./build + rm -f ./css/style.scss + rm -f ./css/src/sprites.scss + rm -f ./img/sprites.svg + rm -f ./js/public/build.js + rm -f ./js/public/build.js.map + rm -rf $(build_directory) # Same as clean but also removes dependencies installed by npm .PHONY: distclean distclean: clean - rm -rf vendor rm -rf node_modules - rm -rf js/vendor - rm -rf js/node_modules -# Builds the source and appstore package -.PHONY: dist -dist: - make source - make appstore +# Watches the js and scss files +.PHONY: watch +watch: + $(npm) run watch -# Run make and make dist in a Docker container -.PHONY: docker-dist -docker-dist: - docker run --rm -it -v $(CURDIR):/tasks -w /tasks node make docker-target - -# Command used inside Docker container; do not invoke directly -.PHONY: docker-target -docker-target: - which rsync zip openssl || (apt-get update && apt-get install -y rsync zip openssl) - make - make dist - -# Builds the source package -.PHONY: source -source: - rm -rf $(source_build_directory) $(source_artifact_directory) - mkdir -p $(source_build_directory) $(source_artifact_directory) - rsync -rv . $(source_build_directory) \ - --exclude=/.git/ \ - --exclude=/.idea/ \ - --exclude=/build/ \ - --exclude=/js/node_modules/ \ - --exclude=/node_modules/ \ - --exclude=*.log -ifdef CAN_SIGN - $(sign) --path "$(source_build_directory)" -else - @echo $(sign_skip_msg) -endif - tar -cvzf $(source_package_name).tar.gz -C $(source_build_directory)/../ $(app_name) - -# Builds the source package for the app store, ignores php and js tests +# Builds the source package for the app store .PHONY: appstore -appstore: - rm -rf $(appstore_build_directory) $(appstore_artifact_directory) +appstore: clean build mkdir -p $(appstore_build_directory) $(appstore_artifact_directory) rsync -av . $(appstore_build_directory) \ - --exclude=/tests \ --exclude=/.git \ - --exclude=/.idea \ + --exclude=/.babelrc \ --exclude=/.editorconfig \ - --exclude=/.gitattributes \ --exclude=/.gitignore \ - --exclude=/.scrutinizer.yml \ - --exclude=/.travis.yml \ - --exclude=/.tx \ - --exclude=/build.xml \ - --exclude=/CONTRIBUTING.md \ - --exclude=/tasks.sublime-project \ - --exclude=/tasks.sublime-workspace \ - --exclude=/issue_template.md \ - --exclude=/Makefile \ - --exclude=/phpunit.xml \ - --exclude=/README.md \ - --exclude=/CHANGELOG.md \ - --exclude=/build \ - --exclude=/css/src \ - --exclude=/img/src \ + --exclude=/.gitlab-ci.yml \ --exclude=/.jshintrc \ --exclude=/.stylelintrc \ + --exclude=/.v8flags*.json \ + --exclude=/CONTRIBUTING.md \ + --exclude=/issue_template.md \ --exclude=/gulpfile.js \ - --exclude=/node_modules \ - --exclude=/package.json \ + --exclude=/Makefile \ --exclude=/package-lock.json \ - --exclude=/js/README.md \ - --exclude=/js/README.mkdir \ + --exclude=/package.json \ + --exclude=/README.md \ + --exclude=/webpack.common.js \ + --exclude=/webpack.prod.js \ + --exclude=/webpack.test.js \ + --exclude=/.nyc_output/ \ + --exclude=/build \ + --exclude=/coverage \ + --exclude=/css/src \ + --exclude=/img/src \ --exclude=/js/app \ - --exclude=/js/config \ - --exclude=/js/vendor/**/.bower.json \ - --exclude=/js/vendor/**/.npmignore \ - --exclude=/js/vendor/**/bower.json \ - --exclude=/js/vendor/**/Gruntfile.js \ - --exclude=/js/vendor/**/package.json \ - --exclude=/js/vendor/**/*.md \ - --exclude=/js/vendor/**/karma.conf.js \ - --exclude=/js/vendor/**/*.map \ - --exclude=/js/vendor/angular-mocks \ - --exclude=/js/vendor/angular/angular.js \ - --exclude=/js/vendor/angular/angular.min.js.gzip \ - --exclude=/js/vendor/angular/angular-csp.css \ - --exclude=/js/vendor/angular/index.js \ - --exclude=/js/vendor/angular-animate/angular-animate.js \ - --exclude=/js/vendor/angular-animate/index.js \ - --exclude=/js/vendor/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js \ - --exclude=/js/vendor/angular-drag-and-drop-lists/demo \ - --exclude=/js/vendor/angular-drag-and-drop-lists/test \ - --exclude=/js/vendor/angular-drag-and-drop-lists/LICENSE \ - --exclude=/js/vendor/angular-route/angular-route.js \ - --exclude=/js/vendor/angular-route/index.js \ - --exclude=/js/vendor/angular-sanitize/angular-sanitize.js \ - --exclude=/js/vendor/angular-sanitize/index.js \ - --exclude=/js/vendor/angular-ui-select/dist/select.js \ - --exclude=/js/vendor/angular-ui-select/dist/select.css \ - --exclude=/js/vendor/angular-ui-select/docs \ - --exclude=/js/vendor/angular-ui-select/composer.json \ - --exclude=/js/vendor/angular-ui-select/deploy-docs.sh \ - --exclude=/js/vendor/ical.js/build/benchmark \ - --exclude=/js/vendor/ical.js/build/ical.js \ - --exclude=/js/vendor/ical.js/lib \ - --exclude=/js/vendor/ical.js/samples \ - --exclude=/js/vendor/ical.js/sandbox \ - --exclude=/js/vendor/ical.js/tasks \ - --exclude=/js/vendor/ical.js/test-agent \ - --exclude=/js/vendor/ical.js/test-agent-server.js \ - --exclude=/js/vendor/ical.js/test-agent-coverage.json \ - --exclude=/js/vendor/jstimezonedetect/dist/jstz.js \ - --exclude=/js/vendor/jstimezonedetect/LICENCE.txt \ - --exclude=/js/vendor/ui-select/dist/select.js \ - --exclude=/js/vendor/ui-select/dist/select.css \ - --exclude=/js/vendor/ui-select/docs \ - --exclude=/js/vendor/ui-select/src \ - --exclude=/js/vendor/ui-select/test \ - --exclude=/js/vendor/ui-select/composer.json \ - --exclude=/js/vendor/ui-select/deploy-docs.sh \ - --exclude=/js/vendor/ui-select/*.js \ - --exclude=/js/vendor/ui-select/LICENSE \ - --exclude=/js/vendor_legacy/jquery-timepicker/i18n \ - --exclude=/js/vendor_legacy/jquery-timepicker/include \ - --exclude=/js/vendor_legacy/jquery-timepicker/legacy_1.2.6 \ - --exclude=/js/vendor_legacy/jquery-timepicker/tests \ - --exclude=/js/vendor_legacy/jquery-timepicker/index.html \ - --exclude=/js/vendor_legacy/jquery-timepicker/jquery.ui.timepicker.css \ - --exclude=/js/vendor_legacy/jquery-timepicker/GPL-LICENSE.txt \ - --exclude=/js/vendor_legacy/jquery-timepicker/MIT-LICENSE.txt \ - --exclude=/js/vendor_legacy/jquery-timepicker/README.md \ - --exclude=/js/vendor_legacy/jquery-timepicker/timepicker.png \ - --exclude=/screenshots \ - --exclude=/timezones/INFO.md + --exclude=/node_modules \ + --exclude=/screenshots/ \ + --exclude=/test ifdef CAN_SIGN mv $(configdir)/config.php $(configdir)/config-2.php $(sign) --path="$(appstore_build_directory)" @@ -250,24 +137,14 @@ endif cd $(appstore_build_directory)/../; \ zip -r $(appstore_package_name).zip $(app_name) tar -czf $(appstore_package_name).tar.gz -C $(appstore_build_directory)/../ $(app_name) +# create hash ifdef CAN_SIGN openssl dgst -sha512 -sign $(private_key) $(appstore_package_name).tar.gz | openssl base64 -out $(appstore_artifact_directory)/$(app_name).sha512 +else + @echo "Skipping hashing, no key found in $(private_key)." endif - -# Command for running JS and PHP tests. Works for package.json files in the js/ -# and root directory. If phpunit is not installed systemwide, a copy is fetched -# from the internet +# Command for running VUE tests .PHONY: test test: - cd js && $(npm) run test -ifeq (, $(shell which phpunit 2> /dev/null)) - @echo "No phpunit command available, downloading a copy from the web" - mkdir -p $(build_tools_directory) - curl -sSL https://phar.phpunit.de/phpunit.phar -o $(build_tools_directory)/phpunit.phar - php $(build_tools_directory)/phpunit.phar -c phpunit.xml --coverage-clover build/php-unit.clover - php $(build_tools_directory)/phpunit.phar -c phpunit.integration.xml --coverage-clover build/php-integration.clover -else - phpunit -c phpunit.xml --coverage-clover build/php-unit.clover - phpunit -c phpunit.integration.xml --coverage-clover build/php-unit.clover -endif + $(npm) run test diff --git a/gulpfile.js b/gulpfile.js index 3a35af4b..a00b7fbd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,5 @@ /** - * Nextcloud - Inventory + * Nextcloud - Tasks * * This file is licensed under the Affero General Public License version 3 or * later. See the COPYING file. @@ -19,35 +19,31 @@ // get plugins const gulp = require('gulp'), - uglify = require('gulp-uglify'), jshint = require('gulp-jshint'), - KarmaServer = require('karma').Server, concat = require('gulp-concat'), - wrap = require('gulp-wrap'), - strip = require('gulp-strip-banner'), - babel = require('gulp-babel'), stylelint = require('gulp-stylelint'), - sourcemaps = require('gulp-sourcemaps'), svgSprite = require('gulp-svg-sprite'), - npmFiles = require('gulp-npm-files'); + webpackStream = require('webpack-stream'), + webpackDevelopmentConfig = require('./webpack.common.js'), + webpackProductionConfig = require('./webpack.prod.js'); // configure -const buildTarget = 'app.min.js'; -const scssBuildTarget = 'style.scss'; -const karmaConfig = __dirname + '/tests/js/config/karma.js'; const destinationFolder = __dirname + '/js/public/'; +const scssBuildTarget = 'style.scss'; const scssDestinationFolder = __dirname + '/css/'; const jsSources = [ - './js/app/**/*.js' + 'js/app/**/*.js' ]; const scssSources = [ - './css/src/*.scss' + 'css/src/*.scss' +]; +const testSources = [ + 'test/**/*.js' ]; -const testSources = ['./tests/js/unit/**/*.js']; const lintSources = jsSources.concat(testSources).concat(['*.js']); -const watchSources = lintSources; +const watchSources = jsSources.concat(['js/app/**/*.vue']); const svgConfig = { shape: { @@ -62,7 +58,7 @@ const svgConfig = { sprite: "../img/sprites.svg", render: { scss: { - dest: "src/sprite.scss" + dest: "src/sprites.scss" } } } @@ -70,31 +66,27 @@ const svgConfig = { }; // tasks -gulp.task('build', ['lint'], () => { - return gulp.src(jsSources) - .pipe(babel({ - presets: ['es2015'], - compact: false, - babelrc: false, - ast: false - })) - .pipe(strip()) - .pipe(sourcemaps.init({identityMap: true})) - .pipe(concat(buildTarget)) - .pipe(wrap(`(function($, oc_requesttoken, undefined){ - 'use strict'; +gulp.task('default', ['build']); - <%= contents %> -})(jQuery, oc_requesttoken);`)) - .pipe(uglify()) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(destinationFolder)); +gulp.task('build', ['lint', 'scssConcat'], function(callback) { + return webpackStream(webpackProductionConfig, require('webpack')) + .pipe(gulp.dest(destinationFolder)); }); -gulp.task('default', ['build', 'vendor', 'scsslint', 'scssConcat']); +gulp.task('development', ['lint', 'scssConcat'], function(callback) { + return webpackStream(webpackDevelopmentConfig, require('webpack')) + .pipe(gulp.dest(destinationFolder)); +}); -gulp.task('lint', () => { +gulp.task('jsWatch', ['jslint'], function(callback) { + return webpackStream(webpackDevelopmentConfig, require('webpack')) + .pipe(gulp.dest(destinationFolder)); +}); + +gulp.task('lint', ['jslint', 'scsslint']); + +gulp.task('jslint', () => { return gulp.src(lintSources) .pipe(jshint('.jshintrc')) .pipe(jshint.reporter('default')) @@ -124,35 +116,12 @@ gulp.task('scssConcatWatch', ['scsslint'], () => { }); gulp.task('watch', () => { - gulp.watch(watchSources, ['build']); + gulp.watch(watchSources, ['jsWatch']); gulp.watch(scssSources, ['scssConcatWatch']); }); -gulp.task('karma', (done) => { - new KarmaServer({ - configFile: karmaConfig, - singleRun: true, - browsers: ['Firefox'], - reporters: ['progress', 'coverage'] - }, done).start(); -}); - -gulp.task('watch-karma', (done) => { - new KarmaServer({ - configFile: karmaConfig, - autoWatch: true, - browsers: ['Firefox'], - reporters: ['progress', 'coverage'] - }, done).start(); -}); - gulp.task('svg_sprite', () => { return gulp.src('**/*.svg', {cwd: 'img/src'}) .pipe(svgSprite(svgConfig)) .pipe(gulp.dest('.')); }); - -gulp.task("vendor", () => { - return gulp.src(npmFiles(), { base: "./node_modules" }) - .pipe(gulp.dest('./js/vendor')); -}); diff --git a/js/app/app.js b/js/app/app.js index 13d8b8e0..7c32fe9d 100644 --- a/js/app/app.js +++ b/js/app/app.js @@ -18,168 +18,54 @@ * License along with this library. If not, see . * */ +'use strict'; -$('#content.app-tasks').attr('ng-app', 'Tasks'); -$('#content.app-tasks').attr('ng-cloak'); -$('#content.app-tasks').attr('ng-controller', 'AppController'); -$('#content.app-tasks').attr('ng-click', 'closeAll($event)'); -$('#content.app-tasks').addClass('handler'); +import Vue from 'vue'; +import Vuex from 'vuex'; +import { mapState } from 'vuex'; +import VueRouter from 'vue-router'; -angular.module('Tasks', ['ngRoute', 'ngAnimate', 'ui.select', 'ngSanitize', 'dndLists']).config([ - '$provide', '$routeProvider', '$interpolateProvider', '$httpProvider', - function($provide, $routeProvider, $interpolateProvider, $httpProvider) { - 'use strict'; - var config; - $provide.value('Config', config = { - markReadTimeout: 500, - taskUpdateInterval: 1000 * 600 - }); - $httpProvider.defaults.headers.common.requesttoken = oc_requesttoken; - $routeProvider - .when('/calendars/:calendarID', {}) - .when('/calendars/:calendarID/edit/:listparameter', {}) - .when('/calendars/:calendarID/tasks/:taskID', {}) - .when('/calendars/:calendarID/tasks/:taskID/settings', {}) - .when('/calendars/:calendarID/tasks/:taskID/edit/:parameter', {}) - .when('/collections/:collectionID/tasks/:taskID', {}) - .when('/collections/:collectionID/tasks/:taskID/settings', {}) - .when('/collections/:collectionID/tasks/:taskID/edit/:parameter', {}) - .when('/collections/:collectionID', {}) - .when('/search/:searchString', {}) - .when('/search/:searchString/tasks/:taskID', {}) - .when('/search/:searchString/tasks/:taskID/edit/:parameter', {}) - .otherwise({ - redirectTo: '/collections/all' - }); - } -]); +import router from './components/TheRouter.js'; +import store from './store'; -angular.module('Tasks').run([ - '$document', '$rootScope', 'Config', '$timeout', 'ListsBusinessLayer', 'TasksBusinessLayer', 'SearchBusinessLayer', - function($document, $rootScope, Config, $timeout, TasksBusinessLayer, ListsBusinessLayer, SearchBusinessLayer) { - 'use strict'; - var update; - var init = false; - (update = function() { - var timeOutUpdate; - timeOutUpdate = function() { - return $timeout(update, Config.taskUpdateInterval); - }; - init = true; - return timeOutUpdate(); - }).call(); - OCA.Search.tasks = SearchBusinessLayer; - $document.click(function(event) { - $rootScope.$broadcast('documentClicked', event); - }); - moment.locale('details', { - calendar: { - lastDay: '[' + t('tasks', 'Due yesterday') + '], HH:mm', - sameDay: '[' + t('tasks', 'Due today') + '], HH:mm', - nextDay: '[' + t('tasks', 'Due tomorrow') + '], HH:mm', - lastWeek: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY, HH:mm', - nextWeek: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY, HH:mm', - sameElse: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY, HH:mm' - } - }); - moment.locale('details_allday', { - calendar: { - lastDay: '[' + t('tasks', 'Due yesterday') + ']', - sameDay: '[' + t('tasks', 'Due today') + ']', - nextDay: '[' + t('tasks', 'Due tomorrow') + ']', - lastWeek: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY', - nextWeek: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY', - sameElse: '[' + t('tasks', 'Due on') + '] MMM DD, YYYY' - } - }); - moment.locale('start', { - calendar: { - lastDay: '[' + t('tasks', 'Started yesterday') + '], HH:mm', - sameDay: '[' + t('tasks', 'Starts today') + '], HH:mm', - nextDay: '[' + t('tasks', 'Starts tomorrow') + '], HH:mm', - lastWeek: '[' + t('tasks', 'Started on') + '] MMM DD, YYYY, HH:mm', - nextWeek: '[' + t('tasks', 'Starts on') + '] MMM DD, YYYY, HH:mm', - sameElse: function() { - if (this.diff(moment()) > 0) { - return '[' + t('tasks', 'Starts on') + '] MMM DD, YYYY, HH:mm'; - } else { - return '[' + t('tasks', 'Started on') + '] MMM DD, YYYY, HH:mm'; +Vue.prototype.OC = OC; +Vue.prototype.t = t; +Vue.prototype.n = n; + +export class App { + start() { + OCA.Tasks.App.Vue = new Vue({ + el: '.app-tasks', + router: router, + store: store, + data: { + active: 'items', + searchString: '', + snap: false, + views: [ + { + name: t('tasks', 'Collections'), + id: "collections" + }, + { + name: t('tasks', 'Calendars'), + id: "calendars" } + ] + }, + methods: { + filter(query) { + this.searchString = query; + }, + cleanSearch() { + this.searchString = ''; } - } - }); - moment.locale('start_allday', { - calendar: { - lastDay: '[' + t('tasks', 'Started yesterday') + ']', - sameDay: '[' + t('tasks', 'Starts today') + ']', - nextDay: '[' + t('tasks', 'Starts tomorrow') + ']', - lastWeek: '[' + t('tasks', 'Started on') + '] MMM DD, YYYY', - nextWeek: '[' + t('tasks', 'Starts on') + '] MMM DD, YYYY', - sameElse: function() { - if (this.diff(moment()) > 0) { - return '[' + t('tasks', 'Starts on') + '] MMM DD, YYYY'; - } else { - return '[' + t('tasks', 'Started on') + '] MMM DD, YYYY'; - } - } - } - }); - moment.locale('reminder', { - calendar: { - lastDay: t('tasks', '[Remind me yesterday at ]HH:mm'), - sameDay: t('tasks', '[Remind me today at ]HH:mm'), - nextDay: t('tasks', '[Remind me tomorrow at ]HH:mm'), - lastWeek: t('tasks', '[Remind me on ]MMM DD, YYYY,[ at ]HH:mm'), - nextWeek: t('tasks', '[Remind me on ]MMM DD, YYYY,[ at ]HH:mm'), - sameElse: t('tasks', '[Remind me on ]MMM DD, YYYY,[ at ]HH:mm') - } - }); - moment.locale('tasks', { - calendar: { - lastDay: '[' + t('tasks', 'Yesterday') + ']', - sameDay: '[' + t('tasks', 'Today') + ']', - nextDay: '[' + t('tasks', 'Tomorrow') + ']', - lastWeek: 'DD.MM.YYYY', - nextWeek: 'DD.MM.YYYY', - sameElse: 'DD.MM.YYYY' - } - }); - moment.locale('details_short', { - calendar: { - lastDay: '[' + t('tasks', 'Yesterday') + ']', - sameDay: '[' + t('tasks', 'Today') + ']', - nextDay: '[' + t('tasks', 'Tomorrow') + ']', - lastWeek: 'MMM DD, YYYY', - nextWeek: 'MMM DD, YYYY', - sameElse: 'MMM DD, YYYY' - } - }); - moment.locale('list_week', { - calendar: { - lastDay: '[' + t('tasks', 'Yesterday') + ']', - sameDay: '[' + t('tasks', 'Today') + '], MMM. DD', - nextDay: '[' + t('tasks', 'Tomorrow') + '], MMM. DD', - lastWeek: 'ddd, MMM. DD', - nextWeek: 'ddd, MMM. DD', - sameElse: 'ddd, MMM. DD' - } - }); - return moment.locale('en', { - relativeTime: { - future: t('tasks', "in %s"), - past: t('tasks', "%s ago"), - s: t('tasks', "seconds"), - m: t('tasks', "a minute"), - mm: t('tasks', "%d minutes"), - h: t('tasks', "an hour"), - hh: t('tasks', "%d hours"), - d: t('tasks', "a day"), - dd: t('tasks', "%d days"), - M: t('tasks', "a month"), - MM: t('tasks', "%d months"), - y: t('tasks', "a year"), - yy: t('tasks', "%d years") - } + }, + computed: mapState({ + showModal: state => state.showModal + }) }); + + store.dispatch('loadItems'); } -]); +} diff --git a/js/app/filters/priorityDetails.js b/js/app/components/TheRouter.js similarity index 54% rename from js/app/filters/priorityDetails.js rename to js/app/components/TheRouter.js index b7076a55..298ce79a 100644 --- a/js/app/filters/priorityDetails.js +++ b/js/app/components/TheRouter.js @@ -19,20 +19,26 @@ * */ +import Vue from "vue"; +import VueRouter from "vue-router"; -angular.module('Tasks').filter('priorityDetails', function() { - 'use strict'; - return function(priority) { - var string; - string = t('tasks', 'priority %s: ').replace('%s', priority); - if (+priority === 6 || +priority === 7 || +priority === 8 || +priority === 9) { - return string + ' ' + t('tasks', 'high'); - } else if (+priority === 5) { - return string + ' ' + t('tasks', 'medium'); - } else if (+priority === 1 || +priority === 2 || +priority === 3 || +priority === 4) { - return string + ' ' + t('tasks', 'low'); - } else { - return t('tasks', 'no priority assigned'); - } - }; +import Collections from "./TheCollections.vue"; +import ItemsNew from "./TheItemsCreator.vue"; + +const routes = [ + // using + // { path: '/collections', component: Collections, alias: '/' }, + // instead of + { path: '/', redirect: '/collections' }, + { path: '/collections', component: Collections}, + // would also be an option, but it currently does not work + // reliably with router-link due to + // https://github.com/vuejs/vue-router/issues/419 + { path: '/calendars/:id', component: Calendars, props: true}, +]; + +Vue.use(VueRouter); + +export default new VueRouter({ + routes, // short for `routes: routes` }); diff --git a/js/app/controllers/appcontroller.js b/js/app/controllers/appcontroller.js deleted file mode 100644 index 592a81ea..00000000 --- a/js/app/controllers/appcontroller.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').controller('AppController', [ - '$scope', '$rootScope', 'ListsBusinessLayer', '$route', 'Status', '$timeout', '$location', '$routeParams', 'Loading', 'SettingsModel', 'Persistence', function($scope, $rootScope, ListsBusinessLayer, $route, status, $timeout, $location, $routeParams, Loading, SettingsModel, Persistence) { - 'use strict'; - var AppController = (function() { - function AppController(_$scope, $rootScope, _$listsbusinesslayer, _$route, _$status, _$timeout, _$location, _$routeparams, _Loading, _$settingsmodel, _persistence) { - this._$scope = _$scope; - this._$listsbusinesslayer = _$listsbusinesslayer; - this._$route = _$route; - this._$status = _$status; - this._$timeout = _$timeout; - this._$location = _$location; - this._$routeparams = _$routeparams; - this._Loading = _Loading; - this._$settingsmodel = _$settingsmodel; - this._persistence = _persistence; - this._$scope.status = this._$status.getStatus(); - this._$scope.route = this._$routeparams; - this._$scope.status.newListName = ""; - this._$scope.settingsmodel = this._$settingsmodel; - - this._$listsbusinesslayer.init().then(function(results) { - Promise.all(results).then(function() { - $scope.$apply(); - }); - }); - - this._persistence.init(); - - this._$scope.closeAll = function($event) { - if ($($event.target).closest('.close-all').length || $($event.currentTarget).is($($event.target).closest('.handler'))) { - if (!angular.isUndefined(_$scope.route.calendarID)) { - if (_$scope.route.listparameter === 'name') { - $rootScope.$broadcast('cancelEditCalendar', _$scope.route.calendarID); - } - _$location.path('/calendars/' + _$scope.route.calendarID); - } else if (!angular.isUndefined(_$scope.route.collectionID)) { - _$location.path('/collections/' + _$scope.route.collectionID); - } else { - _$location.path('/collections/all'); - } - _$scope.status.addingList = false; - _$scope.status.focusTaskInput = false; - _$scope.status.newListName = ""; - } - if (!$($event.target).closest('.newList').length) { - _$scope.status.addingList = false; - _$scope.status.newListName = ""; - } - if (!$($event.target).closest('.add-subtask').length) { - _$scope.status.addSubtaskTo = null; - _$scope.status.focusSubtaskInput = false; - } - }; - this._$scope.isLoading = function() { - return _Loading.isLoading(); - }; - } - return AppController; - })(); - return new AppController($scope, $rootScope, ListsBusinessLayer, $route, status, $timeout, $location, $routeParams, Loading, SettingsModel, Persistence); - } -]); diff --git a/js/app/controllers/detailscontroller.js b/js/app/controllers/detailscontroller.js deleted file mode 100644 index a46995c6..00000000 --- a/js/app/controllers/detailscontroller.js +++ /dev/null @@ -1,397 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').controller('DetailsController', [ - '$scope', '$window', 'TasksModel', 'TasksBusinessLayer', '$route', '$location', '$timeout', '$routeParams', 'SettingsModel', 'Loading', 'ListsModel', - function($scope, $window, TasksModel, TasksBusinessLayer, $route, $location, $timeout, $routeParams, SettingsModel, Loading, ListsModel) { - 'use strict'; - var DetailsController = (function() { - function DetailsController(_$scope, _$window, _$tasksmodel, - _tasksbusinesslayer, _$route, _$location, _$timeout, _$routeparams, _$settingsmodel, _Loading, _$listsmodel) { - this._$scope = _$scope; - this._$window = _$window; - this._$tasksmodel = _$tasksmodel; - this._$listsmodel = _$listsmodel; - this._tasksbusinesslayer = _tasksbusinesslayer; - this._$route = _$route; - this._$location = _$location; - this._$timeout = _$timeout; - this._$routeparams = _$routeparams; - this._$settingsmodel = _$settingsmodel; - this._Loading = _Loading; - this._$scope.task = _$tasksmodel.getById(_$scope.route.taskID); - this._$scope.found = true; - this._$scope.$on('$routeChangeSuccess', function() { - var task = _$tasksmodel.getByUri(_$scope.route.taskID); - - if (!(angular.isUndefined(task) || task === null)) { - _$scope.task = task; - // Bind categories to task.cats as angular.ui/ui-select seems to have problems with Getter/Setter - _$scope.task.cats = task.categories; - _$scope.found = true; - } else if (_$scope.route.taskID !== void 0) { - _$scope.found = false; - } - }); - - this._$scope.settingsmodel = this._$settingsmodel; - this._$scope.settingsmodel.add({ - 'id': 'various', - 'categories': [] - }); - this._$scope.isAddingComment = false; - this._$scope.timers = []; - this._$scope.durations = [{ - name: t('tasks', 'week'), - names: t('tasks', 'weeks'), - id: 'week' - }, { - name: t('tasks', 'day'), - names: t('tasks', 'days'), - id: 'day' - }, { - name: t('tasks', 'hour'), - names: t('tasks', 'hours'), - id: 'hour' - }, { - name: t('tasks', 'minute'), - names: t('tasks', 'minutes'), - id: 'minute' - }, { - name: t('tasks', 'second'), - names: t('tasks', 'seconds'), - id: 'second' - } - ]; - this._$scope.loadTask = function(taskID) { - var task = _$tasksmodel.getByUri(_$scope.route.taskID); - if (!(angular.isUndefined(task) || task === null)) { - _$scope.task = task; - _$scope.found = true; - } - }; - this._$scope.TaskState = function() { - if (_$scope.found) { - return 'found'; - } else { - if (_Loading.isLoading()) { - return 'loading'; - } else { - return null; - } - } - }; - this._$scope.params = [ - { - name: t('tasks', 'before beginning'), - invert: true, - related: 'START', - id: "10" - }, { - name: t('tasks', 'after beginning'), - invert: false, - related: 'START', - id: "00" - }, { - name: t('tasks', 'before end'), - invert: true, - related: 'END', - id: "11" - }, { - name: t('tasks', 'after end'), - invert: false, - related: 'END', - id: "01" - } - ]; - this._$scope.filterParams = function(params) { - var task; - task = _$tasksmodel.getById(_$scope.route.taskID); - if (!(angular.isUndefined(task) || task === null)) { - if (task.due && task.start) { - return params; - } else if (task.start) { - return params.slice(0, 2); - } else { - return params.slice(2); - } - } - }; - this._$scope.deleteTask = function(task) { - return _$timeout(function() { - return _tasksbusinesslayer.deleteTask(task).then(function () { - return $scope.$apply(); - }); - }, 500); - }; - this._$scope.triggerUpdate = function(task) { - _tasksbusinesslayer.triggerUpdate(task); - }; - this._$scope.editName = function($event, task) { - if (task.calendar.writable) { - if (!$($event.target).is('a')) { - _$scope.setEditRoute('name'); - } - } - }; - this._$scope.editDueDate = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.setEditRoute('duedate'); - _tasksbusinesslayer.initDueDate(task); - } - } - }; - this._$scope.editStart = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.setEditRoute('startdate'); - _tasksbusinesslayer.initStartDate(task); - } - } - }; - this._$scope.editReminder = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.setEditRoute('reminer'); - return _tasksbusinesslayer.initReminder(_$scope.route.taskID); - } - } - }; - this._$scope.editNote = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - if (!$($event.target).is('a')) { - _$scope.setEditRoute('note'); - } - } - } - }; - this._$scope.editPriority = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.setEditRoute('priority'); - } - } - }; - this._$scope.editPercent = function($event, task) { - if (task.calendar.writable) { - if ($($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.setEditRoute('percent'); - } - } - }; - this._$scope.endEdit = function($event) { - if ($($event.target).closest('.end-edit').length || $($event.currentTarget).is($($event.target).closest('.handler'))) { - _$scope.resetRoute(); - } - }; - this._$scope.endName = function($event) { - if ($event.keyCode === 13) { - $event.preventDefault(); - _$scope.resetRoute(); - } - if ($event.keyCode === 27) { - return _$scope.resetRoute(); - } - }; - - this._$scope.setEditRoute = function(type) { - var calendarID = _$scope.route.calendarID; - var collectionID = _$scope.route.collectionID; - if (calendarID) { - $location.path('/calendars/' + calendarID + '/tasks/' + _$scope.route.taskID + '/edit/' + type); - } else if (collectionID) { - $location.path('/collections/' + collectionID + '/tasks/' + _$scope.route.taskID + '/edit/' + type); - } - }; - - this._$scope.resetRoute = function() { - var calendarID = _$scope.route.calendarID; - var collectionID = _$scope.route.collectionID; - if (calendarID) { - $location.path('/calendars/' + calendarID + '/tasks/' + _$scope.route.taskID); - } else if (collectionID) { - $location.path('/collections/' + collectionID + '/tasks/' + _$scope.route.taskID); - } - }; - this._$scope.deletePercent = function(task) { - return _tasksbusinesslayer.setPercentComplete(task, 0); - }; - this._$scope.deleteReminder = function() { - return _tasksbusinesslayer.deleteReminderDate(_$scope.route.taskID); - }; - - this._$scope.toggleCompleted = function(task) { - if (task.completed) { - _tasksbusinesslayer.setPercentComplete(task, 0); - } else { - _tasksbusinesslayer.setPercentComplete(task, 100); - } - }; - - this._$scope.setPercentComplete = function(task, complete) { - _tasksbusinesslayer.setPercentComplete(task, complete); - }; - - this._$scope.toggleStarred = function(task) { - if (task.priority > 5) { - _tasksbusinesslayer.setPriority(task, 0); - } else { - _tasksbusinesslayer.setPriority(task, 9); - } - }; - - this._$scope.deletePriority = function(task) { - return _tasksbusinesslayer.setPriority(task, 0); - }; - this._$scope.isDue = function(date) { - return _$tasksmodel.due(date); - }; - this._$scope.isOverDue = function(date) { - return _$tasksmodel.overdue(date); - }; - - this._$scope.setstartday = function(date) { - return _tasksbusinesslayer.setStart(_$scope.task, moment(date, 'MM/DD/YYYY'), 'day'); - }; - this._$scope.setstarttime = function(date) { - return _tasksbusinesslayer.setStart(_$scope.task, moment(date, 'HH:mm'), 'time'); - }; - this._$scope.deleteStartDate = function(task) { - _tasksbusinesslayer.deleteStartDate(task); - }; - - this._$scope.setdueday = function(date) { - return _tasksbusinesslayer.setDue(_$scope.task, moment(date, 'MM/DD/YYYY'), 'day'); - }; - this._$scope.setduetime = function(date) { - return _tasksbusinesslayer.setDue(_$scope.task, moment(date, 'HH:mm'), 'time'); - }; - this._$scope.deleteDueDate = function(task) { - _tasksbusinesslayer.deleteDueDate(task); - }; - - this._$scope.isAllDayPossible = function(task) { - return !angular.isUndefined(task) && task.calendar.writable && (task.due || task.start); - }; - this._$scope.toggleAllDay = function(task) { - _tasksbusinesslayer.setAllDay(task, !task.allDay); - }; - - this._$scope.setreminderday = function(date) { - return _tasksbusinesslayer.setReminderDate(_$scope.route.taskID, moment(date, 'MM/DD/YYYY'), 'day'); - }; - this._$scope.setremindertime = function(date) { - return _tasksbusinesslayer.setReminderDate(_$scope.route.taskID, moment(date, 'HH:mm'), 'time'); - }; - this._$scope.reminderType = function(task) { - if (!angular.isUndefined(task)) { - if (task.reminder === null) { - if (moment(task.start, "YYYYMMDDTHHmmss").isValid() || moment(task.due, "YYYYMMDDTHHmmss").isValid()) { - return 'DURATION'; - } else { - return 'DATE-TIME'; - } - } else { - return task.reminder.type; - } - } - }; - this._$scope.changeReminderType = function(task) { - _tasksbusinesslayer.checkReminderDate(task.id); - if (this.reminderType(task) === 'DURATION') { - if (task.reminder) { - task.reminder.type = 'DATE-TIME'; - } else { - task.reminder = { - type: 'DATE-TIME' - }; - } - } else { - if (task.reminder) { - task.reminder.type = 'DURATION'; - } else { - task.reminder = { - type: 'DURATION' - }; - } - } - return _tasksbusinesslayer.setReminder(task.id); - }; - this._$scope.setReminderDuration = function(taskID) { - return _tasksbusinesslayer.setReminder(_$scope.route.taskID); - }; - this._$scope.addComment = function() { - var comment, - _this = this; - if (_$scope.CommentContent) { - _$scope.isAddingComment = true; - comment = { - tmpID: 'newComment' + Date.now(), - comment: _$scope.CommentContent, - taskID: _$scope.route.taskID, - time: moment().format('YYYYMMDDTHHmmss'), - name: $('#expandDisplayName').text() - }; - _tasksbusinesslayer.addComment(comment, function(data) { - _$tasksmodel.updateComment(data); - _$scope.isAddingComment = false; - }, function() { - _$scope.isAddingComment = false; - }); - _$scope.CommentContent = ''; - } - }; - this._$scope.sendComment = function(event) { - if (event.keyCode === 13) { - return _$scope.addComment(); - } - }; - this._$scope.deleteComment = function(commentID) { - return _tasksbusinesslayer.deleteComment(_$scope.route.taskID, commentID); - }; - this._$scope.commentStrings = function() { - return { - button: t('tasks', 'Comment'), - input: t('tasks', 'Add a comment') - }; - }; - this._$scope.addCategory = function(category, model) { - _$scope.task.categories = _$scope.task.cats; - var default_categories = _$scope.settingsmodel.getById('various').categories; - if (default_categories.indexOf(category) < 0) { - default_categories.push(category); - } - _tasksbusinesslayer.doUpdate(_$scope.task); - }; - this._$scope.removeCategory = function(category, model) { - _$scope.task.categories = _$scope.task.cats; - _tasksbusinesslayer.doUpdate(_$scope.task); - }; - } - - return DetailsController; - - })(); - return new DetailsController($scope, $window, TasksModel, TasksBusinessLayer, $route, $location, $timeout, $routeParams, SettingsModel, Loading, ListsModel); - } -]); diff --git a/js/app/controllers/settingscontroller.js b/js/app/controllers/settingscontroller.js deleted file mode 100644 index 0daa8e54..00000000 --- a/js/app/controllers/settingscontroller.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').controller('SettingsController', [ - '$scope', '$window', 'Status', '$location', 'CollectionsModel', 'SettingsBusinessLayer', 'SettingsModel', function($scope, $window, Status, $location, CollectionsModel, SettingsBusinessLayer, SettingsModel) { - 'use strict'; - var SettingsController; - SettingsController = (function() { - function SettingsController(_$scope, _$window, _$status, _$location, _$collectionsmodel, _$settingsbusinesslayer, _$settingsmodel) { - var _this = this; - this._$scope = _$scope; - this._$window = _$window; - this._$status = _$status; - this._$location = _$location; - this._$collectionsmodel = _$collectionsmodel; - this._$settingsbusinesslayer = _$settingsbusinesslayer; - this._$settingsmodel = _$settingsmodel; - this._$scope.status = this._$status.getStatus(); - this._$scope.collections = this._$collectionsmodel.getAll(); - this._$scope.settingsmodel = this._$settingsmodel; - this._$scope.collectionOptions = [ - { - id: 0, - name: t('tasks', 'Hidden') - }, { - id: 1, - name: t('tasks', 'Visible') - }, { - id: 2, - name: t('tasks', 'Automatic') - } - ]; - this._$scope.startOfWeekOptions = [ - { - id: 0, - name: t('tasks', 'Sunday') - }, { - id: 1, - name: t('tasks', 'Monday') - }, { - id: 2, - name: t('tasks', 'Tuesday') - }, { - id: 3, - name: t('tasks', 'Wednesday') - }, { - id: 4, - name: t('tasks', 'Thursday') - }, { - id: 5, - name: t('tasks', 'Friday') - }, { - id: 6, - name: t('tasks', 'Saturday') - } - ]; - this._$scope.setVisibility = function(collectionID) { - var collection; - collection = _$collectionsmodel.getById(collectionID); - return _$settingsbusinesslayer.setVisibility(collectionID, collection.show); - }; - this._$scope.setStartOfWeek = function() { - return _$settingsbusinesslayer.set('various', 'startOfWeek', _$settingsmodel.getById('various').startOfWeek); - }; - } - - return SettingsController; - - })(); - return new SettingsController($scope, $window, Status, $location, CollectionsModel, SettingsBusinessLayer, SettingsModel); - } -]); diff --git a/js/app/controllers/taskscontroller.js b/js/app/controllers/taskscontroller.js deleted file mode 100644 index 80865385..00000000 --- a/js/app/controllers/taskscontroller.js +++ /dev/null @@ -1,456 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -(function() { - 'use strict'; - var __indexOf = [].indexOf || function(item) { - for (var i = 0, l = this.length; i < l; i++) { - if (i in this && this[i] === item) { - return i; - } - } - return -1; - }; - - angular.module('Tasks').controller('TasksController', [ - '$scope', '$window', '$routeParams', 'TasksModel', 'ListsModel', 'CollectionsModel', 'TasksBusinessLayer', '$location', - 'SettingsBusinessLayer', 'SearchBusinessLayer', 'VTodo', 'SettingsModel', - function($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location, - SettingsBusinessLayer, SearchBusinessLayer, VTodo, SettingsModel) { - var TasksController; - TasksController = (function() { - function TasksController(_$scope, _$window, _$routeParams, _$tasksmodel, _$listsmodel, _$collectionsmodel, _tasksbusinesslayer, $location, - _settingsbusinesslayer, _searchbusinesslayer, vtodo, _$settingsmodel) { - var _this = this; - this._$scope = _$scope; - this._$window = _$window; - this._$routeParams = _$routeParams; - this._$tasksmodel = _$tasksmodel; - this._$listsmodel = _$listsmodel; - this._$collectionsmodel = _$collectionsmodel; - this._tasksbusinesslayer = _tasksbusinesslayer; - this.$location = $location; - this._settingsbusinesslayer = _settingsbusinesslayer; - this._searchbusinesslayer = _searchbusinesslayer; - this._vtodo = vtodo; - this._$scope.tasks = this._$tasksmodel.getAll(); - this._$scope.draggedTasks = []; - this._$scope.calendars = this._$listsmodel.getAll(); - this._$scope.days = [0, 1, 2, 3, 4, 5, 6]; - this._$scope.isAddingTask = false; - this._$scope.focusInputField = false; - this._$scope.TasksModel = this._$tasksmodel; - this._$scope.TasksBusinessLayer = this._tasksbusinesslayer; - this._$settingsmodel = _$settingsmodel; - - this._$scope.addTask = function(taskName, related, calendar, parent) { - var _ref, _this = this; - if (calendar === null) { - calendar = ''; - } - _$scope.isAddingTask = true; - var task = { - calendar: null, - related: related, - summary: taskName, - priority: '0', - due: false, - start: false, - reminder: null, - completed: false, - complete: '0', - note: '' - }; - if (((_ref = _$scope.route.collectionID) === 'starred' || _ref === 'today' || _ref === 'week' || _ref === 'all' || _ref === 'completed' || _ref === 'current')) { - if (related) { - task.calendar = calendar; - } else { - task.calendar = _$listsmodel.getStandardList(); - } - if (_$scope.route.collectionID === 'starred') { - task.priority = '1'; - } - if (_$scope.route.collectionID === 'today') { - task.due = moment().startOf('day').format("YYYY-MM-DDTHH:mm:ss"); - } - if (_$scope.route.collectionID === 'current') { - task.start = moment().format("YYYY-MM-DDTHH:mm:ss"); - } - } else { - task.calendar = _$listsmodel.getByUri(_$scope.route.calendarID); - } - task = VTodo.create(task); - _tasksbusinesslayer.add(task).then(function(task) { - _$scope.isAddingTask = false; - _$scope.openDetails(task.uri, null); - return $scope.$apply(); - }); - if (parent) { - _tasksbusinesslayer.setHideSubtasks(parent, 0); - } - _$scope.status.focusTaskInput = false; - _$scope.status.focusSubtaskInput = false; - _$scope.status.addSubtaskTo = null; - _$scope.status.taskName = ''; - _$scope.status.subtaskName = ''; - }; - - this._$scope.getAddString = function() { - var calendar = _$listsmodel.getStandardList(); - if (angular.isDefined(calendar)) { - if (angular.isDefined(_$scope.route.collectionID)) { - switch (_$scope.route.collectionID) { - case 'starred': - return t('tasks', 'Add an important item in "%s"...').replace('%s', calendar.displayname); - case 'today': - return t('tasks', 'Add an item due today in "%s"...').replace('%s', calendar.displayname); - case 'all': - return t('tasks', 'Add an item in "%s"...').replace('%s', calendar.displayname); - case 'current': - return t('tasks', 'Add a current item in "%s"...').replace('%s', calendar.displayname); - case 'completed': - case 'week': - return null; - } - } else { - if (angular.isDefined(_$listsmodel.getByUri(_$scope.route.calendarID))) { - return t('tasks', 'Add an item in "%s"...').replace('%s', _$listsmodel.getByUri(_$scope.route.calendarID).displayname); - } - } - } - }; - - this._$scope.getSubAddString = function(taskname) { - return t('tasks', 'Add a subtask to "%s"...').replace('%s', taskname); - }; - - this._$scope.showSubtaskInput = function(uid) { - _$scope.status.addSubtaskTo = uid; - }; - - this._$scope.hideSubtasks = function(task) { - var taskID = _$scope.route.taskID; - var descendantIDs = _$tasksmodel.getDescendantIDs(task); - if (task.uri === taskID) { - return false; - } else if (__indexOf.call(descendantIDs, taskID) >= 0) { - return false; - } else { - return task.hideSubtasks; - } - }; - - this._$scope.showInput = function() { - var collectionID = _$scope.route.collectionID; - var calendar = _$listsmodel.getByUri(_$scope.route.calendarID); - if (collectionID === 'completed' || collectionID === 'week') { - return false; - } - if (angular.isDefined(calendar)) { - return calendar.writable; - } else { - return true; - } - }; - - this._$scope.focusTaskInput = function() { - _$scope.status.focusTaskInput = true; - }; - this._$scope.focusSubtaskInput = function() { - _$scope.status.focusSubtaskInput = true; - }; - - this._$scope.openDetails = function(id, $event) { - var calendarID = _$scope.route.calendarID; - var collectionID = _$scope.route.collectionID; - if ($event === null || $($event.currentTarget).is($($event.target).closest('.handler'))) { - var parent = _$tasksmodel.getByUri(id); - if (!parent.loadedCompleted) { - _tasksbusinesslayer.getAll(parent.calendar, true, parent).then(function() { - parent.loadedCompleted = true; - $scope.$apply(); - }); - } - if (calendarID) { - $location.path('/calendars/' + calendarID + '/tasks/' + id); - } else if (collectionID) { - $location.path('/collections/' + collectionID + '/tasks/' + id); - } - } - }; - - this._$scope.toggleCompleted = function(task) { - if (task.completed) { - _tasksbusinesslayer.setPercentComplete(task, 0); - } else { - _tasksbusinesslayer.setPercentComplete(task, 100); - } - }; - - this._$scope.toggleStarred = function(task) { - if (task.priority > 5) { - _tasksbusinesslayer.setPriority(task, 0); - } else { - _tasksbusinesslayer.setPriority(task, 9); - } - }; - - this._$scope.toggleHidden = function() { - return _settingsbusinesslayer.toggle('various', 'showHidden'); - }; - - this._$scope.filterTasks = function(task, filter) { - return function(task) { - return _$tasksmodel.filterTasks(task, filter); - }; - }; - - this._$scope.getSubTasks = function(tasks, parent) { - var ret, task, _i, _len; - ret = []; - for (_i = 0, _len = tasks.length; _i < _len; _i++) { - task = tasks[_i]; - if (task.related === parent.uid && task !== parent && !(parent.hideCompletedSubtasks && task.completed)) { - ret.push(task); - } - } - return ret; - }; - - this._$scope.hasNoParent = function(task) { - return function(task) { - return _$tasksmodel.hasNoParent(task); - }; - }; - - this._$scope.hasSubtasks = function(task) { - return _$tasksmodel.hasSubtasks(task.uid); - }; - - this._$scope.hasCompletedSubtasks = function(task) { - return _$tasksmodel.hasCompletedSubtasks(task.uid); - }; - - this._$scope.toggleSubtasks = function(task) { - _tasksbusinesslayer.setHideSubtasks(task, !task.hideSubtasks); - }; - - this._$scope.toggleCompletedSubtasks = function(task) { - _tasksbusinesslayer.setHideCompletedSubtasks(task, !task.hideCompletedSubtasks); - }; - - this._$scope.filterTasksByString = function(task) { - return function(task) { - var filter = _searchbusinesslayer.getFilter(); - return _$tasksmodel.filterTasksByString(task, filter); - }; - }; - - this._$scope.filteredTasks = function() { - var filter; - filter = _searchbusinesslayer.getFilter(); - return _$tasksmodel.filteredTasks(filter); - }; - - this._$scope.dayHasEntry = function() { - return function(date) { - var filter, task, tasks, _i, _len; - filter = _searchbusinesslayer.getFilter(); - tasks = _$tasksmodel.filteredTasks(filter); - for (_i = 0, _len = tasks.length; _i < _len; _i++) { - task = tasks[_i]; - if (task.completed || !_$tasksmodel.hasNoParent(task)) { - continue; - } - if (_$tasksmodel.taskAtDay(task, date)) { - return true; - } - } - return false; - }; - }; - this._$scope.taskAtDay = function(task, day) { - return function(task) { - return _$tasksmodel.taskAtDay(task, day); - }; - }; - this._$scope.filterLists = function() { - return function(calendar) { - return _$scope.getCount(calendar.uri, _$scope.route.collectionID); - }; - }; - - this._$scope.getCount = function(calendarID, type) { - var filter = _searchbusinesslayer.getFilter(); - return _$listsmodel.getCount(calendarID, type, filter); - }; - - this._$scope.getCountString = function(calendarID, type) { - var filter = _searchbusinesslayer.getFilter(); - return n('tasks', '%n Completed Task', '%n Completed Tasks', _$listsmodel.getCount(calendarID, type, filter)); - }; - - this._$scope.checkTaskInput = function($event) { - if ($event.keyCode === 27) { - $($event.currentTarget).blur(); - _$scope.status.taskName = ''; - _$scope.status.subtaskName = ''; - _$scope.status.addSubtaskTo = null; - _$scope.status.focusTaskInput = false; - _$scope.status.focusSubtaskInput = false; - } - }; - - this._$scope.getCompletedTasks = function(calendarID) { - var calendar = _$listsmodel.getById(calendarID); - _tasksbusinesslayer.getAll(calendar, true).then(function() { - _$listsmodel.setLoadedCompleted(calendarID); - $scope.$apply(); - }); - }; - - this._$scope.loadedCompleted = function(calendarID) { - return _$listsmodel.loadedCompleted(calendarID); - }; - - this._$scope.sortDue = function(task) { - if (task.due === null) { - return 'last'; - } else { - return task.due; - } - }; - - this._$scope.sortStart = function(task) { - if (task.start === null) { - return 'last'; - } else { - return task.start; - } - }; - - this._$scope.getSortOrder = function() { - switch (_$scope.settingsmodel.getById('various').sortOrder) { - case 'due': - return _$scope.sortDue; - case 'start': - return _$scope.sortStart; - case 'priority': - return '-priority'; - case 'alphabetically': - return 'summary'; - case 'manual': - return 'manual'; - default: - return ['completed', _$scope.sortDue, '-priority', _$scope.sortStart, 'summary']; - } - }; - - this._$scope.getSortOrderIcon = function() { - switch (_$scope.settingsmodel.getById('various').sortOrder) { - case 'due': - case 'start': - return 'icon-calendar'; - case 'priority': - return 'icon-task-star'; - case 'alphabetically': - return 'icon-alphabetically'; - case 'manual': - return 'icon-manual'; - default: - return 'icon-list'; - } - }; - - this._$scope.setSortOrder = function($event, order) { - _$scope.settingsmodel.getById('various').sortDirection = (_$scope.settingsmodel.getById('various').sortOrder === order) ? +!_$scope.settingsmodel.getById('various').sortDirection : 0; - _$scope.settingsmodel.getById('various').sortOrder = order; - _settingsbusinesslayer.set('various', 'sortOrder', order); - _settingsbusinesslayer.set('various', 'sortDirection', _$scope.settingsmodel.getById('various').sortDirection); - }; - - this._$scope.dropAsSubtask = function($event, item, index) { - if ($event.dataTransfer.dropEffect === 'move') { - var parentID = $($event.target).closest('.task-item').attr('taskID'); - var task = _$tasksmodel.getByUri(item.uri); - var parent = _$tasksmodel.getByUri(parentID); - _tasksbusinesslayer.changeParent(task, parent); - } - $('.subtasks-container').removeClass('dropzone-visible'); - return true; - - }; - - this._$scope.dropAsRootTask = function($event, item, index) { - if ($event.dataTransfer.dropEffect === 'move') { - var task = _$tasksmodel.getByUri(item.uri); - var collectionID = $($event.target).closest('ol[dnd-list]').attr('collectionID'); - var calendarID = $($event.target).closest('ol[dnd-list]').attr('calendarID'); - var newCalendar = _$listsmodel.getByUri(calendarID); - var queries = _tasksbusinesslayer.makeRootTask(task, newCalendar, collectionID); - Promise.all(queries).then(function() { - $scope.$apply(); - }); - } - $('.subtasks-container').removeClass('dropzone-visible'); - return true; - }; - - this._$scope.dragover = function($event, item, index) { - $('.subtasks-container').removeClass('dropzone-visible'); - var calendarID = $($event.target).closest('ol[dnd-list]').attr('calendarID'); - var calendar = _$listsmodel.getByUri(calendarID); - if (calendar.writable) { - $($event.target).closest('.task-item').children('.subtasks-container').addClass('dropzone-visible'); - return true; - } else { - return false; - } - }; - - this._$scope.allow = function(task) { - if (task.calendar.writable) { - return "copyMove"; - } else { - return "copy"; - } - }; - - this._$scope.dragStart = function($event) { - if ($event.dataTransfer.effectAllowed === 'copy' || ($event.dataTransfer.effectAllowed === 'copyMove' && $event.ctrlKey)) { - $($event.target).addClass('copy'); - } - }; - - this._$scope.dragEnd = function($event) { - $($event.target).removeClass('copy'); - }; - } - - return TasksController; - - })(); - return new TasksController($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location, SettingsBusinessLayer, - SearchBusinessLayer, VTodo, SettingsModel); - } - ]); - -}).call(this); diff --git a/js/app/directives/appnavigationentryutils.js b/js/app/directives/appnavigationentryutils.js deleted file mode 100644 index 4a003180..00000000 --- a/js/app/directives/appnavigationentryutils.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').directive('appNavigationEntryUtils', function() { - 'use strict'; - return { - restrict: 'C', - link: function(scope, elm) { - var button, menu; - menu = elm.siblings('.app-navigation-entry-menu'); - 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'); - } - }); - } - }; -}); diff --git a/js/app/directives/autofocusoninsert.js b/js/app/directives/autofocusoninsert.js deleted file mode 100644 index 611f7c2f..00000000 --- a/js/app/directives/autofocusoninsert.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - - angular.module('Tasks').directive('autofocusOnInsert', function() { - 'use strict'; - return function(scope, elm) { - return elm.focus(); - }; -}); diff --git a/js/app/directives/avatar.js b/js/app/directives/avatar.js deleted file mode 100644 index 6ccee637..00000000 --- a/js/app/directives/avatar.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').directive('avatar', function() { - 'use strict'; - return { - restrict: 'A', - scope: false, - link: function(scope, elm, attr) { - return attr.$observe('userid', function() { - if (attr.userid) { - return elm.avatar(attr.userid, attr.size); - } - }); - } - }; -}); diff --git a/js/app/directives/colorpickerDirective.js b/js/app/directives/colorpickerDirective.js deleted file mode 100644 index 2764c8b5..00000000 --- a/js/app/directives/colorpickerDirective.js +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Nextcloud - Tasks App - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2017 John Molakvoæ - * - * 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 . - * - */ - -/* https://github.com/kayellpeee/hsl_rgb_converter - * expected hue range: [0, 360) - * expected saturation range: [0, 1] - * expected lightness range: [0, 1] - */ -var hslToRgb = function(hue, saturation, lightness) { - 'use strict'; - // based on algorithm from http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB - if(Array.isArray(hue)) { - saturation = hue[1]; - lightness = hue[2]; - hue = hue[0]; - } - if (hue === undefined) { - return [0, 0, 0]; - } - saturation /= 100; - lightness /= 100; - - var chroma = (1 - Math.abs((2 * lightness) - 1)) * saturation; - var huePrime = hue / 60; - var secondComponent = chroma * (1 - Math.abs((huePrime % 2) - 1)); - - huePrime = Math.floor(huePrime); - var red; - var green; - var blue; - - if (huePrime === 0) { - red = chroma; - green = secondComponent; - blue = 0; - } else if (huePrime === 1) { - red = secondComponent; - green = chroma; - blue = 0; - } else if (huePrime === 2) { - red = 0; - green = chroma; - blue = secondComponent; - } else if (huePrime === 3) { - red = 0; - green = secondComponent; - blue = chroma; - } else if (huePrime === 4) { - red = secondComponent; - green = 0; - blue = chroma; - } else if (huePrime === 5) { - red = chroma; - green = 0; - blue = secondComponent; - } - - var lightnessAdjustment = lightness - (chroma / 2); - red += lightnessAdjustment; - green += lightnessAdjustment; - blue += lightnessAdjustment; - - return [Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255)]; - -}; - -/* - * Convert rgb array to hex string - */ -var rgbToHex = function(r, g, b) { - 'use strict'; - if(Array.isArray(r)) { - g = r[1]; - b = r[2]; - r = r[0]; - } - return '#' + parseInt(r, 10).toString(16) + parseInt(g, 10).toString(16) + parseInt(b, 10).toString(16); -}; - -var listofcolours = [ - '#31CC7C', - '#317CCC', - '#FF7A66', - '#F1DB50', - '#7C31CC', - '#CC317C', - '#3A3B3D', - '#CACBCD' -]; - -/* - * Generate a random colour with the core generator - */ -var randColour = function() { - 'use strict'; - if (typeof String.prototype.toHsl === 'function') { - return rgbToHex(hslToRgb(Math.random().toString().toHsl())); - } else { - return listofcolours[Math.floor(Math.random() * listofcolours.length)]; - } -}; - -/** - * Directive: Colorpicker - * Description: Colorpicker for the Tasks app. - */ - - -angular.module('Tasks').directive('colorpicker', function() { - 'use strict'; - if (typeof String.prototype.toHsl === 'function') { - var hsl = ""; - var hslcolour = ""; - // 0 40 80 120 160 200 240 280 320 - listofcolours = ["15", "9", "4", "b", "6", "11", "74", "f", "57"]; - listofcolours.forEach(function(hash, index) { - hsl = hash.toHsl(); - hslcolour = hslToRgb(hsl); - listofcolours[index] = rgbToHex(hslcolour); - }); - } - return { - scope: { - selected: '=', - customizedColors: '=colors' - }, - restrict: 'AE', - templateUrl: OC.filePath('tasks', 'templates', 'colorpicker.html'), - link: function(scope, element, attr) { - scope.colors = scope.customizedColors || listofcolours; - scope.selected = scope.selected || scope.colors[0]; - scope.random = "#000000"; - - scope.randomizeColour = function() { - scope.random = randColour(); - scope.pick(scope.random); - }; - - scope.pick = function(color) { - scope.selected = color; - }; - - } - }; - -}); diff --git a/js/app/directives/datepicker.js b/js/app/directives/datepicker.js deleted file mode 100644 index b283e545..00000000 --- a/js/app/directives/datepicker.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').directive('datepicker', function() { - 'use strict'; - return { - restrict: 'A', - scope: false, - link: function(scope, elm, attr) { - return elm.datepicker({ - onSelect: function(date, inst) { - scope['set' + attr.datepicker + 'day'](date); - return scope.$apply(); - }, - beforeShow: function(input, inst) { - var dp, marginLeft; - dp = $(inst).datepicker('widget'); - marginLeft = -Math.abs($(input).outerWidth() - dp.outerWidth()) / 2 + 'px'; - dp.css({ - 'margin-left': marginLeft - }); - $("div.ui-datepicker:before").css({ - 'left': 100 + 'px' - }); - return $('.hasDatepicker').datepicker("option", "firstDay", scope.settingsmodel.getById('various').startOfWeek); - }, - beforeShowDay: function(date) { - if (moment(date).startOf('day').diff(moment(scope.task[attr.datepicker], "YYYYMMDDTHHmmss").startOf('day'), 'days') === 0) { - return [1, "selected"]; - } else { - return [1, ""]; - } - }, - minDate: null - }); - } - }; -}); diff --git a/js/app/directives/occlickfocus.js b/js/app/directives/occlickfocus.js deleted file mode 100644 index 676c88a0..00000000 --- a/js/app/directives/occlickfocus.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').directive('ocClickFocus', [ - '$timeout', function($timeout) { - 'use strict'; - return function(scope, elm, attr) { - var options; - options = scope.$eval(attr.ocClickFocus); - if (angular.isDefined(options) && angular.isDefined(options.selector)) { - return elm.click(function() { - if (angular.isDefined(options.timeout)) { - return $timeout(function() { - return $(options.selector).focus(); - }, options.timeout); - } else { - return $(options.selector).focus(); - } - }); - } - }; - } -]); diff --git a/js/app/directives/timepicker.js b/js/app/directives/timepicker.js deleted file mode 100644 index 9e4e2511..00000000 --- a/js/app/directives/timepicker.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').directive('timepicker', function() { - 'use strict'; - return { - restrict: 'A', - link: function(scope, elm, attr) { - return elm.timepicker({ - onSelect: function(date, inst) { - scope['set' + attr.timepicker + 'time'](date); - return scope.$apply(); - }, - myPosition: 'center top', - atPosition: 'center bottom', - hourText: t('tasks', 'Hours'), - minuteText: t('tasks', 'Minutes') - }); - } - }; -}); diff --git a/js/app/filters/counterFormatter.js b/js/app/filters/counterFormatter.js deleted file mode 100644 index 65953a6c..00000000 --- a/js/app/filters/counterFormatter.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('counterFormatter', function() { - 'use strict'; - return function(count) { - switch (false) { - case count !== 0: - return ''; - case count < 999: - return '999+'; - default: - return count; - } - }; -}); diff --git a/js/app/filters/dateDetails.js b/js/app/filters/dateDetails.js deleted file mode 100644 index d770ec40..00000000 --- a/js/app/filters/dateDetails.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('dateDetails', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").locale(due.isDate ? 'details_allday' : 'details').calendar(); - } else { - return t('tasks', 'Set due date'); - } - }; -}); diff --git a/js/app/filters/dateDetailsShort.js b/js/app/filters/dateDetailsShort.js deleted file mode 100644 index cee9cfdf..00000000 --- a/js/app/filters/dateDetailsShort.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('dateDetailsShort', function() { - 'use strict'; - return function(reminder) { - if (moment(reminder, "YYYYMMDDTHHmmss").isValid()) { - return moment(reminder, "YYYYMMDDTHHmmss").locale('details_short').calendar(); - } else { - return ''; - } - }; -}); diff --git a/js/app/filters/dateFromNow.js b/js/app/filters/dateFromNow.js deleted file mode 100644 index a6b1e3fa..00000000 --- a/js/app/filters/dateFromNow.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('dateFromNow', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").fromNow(); - } else { - return ''; - } - }; -}); diff --git a/js/app/filters/dateTaskList.js b/js/app/filters/dateTaskList.js deleted file mode 100644 index 227d1b51..00000000 --- a/js/app/filters/dateTaskList.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('dateTaskList', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").locale('tasks').calendar(); - } else { - return ''; - } - }; -}); diff --git a/js/app/filters/dayTaskList.js b/js/app/filters/dayTaskList.js deleted file mode 100644 index 86af3a38..00000000 --- a/js/app/filters/dayTaskList.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('dayTaskList', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").locale('tasks').calendar(); - } else { - return ''; - } - }; -}); diff --git a/js/app/filters/percentDetails.js b/js/app/filters/percentDetails.js deleted file mode 100644 index 0e59f3cd..00000000 --- a/js/app/filters/percentDetails.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('percentDetails', function() { - 'use strict'; - return function(percent) { - return t('tasks', '%s %% completed').replace('%s', percent).replace('%%', '%'); - }; -}); diff --git a/js/app/filters/reminderDetails.js b/js/app/filters/reminderDetails.js deleted file mode 100644 index 72193c89..00000000 --- a/js/app/filters/reminderDetails.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('reminderDetails', function() { - 'use strict'; - return function(reminder, scope) { - function before(related) { - if (related === 'END') { - return ' ' + t('tasks', 'before end'); - } else { - return ' ' + t('tasks', 'before beginning'); - } - } - function after(related) { - if (related === 'END') { - return ' ' + t('tasks', 'after end'); - } else { - return ' ' + t('tasks', 'after beginning'); - } - } - function tokenName(reminder, token) { - if (+reminder.duration[token.id] === 1) { - return token.name; - } else { - return token.names; - } - } - var ds, time, token, _ref; - if (!(angular.isUndefined(reminder) || reminder === null)) { - if (reminder.type === 'DATE-TIME' && moment(reminder.date, "YYYYMMDDTHHmmss").isValid()) { - return moment(reminder.date, "YYYYMMDDTHHmmss").locale('reminder').calendar(); - } else if (reminder.type === 'DURATION' && reminder.duration) { - ds = t('tasks', 'Remind me'); - _ref = scope.durations; - for (var _i = 0, _len = _ref.length; _i < _len; _i++) { - token = _ref[_i]; - if (+reminder.duration[token.id]) { - time = 1; - ds += ' ' + reminder.duration[token.id] + ' '; - ds += tokenName(reminder, token); - } - } - if (!time) { - if (reminder.duration.params.related === 'END') { - ds += ' ' + t('tasks', 'at the end'); - } else { - ds += ' ' + t('tasks', 'at the beginning'); - } - } else { - if (reminder.duration.params.invert) { - ds += before(reminder.duration.params.related); - } else { - ds += after(reminder.duration.params.related); - } - } - return ds; - } else { - return t('tasks', 'Remind me'); - } - } else { - return t('tasks', 'Remind me'); - } - }; -}); diff --git a/js/app/filters/startDetails.js b/js/app/filters/startDetails.js deleted file mode 100644 index 869363a7..00000000 --- a/js/app/filters/startDetails.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('startDetails', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").locale(due.isDate ? 'start_allday' : 'start').calendar(); - } else { - return t('tasks', 'Set start date'); - } - }; -}); diff --git a/js/app/filters/timeTaskList.js b/js/app/filters/timeTaskList.js deleted file mode 100644 index 086f91ac..00000000 --- a/js/app/filters/timeTaskList.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').filter('timeTaskList', function() { - 'use strict'; - return function(due) { - if (moment(due, "YYYYMMDDTHHmmss").isValid()) { - return moment(due, "YYYYMMDDTHHmmss").format('HH:mm'); - } else { - return ''; - } - }; -}); diff --git a/js/app/services/icalfactory.js b/js/app/init.js similarity index 59% rename from js/app/services/icalfactory.js rename to js/app/init.js index fd91cf3a..7339a9a8 100644 --- a/js/app/services/icalfactory.js +++ b/js/app/init.js @@ -1,11 +1,7 @@ /** * Nextcloud - Tasks * - * @author Raghu Nayyar - * @author Georg Ehrke * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke * @copyright 2018 Raimund Schlüßler * * This library is free software; you can redistribute it and/or @@ -22,21 +18,36 @@ * License along with this library. If not, see . * */ +'use strict'; -angular.module('Tasks').service('ICalFactory', [ - function() { - 'use strict'; +import {App} from "./app"; - // creates a new ICAL root element with a product id property - return { - new: function() { - var root = new ICAL.Component(['vcalendar', [], []]); +if (!OCA.Tasks) { + /** + * @namespace OCA.Tasks + */ + OCA.Tasks = {}; +} - var version = angular.element('#app').attr('data-appVersion'); - root.updatePropertyWithValue('prodid', '-//Nextcloud Tasks v' + version); +/** +* @namespace +*/ - return root; +$(document).ready(function () { + OCA.Tasks.App = new App(); + OCA.Tasks.App.start(); + + var version = OC.config.version.split('.'); + + if (version[0] >= 14) { + OC.Search = new OCA.Search(OCA.Tasks.App.Vue.filter, OCA.Tasks.App.Vue.cleanSearch); + } else { + OCA.Tasks.App.Search = { + attach: function (search) { + search.setFilter('tasks', OCA.Tasks.App.Vue.filter); } }; + + OC.Plugins.register('OCA.Search', OCA.Tasks.App.Search); } -]); +}); diff --git a/js/app/services/businesslayer/listsbusinesslayer.js b/js/app/services/businesslayer/listsbusinesslayer.js deleted file mode 100644 index f1e00e5a..00000000 --- a/js/app/services/businesslayer/listsbusinesslayer.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('ListsBusinessLayer', [ - 'ListsModel', 'Persistence', 'TasksBusinessLayer', 'CalendarService', function(ListsModel, Persistence, TasksBusinessLayer, CalendarService) { - 'use strict'; - var ListsBusinessLayer; - ListsBusinessLayer = (function() { - function ListsBusinessLayer(_$listsmodel, _persistence, _$tasksbusinesslayer, _$calendarservice) { - this._$listsmodel = _$listsmodel; - this._persistence = _persistence; - this._$tasksbusinesslayer = _$tasksbusinesslayer; - this._$calendarservice = _$calendarservice; - } - - ListsBusinessLayer.prototype.init = function() { - return this._$calendarservice.getAll().then(function(calendars) { - var calendar, _i, _len, _results; - _results = []; - for (_i = 0, _len = calendars.length; _i < _len; _i++) { - calendar = calendars[_i]; - ListsModel.add(calendar); - _results.push(TasksBusinessLayer.getAll(calendar)); - } - return _results; - }); - }; - - ListsBusinessLayer.prototype.add = function(calendar, color) { - return this._$calendarservice.create(calendar, color, ['vtodo']).then(function(calendar) { - ListsModel.add(calendar); - return calendar; - }); - }; - - ListsBusinessLayer.prototype["delete"] = function(calendar) { - return this._$calendarservice["delete"](calendar).then(function() { - return ListsModel["delete"](calendar); - }); - }; - - ListsBusinessLayer.prototype.rename = function(calendar) { - this._$calendarservice.update(calendar).then(function(calendar) { - calendar.dropPreviousState(); - }); - }; - - return ListsBusinessLayer; - - })(); - return new ListsBusinessLayer(ListsModel, Persistence, TasksBusinessLayer, CalendarService); - } -]); diff --git a/js/app/services/businesslayer/settingsbusinesslayer.js b/js/app/services/businesslayer/settingsbusinesslayer.js deleted file mode 100644 index 811c276b..00000000 --- a/js/app/services/businesslayer/settingsbusinesslayer.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('SettingsBusinessLayer', [ - 'Persistence', 'SettingsModel', function(Persistence, SettingsModel) { - 'use strict'; - var SettingsBusinessLayer = (function() { - function SettingsBusinessLayer(_persistence, _$settingsmodel) { - this._persistence = _persistence; - this._$settingsmodel = _$settingsmodel; - } - - SettingsBusinessLayer.prototype.updateModel = function() { - var success, _this = this; - success = function() {}; - return this._persistence.getCollections(success, true); - }; - - SettingsBusinessLayer.prototype.setVisibility = function(collectionID, visibility) { - return this._persistence.setVisibility(collectionID, visibility); - }; - - SettingsBusinessLayer.prototype.toggle = function(type, setting) { - this._$settingsmodel.toggle(type, setting); - var value = this._$settingsmodel.getById(type)[setting]; - return this._persistence.setting(type, setting, +value); - }; - - SettingsBusinessLayer.prototype.set = function(type, setting, value) { - return this._persistence.setting(type, setting, value); - }; - - return SettingsBusinessLayer; - - })(); - return new SettingsBusinessLayer(Persistence, SettingsModel); - } -]); diff --git a/js/app/services/businesslayer/tasksbusinesslayer.js b/js/app/services/businesslayer/tasksbusinesslayer.js deleted file mode 100644 index dd05af11..00000000 --- a/js/app/services/businesslayer/tasksbusinesslayer.js +++ /dev/null @@ -1,599 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('TasksBusinessLayer', [ - 'TasksModel', 'Persistence', 'VTodoService', 'VTodo', '$timeout', - function(TasksModel, Persistence, VTodoService, VTodo, $timeout) { - 'use strict'; - var TasksBusinessLayer; - TasksBusinessLayer = (function() { - function TasksBusinessLayer(_$tasksmodel, _persistence, _$vtodoservice, _$vtodo, $timeout) { - this._$tasksmodel = _$tasksmodel; - this._persistence = _persistence; - this._$vtodoservice = _$vtodoservice; - } - - TasksBusinessLayer.prototype.getAll = function(calendar, completed, parent) { - return this._$vtodoservice.getAll(calendar, completed, parent).then(function(tasks) { - var task, _i, _len, _results; - _results = []; - for (_i = 0, _len = tasks.length; _i < _len; _i++) { - task = tasks[_i]; - var vTodo = new VTodo(task.calendar, task.properties, task.uri); - _results.push(TasksModel.ad(vTodo)); - } - return _results; - }); - }; - - TasksBusinessLayer.prototype.add = function(task) { - return this._$vtodoservice.create(task.calendar, task.data).then(function(task) { - var vTodo = new VTodo(task.calendar, task.properties, task.uri); - TasksModel.ad(vTodo); - return vTodo; - }); - }; - - TasksBusinessLayer.prototype.getTask = function(calendar, uri) { - return this._$vtodoservice.get(calendar, uri).then(function(task) { - TasksModel.ad(task); - return task; - }); - }; - - TasksBusinessLayer.prototype.setPriority = function(task, priority) { - if (task.calendar.writable) { - task.priority = priority; - this.doUpdate(task); - } - }; - - TasksBusinessLayer.prototype.setPercentComplete = function(task, percentComplete) { - if (task.calendar.writable) { - if (percentComplete < 100) { - this.uncompleteParents(task.related); - } else { - this.completeChildren(task); - } - task.complete = percentComplete; - this.triggerUpdate(task); - } - }; - - TasksBusinessLayer.prototype.triggerUpdate = function(task, duration) { - if (!duration) { - duration = 1000; - } - if (task.timers.update) { - $timeout.cancel(task.timers.update); - } - task.timers.update = $timeout(function(task) { - VTodoService.update(task); - }, duration, true, task); - }; - - TasksBusinessLayer.prototype.doUpdate = function(task) { - return this._$vtodoservice.update(task); - }; - - TasksBusinessLayer.prototype.completeChildren = function(task) { - var child, _i, _len; - var children = this._$tasksmodel.getChildren(task); - var _results = []; - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - _results.push(this.setPercentComplete(child, 100)); - } - return _results; - }; - - TasksBusinessLayer.prototype.uncompleteParents = function(uid) { - if (uid) { - var parent = this._$tasksmodel.getByUid(uid); - if (parent.completed) { - return this.setPercentComplete(parent, 0); - } - } - }; - - TasksBusinessLayer.prototype.setHideSubtasks = function(task, hide) { - task.hideSubtasks = hide; - if (task.calendar.writable) { - this.doUpdate(task); - } - }; - - TasksBusinessLayer.prototype.setHideCompletedSubtasks = function(task, hide) { - task.hideCompletedSubtasks = hide; - if (task.calendar.writable) { - this.doUpdate(task); - } - }; - - TasksBusinessLayer.prototype.deleteTask = function(task) { - var child, children, _i, _len; - children = this._$tasksmodel.getChildren(task); - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - this.deleteTask(child); - } - return this._$vtodoservice["delete"](task).then(function() { - return TasksModel["delete"](task); - }); - }; - - TasksBusinessLayer.prototype.momentToICALTime = function(moment, asDate) { - if(asDate) { - return ICAL.Time.fromDateString(moment.format('YYYY-MM-DD')); - } else { - return ICAL.Time.fromDateTimeString(moment.format('YYYY-MM-DDTHH:mm:ss')); - } - }; - - TasksBusinessLayer.prototype.initDueDate = function(task) { - var start = moment(task.start, "YYYY-MM-DDTHH:mm:ss"); - var due = moment(task.due, "YYYY-MM-DDTHH:mm:ss"); - if (!due.isValid()) { - var reference = start.isAfter() ? start : moment(); - if(task.allDay) { - reference.startOf('day').add(1, 'd'); - } else { - reference.startOf('hour').add(1, 'h'); - } - return this.setDue(task, reference, 'all'); - } - }; - - TasksBusinessLayer.prototype.setDue = function(task, date, type) { - if (type === null) { - type = 'day'; - } - var allDay = task.allDay; - var start = moment(task.start, "YYYY-MM-DDTHH:mm:ss"); - var olddue = moment(task.due, "YYYY-MM-DDTHH:mm:ss"); - var due = olddue.clone(); - if (type === 'day') { - if (moment(due).isValid()) { - due.year(date.year()).month(date.month()).date(date.date()); - } else { - due = date.add(12, 'h'); - } - } else if (type === 'time') { - if (moment(due).isValid()) { - due.hour(date.hour()).minute(date.minute()); - } else { - due = date; - } - } else if (type === 'all') { - due = date; - } else { - return; - } - if (due.isBefore(start) || due.isSame(start)) { - start.subtract(olddue.diff(due), 'ms'); - task.start = this.momentToICALTime(start, allDay); - } - task.due = this.momentToICALTime(due, allDay); - // this.checkReminderDate(task); - this.doUpdate(task); - }; - - TasksBusinessLayer.prototype.deleteDueDate = function(task) { - // var reminder = task.reminder; - // if (reminder !== null && reminder.type === 'DURATION' && reminder.duration.params.related === 'END') { - // this.deleteReminderDate(task); - // } - task.due = null; - this.doUpdate(task); - }; - - TasksBusinessLayer.prototype.initStartDate = function(task) { - var start = moment(task.start, "YYYY-MM-DDTHH:mm:ss"); - var due = moment(task.due, "YYYY-MM-DDTHH:mm:ss"); - if (!start.isValid()) { - var reference = moment().add(1, 'h'); - if (due.isBefore(reference)) { - reference = due.subtract(1, 'm'); - } - reference.startOf(task.allDay ? 'day' : 'hour'); - return this.setStart(task, reference, 'all'); - } - }; - - TasksBusinessLayer.prototype.setStart = function(task, date, type) { - if (type === null) { - type = 'day'; - } - var allDay = task.allDay; - var due = moment(task.due, "YYYY-MM-DDTHH:mm:ss"); - var oldstart = moment(task.start, "YYYY-MM-DDTHH:mm:ss"); - var start = oldstart.clone(); - if (type === 'day') { - if (moment(start).isValid()) { - start.year(date.year()).month(date.month()).date(date.date()); - } else { - start = date.add(12, 'h'); - } - } else if (type === 'time') { - if (moment(start).isValid()) { - start.hour(date.hour()).minute(date.minute()); - } else { - start = date; - } - } else if (type === 'all') { - start = date; - } else { - return; - } - if(start.isAfter(due) || start.isSame(due)) { - due.add(start.diff(oldstart), 'ms'); - task.due = this.momentToICALTime(due, allDay); - } - task.start = this.momentToICALTime(start, allDay); - // this.checkReminderDate(taskID); - this.doUpdate(task); - }; - - TasksBusinessLayer.prototype.deleteStartDate = function(task) { - // var reminder = task.reminder; - // if (reminder !== null && reminder.type === 'DURATION' && reminder.duration.params.related === 'START') { - // this.deleteReminderDate(task); - // } - task.start = null; - this.doUpdate(task); - }; - - TasksBusinessLayer.prototype.setAllDay = function(task, allDay) { - task.allDay = allDay; - if (allDay) { - var due = moment(task.due, "YYYY-MM-DDTHH:mm:ss"); - var start = moment(task.start, "YYYY-MM-DDTHH:mm:ss"); - if(start.isAfter(due) || start.isSame(due)) { - start = moment(due).subtract(1, 'day'); - task.start = this.momentToICALTime(start, allDay); - } - } - this.doUpdate(task); - }; - - TasksBusinessLayer.prototype.initReminder = function(taskID) { - var p, task; - if (!this.checkReminderDate(taskID)) { - task = this._$tasksmodel.getById(taskID); - task.reminder = { - type: 'DURATION', - action: 'DISPLAY', - duration: { - token: 'week', - week: 0, - day: 0, - hour: 0, - minute: 0, - second: 0, - params: { - invert: true - } - } - }; - if (moment(task.start, "YYYYMMDDTHHmmss").isValid()) { - p = task.reminder.duration.params; - p.related = 'START'; - p.id = '10'; - } else if (moment(task.due, "YYYYMMDDTHHmmss").isValid()) { - p = task.reminder.duration.params; - p.related = 'END'; - p.id = '11'; - } else { - task.reminder.type = 'DATE-TIME'; - task.reminder.date = moment().startOf('hour').add(1, 'h').format('YYYYMMDDTHHmmss'); - } - return this.setReminder(taskID); - } - }; - - TasksBusinessLayer.prototype.setReminderDate = function(taskID, date, type) { - var newreminder, reminder, reminderdate; - if (type === null) { - type = 'day'; - } - reminder = this._$tasksmodel.getById(taskID).reminder; - newreminder = { - type: 'DATE-TIME', - action: 'DISPLAY', - duration: null - }; - if (type === 'day') { - if (this.checkReminderDate(taskID) || reminder === null) { - reminderdate = moment(reminder.date, "YYYYMMDDTHHmmss"); - newreminder.action = reminder.action; - if (reminderdate.isValid() && reminder.type === 'DATE-TIME') { - reminderdate.year(date.year()).month(date.month()).date(date.date()); - } else { - reminderdate = date.add(12, 'h'); - } - } else { - reminderdate = date.add(12, 'h'); - } - } else if (type === 'time') { - if (this.checkReminderDate(taskID) || reminder === null) { - reminderdate = moment(reminder.date, "YYYYMMDDTHHmmss"); - newreminder.action = reminder.action; - if (reminderdate.isValid() && reminder.type === 'DATE-TIME') { - reminderdate.hour(date.hour()).minute(date.minute()); - } else { - reminderdate = date; - } - } else { - reminderdate = date; - } - } else { - return; - } - newreminder.date = reminderdate.format('YYYYMMDDTHHmmss'); - this._$tasksmodel.setReminder(taskID, newreminder); - return this._persistence.setReminder(taskID, newreminder); - }; - - TasksBusinessLayer.prototype.setReminder = function(taskID) { - var reminder; - if (this.checkReminderDate(taskID)) { - reminder = this._$tasksmodel.getById(taskID).reminder; - return this._persistence.setReminder(taskID, reminder); - } - }; - - TasksBusinessLayer.prototype.checkReminderDate = function(taskID) { - var d, date, duration, rel, related, reminder, seg, task, token; - task = this._$tasksmodel.getById(taskID); - reminder = task.reminder; - if (reminder !== null && reminder.type === 'DURATION') { - if (!reminder.duration) { - return false; - } else if (reminder.duration.params.related === 'START') { - token = 'start'; - } else if (reminder.duration.params.related === 'END') { - token = 'due'; - } else { - return false; - } - date = moment(task[token], "YYYYMMDDTHHmmss"); - duration = reminder.duration; - d = { - w: duration.week, - d: duration.day, - h: duration.hour, - m: duration.minute, - s: duration.second - }; - if (duration.params.invert) { - date = date.subtract(d); - } else { - date = date.add(d); - } - task.reminder.date = date.format('YYYYMMDDTHHmmss'); - } else if (reminder !== null && reminder.type === 'DATE-TIME') { - duration = reminder.duration; - date = moment(reminder.date, "YYYYMMDDTHHmmss"); - if (!date.isValid()) { - return false; - } - if (duration) { - if (duration.params.related === 'START') { - related = moment(task.start, "YYYYMMDDTHHmmss"); - } else { - related = moment(task.due, "YYYYMMDDTHHmmss"); - } - seg = this.secondsToSegments(date.diff(related, 'seconds')); - duration.params.invert = seg.invert; - duration.token = 'week'; - duration.week = seg.week; - duration.day = seg.day; - duration.hour = seg.hour; - duration.minute = seg.minute; - duration.second = seg.second; - } else { - if (task.start) { - related = moment(task.start, "YYYYMMDDTHHmmss"); - rel = 'START'; - d = 0; - } else if (task.due) { - related = moment(task.due, "YYYYMMDDTHHmmss"); - rel = 'END'; - d = 1; - } else { - return true; - } - seg = this.secondsToSegments(date.diff(related, 'seconds')); - reminder.duration = { - token: 'week', - params: { - related: rel, - invert: seg.invert, - id: +seg.invert + '' + d - }, - week: seg.week, - day: seg.day, - hour: seg.hour, - minute: seg.minute, - second: seg.second - }; - } - } else { - return false; - } - return true; - }; - - TasksBusinessLayer.prototype.secondsToSegments = function(s) { - var d, h, i, m, w; - if (s < 0) { - s *= -1; - i = true; - } else { - i = false; - } - w = Math.floor(s / 604800); - s -= w * 604800; - d = Math.floor(s / 86400); - s -= d * 86400; - h = Math.floor(s / 3600); - s -= h * 3600; - m = Math.floor(s / 60); - s -= m * 60; - return { - week: w, - day: d, - hour: h, - minute: m, - second: s, - invert: i - }; - }; - - TasksBusinessLayer.prototype.deleteReminderDate = function(taskID) { - this._$tasksmodel.setReminder(taskID, null); - return this._persistence.setReminder(taskID, false); - }; - - TasksBusinessLayer.prototype.changeCalendar = function(task, newCalendar) { - if(task.calendar !== newCalendar && newCalendar.writable) { - var newTask = angular.copy(task); - newTask.calendar = newCalendar; - if (!TasksModel.hasNoParent(newTask)) { - var parent = TasksModel.getByUid(newTask.related); - if (parent.calendar.uri !== newTask.calendar.uri) { - newTask.related = null; - TasksBusinessLayer.prototype.setPercentComplete(newTask, 0); - } - } - return VTodoService.create(newCalendar, newTask.data).then(function(newVTodo) { - var vTodo = new VTodo(newVTodo.calendar, newVTodo.properties, newVTodo.uri); - TasksModel.ad(vTodo); - return VTodoService["delete"](task).then(function() { - TasksModel["delete"](task); - var queries = []; - var children = TasksModel.getChildren(newTask); - var _i, _len, child; - for (_i = 0, _len = children.length; _i < _len; _i++) { - child = children[_i]; - if (child.calendar.uri !== newTask.calendar.uri) { - queries.push(TasksBusinessLayer.prototype.changeCalendar(child, newTask.calendar)); - } - } - return Promise.all(queries); - }); - }); - } else { - return Promise.resolve(true); - } - }; - - // called from outside - TasksBusinessLayer.prototype.changeCollection = function(taskID, collectionID) { - var task = this._$tasksmodel.getById(taskID); - switch (collectionID) { - case 'starred': - task.priority = 9; - return this.doUpdate(task); - case 'completed': - return this.setPercentComplete(task, 100); - case 'uncompleted': - if (task.completed) { - return this.setPercentComplete(task, 0); - } else { - return false; - } - break; - case 'today': - return this.setDue(task, moment().startOf('day').add(12, 'h'), 'all'); - case 'week': - case 'all': - return false; - default: - return false; - } - }; - - TasksBusinessLayer.prototype.changeParent = function(task, parent) { - if (parent.calendar.writable) { - task.related = parent.uid; - parent.hideSubtasks = 0; - if (parent.completed && !task.completed) { - this.setPercentComplete(parent, 0); - } else { - this.doUpdate(parent); - } - if (parent.calendar.uri !== task.calendar.uri) { - this.changeCalendar(task, parent.calendar); - } else { - this.doUpdate(task); - } - } - }; - - TasksBusinessLayer.prototype.makeRootTask = function(task, newCalendar, collectionID) { - if (newCalendar.writable) { - var requests = []; - task.related = null; - if (collectionID !== "completed" && task.completed) { - task.complete = 0; - } - requests.push(this.changeCollection(task.uri, collectionID)); - if (task.calendar !== newCalendar) { - requests.push(this.changeCalendar(task, newCalendar)); - } else { - requests.push(this.doUpdate(task)); - } - return requests; - } - }; - - TasksBusinessLayer.prototype.addComment = function(comment, onSuccess, onFailure) { - var success, - _this = this; - if (!onSuccess) { - onSuccess = function() {}; - } - if (!onFailure) { - onFailure = function() {}; - } - this._$tasksmodel.addComment(comment); - success = function(response) { - if (response.status === 'error') { - return onFailure(); - } else { - return onSuccess(response.data); - } - }; - return this._persistence.addComment(comment, success); - }; - - TasksBusinessLayer.prototype.deleteComment = function(taskID, commentID) { - this._$tasksmodel.deleteComment(taskID, commentID); - return this._persistence.deleteComment(taskID, commentID); - }; - - return TasksBusinessLayer; - - })(); - return new TasksBusinessLayer(TasksModel, Persistence, VTodoService, VTodo, $timeout); - } -]); diff --git a/js/app/services/calendarservice.js b/js/app/services/calendarservice.js deleted file mode 100644 index 80de38f0..00000000 --- a/js/app/services/calendarservice.js +++ /dev/null @@ -1,461 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').service('CalendarService', ['DavClient', 'Calendar', function(DavClient, Calendar){ - 'use strict'; - - var _this = this; - - this._CALENDAR_HOME = null; - - this._currentUserPrincipal = null; - - this._takenUrls = []; - - this._PROPERTIES = [ - '{' + DavClient.NS_DAV + '}displayname', - '{' + DavClient.NS_IETF + '}calendar-description', - '{' + DavClient.NS_IETF + '}calendar-timezone', - '{' + DavClient.NS_APPLE + '}calendar-order', - '{' + DavClient.NS_APPLE + '}calendar-color', - '{' + DavClient.NS_IETF + '}supported-calendar-component-set', - '{' + DavClient.NS_OWNCLOUD + '}calendar-enabled', - '{' + DavClient.NS_DAV + '}acl', - '{' + DavClient.NS_DAV + '}owner', - '{' + DavClient.NS_OWNCLOUD + '}invite' - ]; - - function discoverHome(callback) { - return DavClient.propFind(DavClient.buildUrl(OC.linkToRemoteBase('dav')), ['{' + DavClient.NS_DAV + '}current-user-principal'], 0, {'requesttoken': OC.requestToken}).then(function(response) { - if (!DavClient.wasRequestSuccessful(response.status)) { - throw "CalDAV client could not be initialized - Querying current-user-principal failed"; - } - - if (response.body.propStat.length < 1) { - return; - } - var props = response.body.propStat[0].properties; - _this._currentUserPrincipal = props['{' + DavClient.NS_DAV + '}current-user-principal'][0].textContent; - - return DavClient.propFind(DavClient.buildUrl(_this._currentUserPrincipal), ['{' + DavClient.NS_IETF + '}calendar-home-set'], 0, {'requesttoken': OC.requestToken}).then(function (response) { - if (!DavClient.wasRequestSuccessful(response.status)) { - throw "CalDAV client could not be initialized - Querying calendar-home-set failed"; - } - - if (response.body.propStat.length < 1) { - return; - } - var props = response.body.propStat[0].properties; - _this._CALENDAR_HOME = props['{' + DavClient.NS_IETF + '}calendar-home-set'][0].textContent; - - return callback(); - }); - }); - } - - function getResponseCodeFromHTTPResponse(t) { - return parseInt(t.split(' ')[1]); - } - - this.getAll = function() { - if (this._CALENDAR_HOME === null) { - return discoverHome(function() { - return _this.getAll(); - }); - } - - var prom = DavClient.propFind(DavClient.buildUrl(this._CALENDAR_HOME), this._PROPERTIES, 1, {'requesttoken': OC.requestToken}).then(function(response) { - var calendars = []; - - if (!DavClient.wasRequestSuccessful(response.status)) { - throw "CalDAV client could not be initialized - Querying calendars failed"; - } - - for (var i = 0; i < response.body.length; i++) { - var body = response.body[i]; - if (body.propStat.length < 1) { - continue; - } - - _this._takenUrls.push(body.href); - - var responseCode = getResponseCodeFromHTTPResponse(body.propStat[0].status); - if (!DavClient.wasRequestSuccessful(responseCode)) { - continue; - } - - var doesSupportVTodo = false; - var components = body.propStat[0].properties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; - if (components) { - for (var j=0; j < components.length; j++) { - var name = components[j].attributes.getNamedItem('name').textContent.toLowerCase(); - if (name === 'vtodo') { - doesSupportVTodo = true; - } - } - } - - if (!doesSupportVTodo) { - continue; - } - - _this._getACLFromResponse(body); - - var uri = body.href.substr(_this._CALENDAR_HOME.length).replace(/[^\w\-]+/g, ''); - - var calendar = new Calendar(body.href, body.propStat[0].properties, uri); - calendars.push(calendar); - } - - return calendars; - }); - return prom; - }; - - this.get = function(url) { - if (this._CALENDAR_HOME === null) { - return discoverHome(function() { - return _this.get(url); - }); - } - - return DavClient.propFind(DavClient.buildUrl(url), this._PROPERTIES, 0, {'requesttoken': OC.requestToken}).then(function(response) { - var body = response.body; - if (body.propStat.length < 1) { - //TODO - something went wrong - return; - } - - var responseCode = getResponseCodeFromHTTPResponse(body.propStat[0].status); - if (!DavClient.wasRequestSuccessful(responseCode)) { - //TODO - something went wrong - return; - } - - _this._getACLFromResponse(body); - - var uri = body.href.substr(_this._CALENDAR_HOME.length).replace(/[^\w\-]+/g, ''); - - return new Calendar(body.href, body.propStat[0].properties, uri); - }); - }; - - this.create = function(name, color, components) { - if (this._CALENDAR_HOME === null) { - return discoverHome(function() { - return _this.create(name, color); - }); - } - - if (typeof components === 'undefined') { - components = ['vtodo']; - } - - var xmlDoc = document.implementation.createDocument('', '', null); - var cMkcalendar = xmlDoc.createElement('c:mkcalendar'); - cMkcalendar.setAttribute('xmlns:c', 'urn:ietf:params:xml:ns:caldav'); - cMkcalendar.setAttribute('xmlns:d', 'DAV:'); - cMkcalendar.setAttribute('xmlns:a', 'http://apple.com/ns/ical/'); - cMkcalendar.setAttribute('xmlns:o', 'http://owncloud.org/ns'); - xmlDoc.appendChild(cMkcalendar); - - var dSet = xmlDoc.createElement('d:set'); - cMkcalendar.appendChild(dSet); - - var dProp = xmlDoc.createElement('d:prop'); - dSet.appendChild(dProp); - - dProp.appendChild(this._createXMLForProperty(xmlDoc, 'displayname', name)); - dProp.appendChild(this._createXMLForProperty(xmlDoc, 'enabled', true)); - dProp.appendChild(this._createXMLForProperty(xmlDoc, 'color', color)); - dProp.appendChild(this._createXMLForProperty(xmlDoc, 'components', components)); - - var body = cMkcalendar.outerHTML; - - var uri = this._suggestUri(name); - var url = this._CALENDAR_HOME + uri + '/'; - var headers = { - 'Content-Type' : 'application/xml; charset=utf-8', - 'requesttoken' : OC.requestToken - }; - - return DavClient.request('MKCALENDAR', url, headers, body).then(function(response) { - if (response.status === 201) { - _this._takenUrls.push(url); - return _this.get(url).then(function(calendar) { - calendar.enabled = true; - return _this.update(calendar); - }); - } - }); - }; - - this.update = function(calendar) { - var xmlDoc = document.implementation.createDocument('', '', null); - var dPropUpdate = xmlDoc.createElement('d:propertyupdate'); - dPropUpdate.setAttribute('xmlns:c', 'urn:ietf:params:xml:ns:caldav'); - dPropUpdate.setAttribute('xmlns:d', 'DAV:'); - dPropUpdate.setAttribute('xmlns:a', 'http://apple.com/ns/ical/'); - dPropUpdate.setAttribute('xmlns:o', 'http://owncloud.org/ns'); - xmlDoc.appendChild(dPropUpdate); - - var dSet = xmlDoc.createElement('d:set'); - dPropUpdate.appendChild(dSet); - - var dProp = xmlDoc.createElement('d:prop'); - dSet.appendChild(dProp); - - var updatedProperties = calendar.updatedProperties; - calendar.resetUpdatedProperties(); - for (var i=0; i < updatedProperties.length; i++) { - dProp.appendChild(this._createXMLForProperty( - xmlDoc, - updatedProperties[i], - calendar[updatedProperties[i]] - )); - } - - var url = calendar.url; - var body = dPropUpdate.outerHTML; - var headers = { - 'Content-Type' : 'application/xml; charset=utf-8', - 'requesttoken' : OC.requestToken - }; - - return DavClient.request('PROPPATCH', url, headers, body).then(function(response) { - return calendar; - }); - }; - - this.delete = function(calendar) { - return DavClient.request('DELETE', calendar.url, {'requesttoken': OC.requestToken}, '').then(function(response) { - if (response.status === 204) { - return true; - } else { - // TODO - handle error case - return false; - } - }); - }; - - this.share = function(calendar, shareType, shareWith, writable, existingShare) { - var xmlDoc = document.implementation.createDocument('', '', null); - var oShare = xmlDoc.createElement('o:share'); - oShare.setAttribute('xmlns:d', 'DAV:'); - oShare.setAttribute('xmlns:o', 'http://owncloud.org/ns'); - xmlDoc.appendChild(oShare); - - var oSet = xmlDoc.createElement('o:set'); - oShare.appendChild(oSet); - - var dHref = xmlDoc.createElement('d:href'); - if (shareType === OC.Share.SHARE_TYPE_USER) { - dHref.textContent = 'principal:principals/users/'; - } else if (shareType === OC.Share.SHARE_TYPE_GROUP) { - dHref.textContent = 'principal:principals/groups/'; - } - dHref.textContent += shareWith; - oSet.appendChild(dHref); - - var oSummary = xmlDoc.createElement('o:summary'); - oSummary.textContent = t('calendar', '{calendar} shared by {owner}', { - calendar: calendar.displayname, - owner: calendar.owner - }); - oSet.appendChild(oSummary); - - if (writable) { - var oRW = xmlDoc.createElement('o:read-write'); - oSet.appendChild(oRW); - } - - var headers = { - 'Content-Type' : 'application/xml; charset=utf-8', - requesttoken : oc_requesttoken - }; - var body = oShare.outerHTML; - return DavClient.request('POST', calendar.url, headers, body).then(function(response) { - if (response.status === 200) { - if (!existingShare) { - if (shareType === OC.Share.SHARE_TYPE_USER) { - calendar.sharedWith.users.push({ - id: shareWith, - displayname: shareWith, - writable: writable - }); - } else if (shareType === OC.Share.SHARE_TYPE_GROUP) { - calendar.sharedWith.groups.push({ - id: shareWith, - displayname: shareWith, - writable: writable - }); - } - } - } - }); - }; - - this.unshare = function(calendar, shareType, shareWith) { - var xmlDoc = document.implementation.createDocument('', '', null); - var oShare = xmlDoc.createElement('o:share'); - oShare.setAttribute('xmlns:d', 'DAV:'); - oShare.setAttribute('xmlns:o', 'http://owncloud.org/ns'); - xmlDoc.appendChild(oShare); - - var oRemove = xmlDoc.createElement('o:remove'); - oShare.appendChild(oRemove); - - var dHref = xmlDoc.createElement('d:href'); - if (shareType === OC.Share.SHARE_TYPE_USER) { - dHref.textContent = 'principal:principals/users/'; - } else if (shareType === OC.Share.SHARE_TYPE_GROUP) { - dHref.textContent = 'principal:principals/groups/'; - } - dHref.textContent += shareWith; - oRemove.appendChild(dHref); - - var headers = { - 'Content-Type' : 'application/xml; charset=utf-8', - requesttoken: oc_requesttoken - }; - var body = oShare.outerHTML; - return DavClient.request('POST', calendar.url, headers, body).then(function(response) { - if (response.status === 200) { - if (shareType === OC.Share.SHARE_TYPE_USER) { - calendar.sharedWith.users = calendar.sharedWith.users.filter(function(user) { - return user.id !== shareWith; - }); - } else if (shareType === OC.Share.SHARE_TYPE_GROUP) { - calendar.sharedWith.groups = calendar.sharedWith.groups.filter(function(groups) { - return groups.id !== shareWith; - }); - } - //todo - remove entry from calendar object - return true; - } else { - return false; - } - }); - }; - - this._createXMLForProperty = function(xmlDoc, propName, value) { - switch(propName) { - case 'enabled': - var oEnabled = xmlDoc.createElement('o:calendar-enabled'); - oEnabled.textContent = value ? '1' : '0'; - return oEnabled; - - case 'displayname': - var dDisplayname = xmlDoc.createElement('d:displayname'); - dDisplayname.textContent = value; - return dDisplayname; - - case 'order': - var aOrder = xmlDoc.createElement('a:calendar-color'); - aOrder.textContent = value; - return aOrder; - - case 'color': - var aColor = xmlDoc.createElement('a:calendar-color'); - aColor.textContent = value; - return aColor; - - case 'components': - var cComponents = xmlDoc.createElement('c:supported-calendar-component-set'); - for (var i=0; i < value.length; i++) { - var cComp = xmlDoc.createElement('c:comp'); - cComp.setAttribute('name', value[i].toUpperCase()); - cComponents.appendChild(cComp); - } - return cComponents; - } - }; - - this._getACLFromResponse = function(body) { - var canWrite = false; - var acl = body.propStat[0].properties['{' + DavClient.NS_DAV + '}acl']; - if (acl) { - for (var k=0; k < acl.length; k++) { - var href = acl[k].getElementsByTagNameNS('DAV:', 'href'); - if (href.length === 0) { - continue; - } - href = href[0].textContent; - if (href !== _this._currentUserPrincipal) { - continue; - } - var writeNode = acl[k].getElementsByTagNameNS('DAV:', 'write'); - if (writeNode.length > 0) { - canWrite = true; - } - } - } - body.propStat[0].properties.canWrite = canWrite; - }; - - this._isUriAlreadyTaken = function(uri) { - return (this._takenUrls.indexOf(this._CALENDAR_HOME + uri + '/') !== -1); - }; - - this._suggestUri = function(displayname) { - var uri = displayname.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, ''); // Trim - from end of text - - if (!this._isUriAlreadyTaken(uri)) { - return uri; - } - - if (uri.indexOf('-') === -1) { - uri = uri + '-1'; - if (!this._isUriAlreadyTaken(uri)) { - return uri; - } - } - - while (this._isUriAlreadyTaken(uri)) { - var positionLastDash = uri.lastIndexOf('-'); - var firstPart = uri.substr(0, positionLastDash); - var lastPart = uri.substr(positionLastDash + 1); - - if (lastPart.match(/^\d+$/)) { - lastPart = parseInt(lastPart); - lastPart++; - - uri = firstPart + '-' + lastPart; - } else if (lastPart === '') { - uri = uri + '1'; - } else { - uri = uri = '-1'; - } - } - - return uri; - }; - -}]); diff --git a/js/app/services/davclient.js b/js/app/services/davclient.js deleted file mode 100644 index bc13a7f1..00000000 --- a/js/app/services/davclient.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').service('DavClient', [ - function() { - 'use strict'; - var client; - client = new dav.Client({ - baseUrl: OC.linkToRemote('dav/calendars'), - xmlNamespaces: { - 'DAV:': 'd', - 'urn:ietf:params:xml:ns:caldav': 'c', - 'http://apple.com/ns/ical/': 'aapl', - 'http://owncloud.org/ns': 'oc', - 'http://nextcloud.com/ns': 'nc', - 'http://calendarserver.org/ns/': 'cs' - } - }); - angular.extend(client, { - NS_DAV: 'DAV:', - NS_IETF: 'urn:ietf:params:xml:ns:caldav', - NS_APPLE: 'http://apple.com/ns/ical/', - NS_OWNCLOUD: 'http://owncloud.org/ns', - NS_NEXTCLOUD: 'http://nextcloud.com/ns', - NS_CALENDARSERVER: 'http://calendarserver.org/ns/', - buildUrl: function(path) { - return window.location.protocol + '//' + window.location.host + path; - }, - wasRequestSuccessful: function(status) { - return status >= 200 && status <= 299; - } - }); - return client; - } -]); diff --git a/js/app/services/loading.js b/js/app/services/loading.js deleted file mode 100644 index 8bae808d..00000000 --- a/js/app/services/loading.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - - angular.module('Tasks').factory('Loading', [ - function() { - 'use strict'; - var Loading = (function() { - function Loading() { - this.count = 0; - } - - Loading.prototype.increase = function() { - return this.count += 1; - }; - - Loading.prototype.decrease = function() { - return this.count -= 1; - }; - - Loading.prototype.getCount = function() { - return this.count; - }; - - Loading.prototype.isLoading = function() { - return this.count > 0; - }; - - return Loading; - - })(); - return new Loading(); - } -]); diff --git a/js/app/services/model.js b/js/app/services/model.js deleted file mode 100644 index 7405a0c0..00000000 --- a/js/app/services/model.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -(function() { - 'use strict'; - angular.module('Tasks').factory('_Model', [ - function() { - var Model; - Model = (function() { - function Model() { - this._data = []; - this._dataMap = {}; - this._filterCache = {}; - } - - Model.prototype.handle = function(data) { - var item, _i, _len, _results; - _results = []; - for (_i = 0, _len = data.length; _i < _len; _i++) { - item = data[_i]; - _results.push(this.add(item)); - } - return _results; - }; - - Model.prototype.add = function(data, clearCache) { - if (clearCache === null) { - clearCache = true; - } - if (clearCache) { - this._invalidateCache(); - } - if (angular.isDefined(this._dataMap[data.id])) { - return this.update(data, clearCache); - } else { - this._data.push(data); - this._dataMap[data.id] = data; - } - }; - - Model.prototype.update = function(data, clearCache) { - var entry, key, value, _results; - if (clearCache === null) { - clearCache = true; - } - if (clearCache) { - this._invalidateCache(); - } - entry = this.getById(data.id); - _results = []; - for (key in data) { - value = data[key]; - if (key === 'id') { - continue; - } else { - _results.push(entry[key] = value); - } - } - return _results; - }; - - Model.prototype.getById = function(id) { - return this._dataMap[id]; - }; - - Model.prototype.getAll = function() { - return this._data; - }; - - Model.prototype.removeById = function(id, clearCache) { - var counter, data, entry, _i, _len, _ref; - if (clearCache === null) { - clearCache = true; - } - _ref = this._data; - for (counter = _i = 0, _len = _ref.length; _i < _len; counter = ++_i) { - entry = _ref[counter]; - if (entry.id === id) { - this._data.splice(counter, 1); - data = this._dataMap[id]; - delete this._dataMap[id]; - if (clearCache) { - this._invalidateCache(); - } - return data; - } - } - }; - - Model.prototype.clear = function() { - this._data.length = 0; - this._dataMap = {}; - return this._invalidateCache(); - }; - - Model.prototype._invalidateCache = function() { - this._filterCache = {}; - }; - - Model.prototype.get = function(query) { - var hash; - hash = query.hashCode(); - if (!angular.isDefined(this._filterCache[hash])) { - this._filterCache[hash] = query.exec(this._data); - } - return this._filterCache[hash]; - }; - - Model.prototype.size = function() { - return this._data.length; - }; - - return Model; - - })(); - return Model; - } - ]); - -}).call(this); diff --git a/js/app/services/models/calendar.js b/js/app/services/models/calendar.js deleted file mode 100644 index 978ee56a..00000000 --- a/js/app/services/models/calendar.js +++ /dev/null @@ -1,289 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('Calendar', ['$rootScope', '$filter', '$window', function($rootScope, $filter, $window) { - 'use strict'; - - function Calendar(url, props, uri) { - var _this = this; - - props.color = props['{http://apple.com/ns/ical/}calendar-color']; - if (typeof props.color !== 'undefined') { - if (props.color.length === 9) { - props.color = props.color.substr(0,7); - } - } else { - props.color = '#1d2d44'; - } - - angular.extend(this, { - _propertiesBackup: {}, - _properties: { - url: url, - uri: uri, - enabled: props['{http://owncloud.org/ns}calendar-enabled'] === '1', - displayname: props['{DAV:}displayname'] || t('tasks','Unnamed'), - color: props.color, - order: parseInt(props['{http://apple.com/ns/ical/}calendar-order']) || 0, - components: { - vevent: false, - vjournal: false, - vtodo: false - }, - writable: props.canWrite, - shareable: props.canWrite, - sharedWith: { - users: [], - groups: [] - }, - owner: '', - loadedCompleted: false - }, - _updatedProperties: [] - }); - this._propertiesBackup = angular.copy(this._properties); - - // angular.extend(this, { - // tmpId: null, - // fcEventSource: { - // events: function (start, end, timezone, callback) { - // // console.log('querying events ...'); - // // TimezoneService.get(timezone).then(function(tz) { - // // _this.list.loading = true; - // // $rootScope.$broadcast('reloadCalendarList'); - - // // VEventService.getAll(_this, start, end).then(function(events) { - // // var vevents = []; - // // for (var i = 0; i < events.length; i++) { - // // vevents = vevents.concat(events[i].getFcEvent(start, end, tz)); - // // } - - // // callback(vevents); - - // // _this.list.loading = false; - // // $rootScope.$broadcast('reloadCalendarList'); - // // }); - // // }); - // }, - // editable: this._properties.writable, - // calendar: this - // }, - // list: { - // edit: false, - // loading: this.enabled, - // locked: false, - // editingShares: false - // } - // }); - - var components = props['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; - for (var i=0; i < components.length; i++) { - var name = components[i].attributes.getNamedItem('name').textContent.toLowerCase(); - if (this._properties.components.hasOwnProperty(name)) { - this._properties.components[name] = true; - } - } - - var shares = props['{http://owncloud.org/ns}invite']; - if (typeof shares !== 'undefined') { - for (var j=0; j < shares.length; j++) { - var href = shares[j].getElementsByTagNameNS('DAV:', 'href'); - if (href.length === 0) { - continue; - } - href = href[0].textContent; - - var access = shares[j].getElementsByTagNameNS('http://owncloud.org/ns', 'access'); - if (access.length === 0) { - continue; - } - access = access[0]; - - var readWrite = access.getElementsByTagNameNS('http://owncloud.org/ns', 'read-write'); - readWrite = readWrite.length !== 0; - - if (href.startsWith('principal:principals/users/')) { - this._properties.sharedWith.users.push({ - id: href.substr(27), - displayname: href.substr(27), - writable: readWrite - }); - } else if (href.startsWith('principal:principals/groups/')) { - this._properties.sharedWith.groups.push({ - id: href.substr(28), - displayname: href.substr(28), - writable: readWrite - }); - } - } - } - - var owner = props['{DAV:}owner']; - if (typeof owner !== 'undefined' && owner.length !== 0) { - owner = owner[0].textContent.slice(0, -1); - if (owner.startsWith('/remote.php/dav/principals/users/')) { - this._properties.owner = owner.substr(33); - } - } - - // this.tmpId = RandomStringService.generate(); - } - - Calendar.prototype = { - get url() { - return this._properties.url; - }, - get caldav() { - return $window.location.origin + this.url; - }, - get exportUrl() { - var url = this.url; - // cut off last slash to have a fancy name for the ics - if (url.slice(url.length - 1) === '/') { - url = url.slice(0, url.length - 1); - } - url += '?export'; - return url; - }, - get enabled() { - return this._properties.enabled; - }, - get uri() { - return this._properties.uri; - }, - get components() { - return this._properties.components; - }, - set enabled(enabled) { - this._properties.enabled = enabled; - this._setUpdated('enabled'); - }, - get displayname() { - return this._properties.displayname; - }, - set displayname(displayname) { - this._properties.displayname = displayname; - this._setUpdated('displayname'); - }, - get color() { - return this._properties.color; - }, - set color(color) { - this._properties.color = color; - this._setUpdated('color'); - }, - get sharedWith() { - return this._properties.sharedWith; - }, - set sharedWith(sharedWith) { - this._properties.sharedWith = sharedWith; - }, - get textColor() { - var color = this.color; - var fallbackColor = '#fff'; - var c; - switch (color.length) { - case 4: - c = color.match(/^#([0-9a-f]{3})$/i)[1]; - if (c) { - return this._generateTextColor( - parseInt(c.charAt(0),16)*0x11, - parseInt(c.charAt(1),16)*0x11, - parseInt(c.charAt(2),16)*0x11 - ); - } - return fallbackColor; - - case 7: - case 9: - var regex = new RegExp('^#([0-9a-f]{' + (color.length - 1) + '})$', 'i'); - c = color.match(regex)[1]; - if (c) { - return this._generateTextColor( - parseInt(c.substr(0,2),16), - parseInt(c.substr(2,2),16), - parseInt(c.substr(4,2),16) - ); - } - return fallbackColor; - - default: - return fallbackColor; - } - }, - get order() { - return this._properties.order; - }, - set order(order) { - this._properties.order = order; - this._setUpdated('order'); - }, - get writable() { - return this._properties.writable; - }, - get shareable() { - return this._properties.shareable; - }, - get owner() { - return this._properties.owner; - }, - get loadedCompleted() { - return this._properties.loadedCompleted; - }, - set loadedCompleted(loadedCompleted) { - this._properties.loadedCompleted = loadedCompleted; - }, - _setUpdated: function(propName) { - if (this._updatedProperties.indexOf(propName) === -1) { - this._updatedProperties.push(propName); - } - }, - get updatedProperties() { - return this._updatedProperties; - }, - resetUpdatedProperties: function() { - this._updatedProperties = []; - }, - prepareUpdate: function() { - this._propertiesBackup = angular.copy(this._properties); - }, - resetToPreviousState: function() { - this._properties = angular.copy(this._propertiesBackup); - this._propertiesBackup = {}; - }, - dropPreviousState: function() { - this._propertiesBackup = {}; - }, - toggleSharesEditor: function() { - this.list.editingShares = !this.list.editingShares; - }, - _generateTextColor: function(r,g,b) { - var brightness = (((r * 299) + (g * 587) + (b * 114)) / 1000); - return (brightness > 130) ? '#000000' : '#FAFAFA'; - } - }; - - return Calendar; -}]); diff --git a/js/app/services/models/collectionsmodel.js b/js/app/services/models/collectionsmodel.js deleted file mode 100644 index 5e2091c7..00000000 --- a/js/app/services/models/collectionsmodel.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -(function() { - 'use strict'; - var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { - for (var key in parent) { - if (__hasProp.call(parent, key)) { - child[key] = parent[key]; - } - } - function Ctor() { - this.constructor = child; - } - Ctor.prototype = parent.prototype; - child.prototype = new Ctor(); - child.__super__ = parent.prototype; - return child; - }, - __indexOf = [].indexOf || function(item) { - for (var i = 0, l = this.length; i < l; i++) { - if (i in this && this[i] === item) { - return i; - } - } - return -1; - }; - - angular.module('Tasks').factory('CollectionsModel', [ - 'TasksModel', '_Model', function(TasksModel, _Model) { - var CollectionsModel = (function(_super) { - - function CollectionsModel(_$tasksmodel) { - this._$tasksmodel = _$tasksmodel; - this._nameCache = {}; - CollectionsModel.__super__.constructor.call(this); - } - - __extends(CollectionsModel, _super); - - CollectionsModel.prototype.add = function(data, clearCache) { - if (clearCache === null) { - clearCache = true; - } - this._nameCache[data.displayname] = data; - if (angular.isDefined(data.id)) { - return CollectionsModel.__super__.add.call(this, data, clearCache); - } - }; - - CollectionsModel.prototype.getCount = function(collectionID, filter) { - var count, task, tasks, _i, _len; - if (filter === null) { - filter = ''; - } - count = 0; - tasks = this._$tasksmodel.filteredTasks(filter); - for (_i = 0, _len = tasks.length; _i < _len; _i++) { - task = tasks[_i]; - count += this._$tasksmodel.filterTasks(task, collectionID) && !task.related; - } - return count; - }; - - return CollectionsModel; - - })(_Model); - return new CollectionsModel(TasksModel); - } - ]); - -}).call(this); diff --git a/js/app/services/models/listsmodel.js b/js/app/services/models/listsmodel.js deleted file mode 100644 index 3f71c899..00000000 --- a/js/app/services/models/listsmodel.js +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -(function() { - 'use strict'; - var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { - for (var key in parent) { - if (__hasProp.call(parent, key)) { - child[key] = parent[key]; - } - } - function Ctor() { - this.constructor = child; - } - Ctor.prototype = parent.prototype; - child.prototype = new Ctor(); - child.__super__ = parent.prototype; - return child; - }, - __indexOf = [].indexOf || function(item) { - for (var i = 0, l = this.length; i < l; i++) { - if (i in this && this[i] === item) { - return i; - } - } - return -1; - }; - - angular.module('Tasks').factory('ListsModel', [ - 'TasksModel', '_Model', function(TasksModel, _Model) { - var ListsModel = (function(_super) { - - function ListsModel(_$tasksmodel) { - this._$tasksmodel = _$tasksmodel; - this._tmpUriCache = {}; - this._data = []; - this._dataMap = {}; - this._filterCache = {}; - } - - __extends(ListsModel, _super); - - ListsModel.prototype.add = function(calendar, clearCache) { - var updateByUri; - if (clearCache === null) { - clearCache = true; - } - updateByUri = angular.isDefined(calendar.uri) && angular.isDefined(this.getByUri(calendar.uri)); - if (updateByUri) { - return this.update(calendar, clearCache); - } else { - if (angular.isDefined(calendar.uri)) { - if (clearCache) { - this._invalidateCache(); - } - if (!angular.isDefined(this._dataMap[calendar.uri])) { - this._data.push(calendar); - this._dataMap[calendar.uri] = calendar; - } - } - } - }; - - ListsModel.prototype.getByUri = function(uri) { - return this._dataMap[uri]; - }; - - ListsModel.prototype.update = function(list, clearCache) { - var tmplist; - if (clearCache === null) { - clearCache = true; - } - tmplist = this._tmpIdCache[list.tmpID]; - if (angular.isDefined(list.id) && angular.isDefined(tmplist) && angular.isUndefined(tmplist.id)) { - tmplist.id = list.id; - this._dataMap[list.id] = tmplist; - } - list["void"] = false; - return ListsModel.__super__.update.call(this, list, clearCache); - }; - - ListsModel.prototype["delete"] = function(calendar, clearCache) { - var counter, data, entry, _i, _len, _ref; - if (clearCache === null) { - clearCache = true; - } - _ref = this._data; - for (counter = _i = 0, _len = _ref.length; _i < _len; counter = ++_i) { - entry = _ref[counter]; - if (entry === calendar) { - this._data.splice(counter, 1); - data = this._dataMap[calendar.uri]; - delete this._dataMap[calendar.uri]; - if (clearCache) { - this._invalidateCache(); - } - return data; - } - } - }; - - ListsModel.prototype.getStandardList = function() { - var calendars; - if (this.size()) { - calendars = this.getAll(); - return calendars[0]; - } - }; - - ListsModel.prototype.isNameAlreadyTaken = function(displayname, uri) { - var calendar, calendars, ret, _i, _len; - calendars = this.getAll(); - ret = false; - for (_i = 0, _len = calendars.length; _i < _len; _i++) { - calendar = calendars[_i]; - if (calendar.displayname === displayname && calendar.uri !== uri) { - ret = true; - } - } - return ret; - }; - - ListsModel.prototype.getCount = function(calendarID, collectionID, filter) { - var count, task, tasks, _i, _len; - if (filter === null) { - filter = ''; - } - count = 0; - tasks = this._$tasksmodel.filteredTasks(filter); - for (_i = 0, _len = tasks.length; _i < _len; _i++) { - task = tasks[_i]; - count += this._$tasksmodel.filterTasks(task, collectionID) && task.calendar.uri === calendarID && !task.related; - } - // if (collectionID === 'completed' && filter === '') { - // count += this.notLoaded(calendarID); - // } - return count; - }; - - ListsModel.prototype.loadedCompleted = function(calendarID) { - if (angular.isUndefined(this.getById(calendarID))) { - return false; - } else { - return this.getById(calendarID).loadedCompleted; - } - }; - - ListsModel.prototype.setLoadedCompleted = function(calendarID) { - this.getById(calendarID).loadedCompleted = true; - }; - - ListsModel.prototype.getColor = function(calendarID) { - if (angular.isUndefined(this.getById(calendarID))) { - return '#CCCCCC'; - } else { - return this.getById(calendarID).calendarcolor; - } - }; - - ListsModel.prototype.getName = function(calendarID) { - if (angular.isUndefined(this.getById(calendarID))) { - return ''; - } else { - return this.getById(calendarID).displayname; - } - }; - - return ListsModel; - - })(_Model); - return new ListsModel(TasksModel); - } - ]); - -}).call(this); diff --git a/js/app/services/models/settingsmodel.js b/js/app/services/models/settingsmodel.js deleted file mode 100644 index 9c3a5fc9..00000000 --- a/js/app/services/models/settingsmodel.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -(function() { - 'use strict'; - var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { - for (var key in parent) { - if (__hasProp.call(parent, key)) { - child[key] = parent[key]; - } - } - function Ctor() { - this.constructor = child; - } - Ctor.prototype = parent.prototype; - child.prototype = new Ctor(); - child.__super__ = parent.prototype; - return child; - }, - __indexOf = [].indexOf || function(item) { - for (var i = 0, l = this.length; i < l; i++) { - if (i in this && this[i] === item) { - return i; - } - } - return -1; - }; - - angular.module('Tasks').factory('SettingsModel', [ - '_Model', function(_Model) { - var SettingsModel = (function(_super) { - - function SettingsModel() { - this._nameCache = {}; - SettingsModel.__super__.constructor.call(this); - } - - __extends(SettingsModel, _super); - - SettingsModel.prototype.add = function(data, clearCache) { - if (clearCache === null) { - clearCache = true; - } - this._nameCache[data.displayname] = data; - if (angular.isDefined(data.id)) { - return SettingsModel.__super__.add.call(this, data, clearCache); - } else { - return this._data.push(data); - } - }; - - SettingsModel.prototype.toggle = function(type, setting) { - var set; - set = this.getById(type); - this.getById(type)[setting] = !set[setting]; - }; - return SettingsModel; - })(_Model); - return new SettingsModel(); - } - ]); -}).call(this); diff --git a/js/app/services/models/vtodo.js b/js/app/services/models/vtodo.js deleted file mode 100644 index 99b7a513..00000000 --- a/js/app/services/models/vtodo.js +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('VTodo', ['$filter', 'ICalFactory', 'RandomStringService', - function($filter, icalfactory, RandomStringService) { - 'use strict'; - - function VTodo(calendar, props, uri) { - var _this = this; - - angular.extend(this, { - calendar: calendar, - data: props['{urn:ietf:params:xml:ns:caldav}calendar-data'], - uri: uri, - etag: props['{DAV:}getetag'] || null, - timers: [], - loaded: false - }); - - this.jCal = ICAL.parse(this.data); - this.components = new ICAL.Component(this.jCal); - - if (this.components.jCal.length === 0) { - throw "invalid calendar"; - } - } - - VTodo.prototype = { - get summary() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('summary'); - }, - set summary(summary) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('summary', summary); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get priority() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var priority = vtodos[0].getFirstPropertyValue('priority'); - return (10 - priority) % 10; - }, - set priority(priority) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('priority', (10 - priority) % 10); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get complete() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('percent-complete') || 0; - }, - set complete(complete) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('percent-complete', complete); - this.updateLastModified(); - this.data = this.components.toString(); - if (complete < 100) { - this.completed = null; - if (complete === 0) { - this.status = 'NEEDS-ACTION'; - } else { - this.status = 'IN-PROCESS'; - } - } else { - this.completed = ICAL.Time.now(); - this.status = 'COMPLETED'; - } - }, - get completed() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var comp = vtodos[0].getFirstPropertyValue('completed'); - if (comp) { - return true; - } else { - return false; - } - }, - set completed(completed) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - if (completed) { - vtodos[0].updatePropertyWithValue('completed', completed); - } else { - vtodos[0].removeProperty('completed'); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get completed_date() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var comp = vtodos[0].getFirstPropertyValue('completed'); - if (comp) { - return comp.toJSDate(); - } else { - return null; - } - }, - get status() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('status'); - }, - set status(status) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('status', status); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get note() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('description') || ''; - }, - set note(note) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('description', note); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get uid() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('uid') || ''; - }, - get related() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('related-to') || null; - }, - set related(related) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - if (related) { - vtodos[0].updatePropertyWithValue('related-to', related); - } else { - vtodos[0].removeProperty('related-to'); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get hideSubtasks() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return +vtodos[0].getFirstPropertyValue('x-oc-hidesubtasks') || 0; - }, - set hideSubtasks(hide) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('x-oc-hidesubtasks', +hide); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get hideCompletedSubtasks() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return +vtodos[0].getFirstPropertyValue('x-oc-hidecompletedsubtasks') || 0; - }, - set hideCompletedSubtasks(hide) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('x-oc-hidecompletedsubtasks', +hide); - this.updateLastModified(); - this.data = this.components.toString(); - }, - get reminder() { - return null; - }, - get categories() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var categories = vtodos[0].getFirstProperty('categories'); - if (categories) { - return categories.getValues(); - } else { - return []; - } - }, - set categories(cats) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var categories = vtodos[0].getFirstProperty('categories'); - if (cats.length > 0) { - if (categories) { - categories.setValues(cats); - } else { - var prop = new ICAL.Property('categories'); - prop.setValues(cats); - categories = vtodos[0].addProperty(prop); - } - } else { - vtodos[0].removeProperty('categories'); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get start() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('dtstart'); - }, - set start(start) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - if (start) { - vtodos[0].updatePropertyWithValue('dtstart', start); - } else { - vtodos[0].removeProperty('dtstart'); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get due() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - return vtodos[0].getFirstPropertyValue('due'); - }, - set due(due) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - if (due) { - vtodos[0].updatePropertyWithValue('due', due); - } else { - vtodos[0].removeProperty('due'); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get allDay() { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var start = vtodos[0].getFirstPropertyValue('dtstart'); - var due = vtodos[0].getFirstPropertyValue('due'); - var d = due ? due : start; - return d!==null && d.isDate; - }, - set allDay(allDay) { - var vtodos = this.components.getAllSubcomponents('vtodo'); - var start = vtodos[0].getFirstPropertyValue('dtstart'); - if(start) { - start.isDate = allDay; - vtodos[0].updatePropertyWithValue('dtstart', start); - } - var due = vtodos[0].getFirstPropertyValue('due'); - if(due) { - due.isDate = allDay; - vtodos[0].updatePropertyWithValue('due', due); - } - this.updateLastModified(); - this.data = this.components.toString(); - }, - get comments() { - return null; - }, - get loadedCompleted () { - return this.loaded; - }, - set loadedCompleted (loadedCompleted) { - this.loaded = loadedCompleted; - }, - updateLastModified () { - var vtodos = this.components.getAllSubcomponents('vtodo'); - vtodos[0].updatePropertyWithValue('last-modified', ICAL.Time.now()); - vtodos[0].updatePropertyWithValue('dtstamp', ICAL.Time.now()); - } - }; - - VTodo.create = function(task) { - var comp = icalfactory.new(); - - var vtodo = new ICAL.Component('vtodo'); - comp.addSubcomponent(vtodo); - vtodo.updatePropertyWithValue('created', ICAL.Time.now()); - vtodo.updatePropertyWithValue('dtstamp', ICAL.Time.now()); - vtodo.updatePropertyWithValue('last-modified', ICAL.Time.now()); - vtodo.updatePropertyWithValue('uid', RandomStringService.generate()); - vtodo.updatePropertyWithValue('summary', task.summary); - vtodo.updatePropertyWithValue('priority', task.priority); - vtodo.updatePropertyWithValue('percent-complete', task.complete); - vtodo.updatePropertyWithValue('x-oc-hidesubtasks', 0); - if (task.related) { - vtodo.updatePropertyWithValue('related-to', task.related); - } - if (task.note) { - vtodo.updatePropertyWithValue('description', task.note); - } - if (task.due) { - vtodo.updatePropertyWithValue('due', task.due); - } - if (task.start) { - vtodo.updatePropertyWithValue('dtstart', task.start); - } - - return new VTodo(task.calendar, { - '{urn:ietf:params:xml:ns:caldav}calendar-data': comp.toString(), - '{DAV:}getetag': null - }, null); - }; - - return VTodo; -}]); diff --git a/js/app/services/persistence.js b/js/app/services/persistence.js deleted file mode 100644 index 1305e287..00000000 --- a/js/app/services/persistence.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('Persistence', [ - 'Request', 'Loading', '$rootScope', '$q', 'CalendarService', function(Request, Loading, $rootScope, $q, CalendarService) { - 'use strict'; - var Persistence = (function() { - function Persistence(_request, _Loading, _$rootScope, _CalendarService) { - this._request = _request; - this._Loading = _Loading; - this._$rootScope = _$rootScope; - this._CalendarService = _CalendarService; - } - - Persistence.prototype.init = function() { - var successCallback, - _this = this; - this.deferred = $q.defer(); - successCallback = function() { - return _this.deferred.resolve(); - }; - this.getCollections(); - this.getSettings(); - return this.deferred.promise; - }; - - Persistence.prototype.getCollections = function(onSuccess, showLoading) { - var failureCallbackWrapper, params, successCallbackWrapper, - _this = this; - if (showLoading === null) { - showLoading = true; - } - if (!onSuccess) { - onSuccess = function() {}; - } - if (showLoading) { - this._Loading.increase(); - successCallbackWrapper = function(data) { - onSuccess(); - return _this._Loading.decrease(); - }; - failureCallbackWrapper = function(data) { - return _this._Loading.decrease(); - }; - } else { - successCallbackWrapper = function(data) { - return onSuccess(); - }; - failureCallbackWrapper = function(data) {}; - } - params = { - onSuccess: successCallbackWrapper, - onFailure: failureCallbackWrapper - }; - return this._request.get('/apps/tasks/collections', params); - }; - - Persistence.prototype.getSettings = function(onSuccess, showLoading) { - var failureCallbackWrapper, params, successCallbackWrapper, - _this = this; - if (showLoading === null) { - showLoading = true; - } - if (!onSuccess) { - onSuccess = function() {}; - } - if (showLoading) { - this._Loading.increase(); - successCallbackWrapper = function(data) { - onSuccess(); - return _this._Loading.decrease(); - }; - failureCallbackWrapper = function(data) { - return _this._Loading.decrease(); - }; - } else { - successCallbackWrapper = function(data) { - return onSuccess(); - }; - failureCallbackWrapper = function(data) {}; - } - params = { - onSuccess: successCallbackWrapper, - onFailure: failureCallbackWrapper - }; - return this._request.get('/apps/tasks/settings', params); - }; - - Persistence.prototype.setVisibility = function(collectionID, visibility) { - var params = { - routeParams: { - collectionID: collectionID, - visibility: visibility - } - }; - return this._request.post('/apps/tasks/collection/{collectionID}/visibility/{visibility}', params); - }; - - Persistence.prototype.setting = function(type, setting, value) { - var params = { - routeParams: { - type: type, - setting: setting, - value: value - } - }; - return this._request.post('/apps/tasks/settings/{type}/{setting}/{value}', params); - }; - return Persistence; - })(); - return new Persistence(Request, Loading, $rootScope, CalendarService); - } -]); diff --git a/js/app/services/publisher.js b/js/app/services/publisher.js deleted file mode 100644 index 6d803727..00000000 --- a/js/app/services/publisher.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('Publisher', [ - 'CollectionsModel', 'SettingsModel', function(CollectionsModel, SettingsModel) { - 'use strict'; - var Publisher = (function() { - function Publisher(_$collectionsmodel, _$settingsmodel) { - this._$collectionsmodel = _$collectionsmodel; - this._$settingsmodel = _$settingsmodel; - this._subscriptions = {}; - this.subscribeObjectTo(this._$collectionsmodel, 'collections'); - this.subscribeObjectTo(this._$settingsmodel, 'settings'); - } - - Publisher.prototype.subscribeObjectTo = function(object, name) { - var base = this._subscriptions; - if (!base[name]) { - base[name] = []; - } - return this._subscriptions[name].push(object); - }; - - Publisher.prototype.publishDataTo = function(data, name) { - var ref, results, subscriber, _i, _len; - ref = this._subscriptions[name] || []; - results = []; - for (_i = 0, _len = ref.length; _i < _len; _i++) { - subscriber = ref[_i]; - results.push(subscriber.handle(data)); - } - return results; - }; - return Publisher; - })(); - return new Publisher(CollectionsModel, SettingsModel); - } -]); diff --git a/js/app/services/randomstringservice.js b/js/app/services/randomstringservice.js deleted file mode 100644 index be28eae9..00000000 --- a/js/app/services/randomstringservice.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * - * 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 . - * - */ - -angular.module('Tasks').factory('RandomStringService', function () { - 'use strict'; - - return { - generate: function() { - return Math.random().toString(36).substr(2); - } - }; -}); diff --git a/js/app/services/request.js b/js/app/services/request.js deleted file mode 100644 index f2745cf3..00000000 --- a/js/app/services/request.js +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('Request', [ - '$http', 'Publisher', function($http, Publisher) { - 'use strict'; - var Request = (function() { - function Request($http, publisher) { - this.$http = $http; - this.publisher = publisher; - this.count = 0; - this.initialized = false; - this.shelvedRequests = []; - this.initialized = true; - this._executeShelvedRequests(); - } - - Request.prototype.request = function(route, data) { - var defaultConfig, defaultData, url; - if (data === null) { - data = {}; - } - defaultData = { - routeParams: {}, - data: {}, - onSuccess: function() { - return {}; - }, - onFailure: function() { - return {}; - }, - config: {} - }; - angular.extend(defaultData, data); - if (!this.initialized) { - this._shelveRequest(route, defaultData); - return; - } - url = OC.generateUrl(route, defaultData.routeParams); - defaultConfig = { - url: url, - data: defaultData.data - }; - angular.extend(defaultConfig, defaultData.config); - if (defaultConfig.method === 'GET') { - defaultConfig.params = defaultConfig.data; - } - return this.$http(defaultConfig).then((function(_this) { - return function(response) { - var name, ref, value; - ref = response.data.data; - for (name in ref) { - value = ref[name]; - _this.publisher.publishDataTo(value, name); - } - return defaultData.onSuccess(response.data, response.status, response.headers, response.config); - }; - })(this)).catch(function(response) { - return defaultData.onFailure(response.data, response.status, response.headers, response.config); - }); - }; - - Request.prototype.post = function(route, data) { - if (data === null) { - data = {}; - } - if (!data.config) { - data.config = {}; - } - data.config.method = 'POST'; - return this.request(route, data); - }; - - Request.prototype.get = function(route, data) { - if (data === null) { - data = {}; - } - if (!data.config) { - data.config = {}; - } - data.config.method = 'GET'; - return this.request(route, data); - }; - - Request.prototype.put = function(route, data) { - if (data === null) { - data = {}; - } - if (!data.config) { - data.config = {}; - } - data.config.method = 'PUT'; - return this.request(route, data); - }; - - Request.prototype["delete"] = function(route, data) { - if (data === null) { - data = {}; - } - if (!data.config) { - data.config = {}; - } - data.config.method = 'DELETE'; - return this.request(route, data); - }; - - Request.prototype._shelveRequest = function(route, data) { - var request = { - route: route, - data: data - }; - return this.shelvedRequests.push(request); - }; - - Request.prototype._executeShelvedRequests = function() { - var r, ref, results, _i, _len; - ref = this.shelvedRequests; - results = []; - for (_i = 0, _len = ref.length; _i < _len; _i++) { - r = ref[_i]; - results.push(this.request(r.route, r.data)); - } - return results; - }; - return Request; - })(); - return new Request($http, Publisher); - } -]); diff --git a/js/app/services/status.js b/js/app/services/status.js deleted file mode 100644 index af61c731..00000000 --- a/js/app/services/status.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raimund Schlüßler - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').factory('Status', [ - function() { - 'use strict'; - var Status; - Status = (function() { - function Status() { - this._$status = { - addingList: false, - focusTaskInput: false - }; - } - - Status.prototype.getStatus = function() { - return this._$status; - }; - - return Status; - - })(); - return new Status(); - } -]); diff --git a/js/app/services/vtodoservice.js b/js/app/services/vtodoservice.js deleted file mode 100644 index 5db2e8ef..00000000 --- a/js/app/services/vtodoservice.js +++ /dev/null @@ -1,212 +0,0 @@ -/** - * Nextcloud - Tasks - * - * @author Raghu Nayyar - * @author Georg Ehrke - * @author Raimund Schlüßler - * @copyright 2017 Raghu Nayyar - * @copyright 2017 Georg Ehrke - * @copyright 2018 Raimund Schlüßler - * - * 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 . - * - */ - -angular.module('Tasks').service('VTodoService', ['DavClient', 'RandomStringService', '$timeout', function(DavClient, RandomStringService, $timeout) { - 'use strict'; - - var _this = this; - - this.getAll = function(calendar, completed, parent) { - if (completed === null) { - completed = false; - } - if (parent === null) { - parent = false; - } - var xmlDoc = document.implementation.createDocument('', '', null); - var cCalQuery = xmlDoc.createElement('c:calendar-query'); - cCalQuery.setAttribute('xmlns:c', 'urn:ietf:params:xml:ns:caldav'); - cCalQuery.setAttribute('xmlns:d', 'DAV:'); - cCalQuery.setAttribute('xmlns:a', 'http://apple.com/ns/ical/'); - cCalQuery.setAttribute('xmlns:o', 'http://owncloud.org/ns'); - xmlDoc.appendChild(cCalQuery); - - var dProp = xmlDoc.createElement('d:prop'); - cCalQuery.appendChild(dProp); - - var dGetEtag = xmlDoc.createElement('d:getetag'); - dProp.appendChild(dGetEtag); - - var cCalendarData = xmlDoc.createElement('c:calendar-data'); - dProp.appendChild(cCalendarData); - - var cFilter = xmlDoc.createElement('c:filter'); - cCalQuery.appendChild(cFilter); - - var cCompFilterVCal = xmlDoc.createElement('c:comp-filter'); - cCompFilterVCal.setAttribute('name', 'VCALENDAR'); - cFilter.appendChild(cCompFilterVCal); - - var cCompFilterVTodo = xmlDoc.createElement('c:comp-filter'); - cCompFilterVTodo.setAttribute('name', 'VTODO'); - cCompFilterVCal.appendChild(cCompFilterVTodo); - - var cPropFilterCompleted = xmlDoc.createElement('c:prop-filter'); - cPropFilterCompleted.setAttribute('name', 'COMPLETED'); - cCompFilterVTodo.appendChild(cPropFilterCompleted); - - if (!completed) { - var cIsNotDefined = xmlDoc.createElement('c:is-not-defined'); - cPropFilterCompleted.appendChild(cIsNotDefined); - } - - if (parent) { - var cPropFilterRelated = xmlDoc.createElement('c:prop-filter'); - cPropFilterRelated.setAttribute('name', 'RELATED-TO'); - cCompFilterVTodo.appendChild(cPropFilterRelated); - var cTextMatch = xmlDoc.createElement('c:text-match'); - var cTextMatchValue = xmlDoc.createTextNode(parent.uid); - cTextMatch.appendChild(cTextMatchValue); - cPropFilterRelated.appendChild(cTextMatch); - } - - // var cPropFilterStatus = xmlDoc.createElement('c:prop-filter'); - // cPropFilterStatus.setAttribute('name', 'STATUS'); - // cCompFilterVTodo.appendChild(cPropFilterStatus); - - // var cTextMatch = xmlDoc.createElement('c:text-match'); - // cTextMatch.setAttribute('negate-condition', 'yes'); - // var cTextMatchValue = xmlDoc.createTextNode('CANCELLED'); - // cTextMatch.appendChild(cTextMatchValue); - // cPropFilterStatus.appendChild(cTextMatch); - - // var cTimeRange = xmlDoc.createElement('c:time-range'); - // cTimeRange.setAttribute('start', this._getTimeRangeStamp(start)); - // cTimeRange.setAttribute('end', this._getTimeRangeStamp(end)); - // cCompFilterVTodo.appendChild(cTimeRange); - - var url = calendar.url; - var headers = { - 'Content-Type': 'application/xml; charset=utf-8', - 'Depth': 1, - 'requesttoken': OC.requestToken - }; - var body = cCalQuery.outerHTML; - - return DavClient.request('REPORT', url, headers, body).then(function(response) { - if (!DavClient.wasRequestSuccessful(response.status)) { - //TODO - something went wrong - return; - } - - var vTodos = []; - - for (var i in response.body) { - var object = response.body[i]; - var properties = object.propStat[0].properties; - - var uri = object.href.substr(object.href.lastIndexOf('/') + 1); - - var vTodo = { - calendar: calendar, - properties: properties, - uri: uri - }; - vTodos.push(vTodo); - } - - return vTodos; - }); - }; - - this.get = function(calendar, uri) { - var url = calendar.url + uri; - return DavClient.request('GET', url, {'requesttoken' : OC.requestToken}, '').then(function(response) { - var vTodo = { - calendar: calendar, - properties: { - '{urn:ietf:params:xml:ns:caldav}calendar-data': response.body, - '{DAV:}getetag': response.xhr.getResponseHeader('ETag')}, - uri: uri - }; - return vTodo; - }); - }; - - this.create = function(calendar, data, returnTodo) { - if (typeof returnTodo === 'undefined') { - returnTodo = true; - } - - var headers = { - 'Content-Type': 'text/calendar; charset=utf-8', - 'requesttoken': OC.requestToken - }; - var uri = this._generateRandomUri(); - var url = calendar.url + uri; - - return DavClient.request('PUT', url, headers, data).then(function(response) { - if (!DavClient.wasRequestSuccessful(response.status)) { - console.log(response); - return false; - // TODO - something went wrong, do smth about it - } - - return returnTodo ? - _this.get(calendar, uri) : - true; - }); - }; - - this.update = function(task) { - var url = task.calendar.url + task.uri; - var headers = { - 'Content-Type': 'text/calendar; charset=utf-8', - 'If-Match': task.etag, - 'requesttoken': OC.requestToken - }; - $timeout.cancel(task.timers.update); - return DavClient.request('PUT', url, headers, task.data).then(function(response) { - task.etag = response.xhr.getResponseHeader('ETag'); - return DavClient.wasRequestSuccessful(response.status); - }); - }; - - this.delete = function(task) { - var url = task.calendar.url + task.uri; - var headers = { - 'If-Match': task.etag, - 'requesttoken': OC.requestToken - }; - - return DavClient.request('DELETE', url, headers, '').then(function(response) { - return DavClient.wasRequestSuccessful(response.status); - }); - }; - - this._generateRandomUri = function() { - var uri = 'Nextcloud-'; - uri += RandomStringService.generate(); - uri += RandomStringService.generate(); - uri += '.ics'; - - return uri; - }; - - // this._getTimeRangeStamp = function(momentObject) { - // return momentObject.format('YYYYMMDD') + 'T' + momentObject.format('HHmmss') + 'Z'; - // }; - -}]); diff --git a/js/app/filters/day.js b/js/app/store.js similarity index 76% rename from js/app/filters/day.js rename to js/app/store.js index 2e8709ef..32cf9f71 100644 --- a/js/app/filters/day.js +++ b/js/app/store.js @@ -18,10 +18,20 @@ * License along with this library. If not, see . * */ +'use strict'; -angular.module('Tasks').filter('day', function() { - 'use strict'; - return function(i) { - return moment().add('days', i).locale('list_week').calendar(); - }; +import Vue from 'vue'; +import Vuex from 'vuex'; +import Axios from 'axios'; +Axios.defaults.headers.common.requesttoken = OC.requestToken; + +Vue.use(Vuex); + +export default new Vuex.Store({ + state: { + }, + mutations: { + }, + actions: { + } }); diff --git a/js/merged.json b/js/merged.json index 86ca1500..eb4c7ddd 100644 --- a/js/merged.json +++ b/js/merged.json @@ -1,12 +1,3 @@ [ - "vendor/angular/angular.min.js", - "vendor/angular-route/angular-route.min.js", - "vendor/angular-animate/angular-animate.min.js", - "vendor/angular-sanitize/angular-sanitize.min.js", - "vendor/angular-drag-and-drop-lists/angular-drag-and-drop-lists.min.js", - "vendor/ui-select/dist/select.min.js", - "vendor/jstimezonedetect/dist/jstz.min.js", - "vendor/ical.js/build/ical.min.js", - "vendor_legacy/jquery-timepicker/jquery.ui.timepicker.js", - "public/app.min.js" + "public/build.js" ] diff --git a/package.json b/package.json index 5ca83add..ac057850 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,11 @@ "private": true, "homepage": "https://github.com/nextcloud/tasks", "scripts": { - "test": "node node_modules/gulp-cli/bin/gulp.js karma", + "test": "jest --verbose", "prebuild": "npm install && npm upgrade", - "build": "node node_modules/gulp-cli/bin/gulp.js" + "build": "node node_modules/gulp-cli/bin/gulp.js build", + "development": "node node_modules/gulp-cli/bin/gulp.js development", + "watch": "node node_modules/gulp-cli/bin/gulp.js watch" }, "repository": { "type": "git", @@ -21,38 +23,73 @@ "bugs": "https://github.com/nextcloud/tasks/issues", "contributors": [], "dependencies": { - "angular": "1.5.5", - "angular-animate": "1.5.5", - "angular-drag-and-drop-lists": "git+https://github.com/marceljuenemann/angular-drag-and-drop-lists.git#2.1.0", - "angular-route": "1.5.5", - "angular-sanitize": "1.5.5", + "axios": "^0.18.0", + "vue": "^2.5.17", + "vue-router": "3.0.1", + "vuex": "^3.0.1", "ical.js": "~1.2.2", "jstimezonedetect": "", "ui-select": "git+https://github.com/angular-ui/ui-select.git#v0.19.8" }, "devDependencies": { - "babel-core": "6.26.3", - "babel-preset-es2015": "^6.14.0", + "@vue/test-utils": "^1.0.0-beta.24", + "babel-core": "^6.26.3", + "babel-jest": "^23.4.2", + "babel-loader": "^7.1.5", + "babel-preset-env": "^1.7.0", + "cross-env": "^5.2.0", + "css-loader": "^1.0.0", + "expect": "^23.5.0", + "file-loader": "^1.1.11", "gulp": "^3.9.1", - "gulp-babel": "^7.0.1", "gulp-cli": "^2.0.1", "gulp-concat": "^2.6.1", "gulp-jshint": "^2.1.0", - "gulp-ng-annotate": "^2.1.0", - "gulp-npm-files": "^0.1.3", - "gulp-sourcemaps": "^2.6.4", - "gulp-strip-banner": "0.0.2", "gulp-stylelint": "^7.0.0", "gulp-svg-sprite": "1.4.0", - "gulp-uglify": "^3.0.1", - "gulp-wrap": "^0.14.0", + "jest": "^23.5.0", + "jest-serializer-vue": "^2.0.2", + "jsdom": "^11.12.0", + "jsdom-global": "^3.0.2", "jshint": "^2.9.6", - "karma": "^3.1.1", - "stylelint": "^9.8.0", + "stylelint": "^9.4.0", "stylelint-config-standard": "^18.2.0", - "stylelint-scss": "^3.4.0" + "stylelint-scss": "^3.2.0", + "uglifyjs-webpack-plugin": "^1.2.7", + "vue-jest": "^2.6.0", + "vue-loader": "^15.3.0", + "vue-template-compiler": "^2.5.17", + "webpack": "^4.16.5", + "webpack-cli": "^3.1.0", + "webpack-dev-server": "^3.1.5", + "webpack-merge": "^4.1.4", + "webpack-node-externals": "^1.6.0", + "webpack-stream": "^5.1.1" }, "engines": { "node": ">=6" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "vue" + ], + "moduleNameMapper": { + "^@/(.*)$": "/js/app/$1" + }, + "transform": { + "^.+\\.js$": "/node_modules/babel-jest", + ".*\\.(vue)$": "/node_modules/vue-jest" + }, + "snapshotSerializers": [ + "/node_modules/jest-serializer-vue" + ], + "collectCoverage": true, + "collectCoverageFrom": [ + "/js/app/**/*.{js,vue}", + "!**/node_modules/**", + "!**/vendor/**" + ], + "coverageReporters": ["json", "text", "html"] } } diff --git a/test/OC.js b/test/OC.js new file mode 100644 index 00000000..4fef3173 --- /dev/null +++ b/test/OC.js @@ -0,0 +1,9 @@ +export class OC { + generateUrl(url) { + return ''; + } + + imagePath(app, img) { + return ''; + } +} diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 00000000..0925dfad --- /dev/null +++ b/test/setup.js @@ -0,0 +1,3 @@ +require('jsdom-global')(); + +global.expect = require('expect'); diff --git a/webpack.common.js b/webpack.common.js new file mode 100644 index 00000000..106cab7f --- /dev/null +++ b/webpack.common.js @@ -0,0 +1,57 @@ +var path = require('path'); +var VueLoaderPlugin = require('vue-loader/lib/plugin'); + +module.exports = { + mode: 'development', + entry: './js/app/init.js', + output: { + path: path.resolve(__dirname, './js/public'), + publicPath: '/public/', + filename: 'build.js' + }, + plugins: [ + new VueLoaderPlugin() + ], + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader', + }, + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/ + }, + { + test: /\.(png|jpg|gif|svg)$/, + loader: 'file-loader', + options: { + name: '[name].[ext]?[hash]' + } + }, + { + test: /\.css$/, + use: [ + 'vue-style-loader', + 'css-loader' + ] + } + ] + }, + resolve: { + alias: { + 'vue$': 'vue/dist/vue.esm.js', + '@': path.resolve(__dirname, 'js/app') + } + }, + devServer: { + historyApiFallback: true, + noInfo: true, + overlay: true + }, + performance: { + hints: false + }, + devtool: '#eval-source-map' +}; diff --git a/webpack.prod.js b/webpack.prod.js new file mode 100644 index 00000000..f6993230 --- /dev/null +++ b/webpack.prod.js @@ -0,0 +1,16 @@ +const merge = require('webpack-merge'); +const common = require('./webpack.common'); +const webpack = require('webpack'); +const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); + +module.exports = merge(common, { + devtool: 'none', + mode: 'production', + // http://vue-loader.vuejs.org/en/workflow/production.html + plugins: [ + new UglifyJSPlugin(), + new webpack.LoaderOptionsPlugin({ + minimize: true + }) + ] +});