diff --git a/appinfo/routes.php b/appinfo/routes.php
index eab8a058..55b1a935 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -33,6 +33,28 @@ $this->create('tasks_enhanced_index', '/')
$dispatcher->dispatch('PageController', 'index');
}
);
+/*
+ * Collections
+ */
+$this->create('getCollections', '/collections')
+ ->get()
+ ->action(
+ function($params){
+ session_write_close();
+ $dispatcher = new Dispatcher($params);
+ $dispatcher->dispatch('CollectionsController', 'getCollections');
+ }
+ );
+
+$this->create('setVisibility', '/collection/{collectionID}/visibility/{visibility}')
+ ->post()
+ ->action(
+ function($params){
+ session_write_close();
+ $dispatcher = new Dispatcher($params);
+ $dispatcher->dispatch('CollectionsController', 'setVisibility');
+ }
+ );
/*
* Lists
@@ -209,4 +231,27 @@ $this->create('task_reminder', '/tasks/{taskID}/reminder')
$dispatcher = new Dispatcher($params);
$dispatcher->dispatch('TasksController', 'setReminderDate');
}
+ );
+
+/*
+ * Settings
+ */
+$this->create('getSettings', '/settings')
+ ->get()
+ ->action(
+ function($params){
+ session_write_close();
+ $dispatcher = new Dispatcher($params);
+ $dispatcher->dispatch('SettingsController', 'getSettings');
+ }
+ );
+
+$this->create('showHidden', '/settings/{type}/{setting}/{value}')
+ ->post()
+ ->action(
+ function($params){
+ session_write_close();
+ $dispatcher = new Dispatcher($params);
+ $dispatcher->dispatch('SettingsController', 'set');
+ }
);
\ No newline at end of file
diff --git a/css/style.css b/css/style.css
index d7ad9958..0b6fe268 100644
--- a/css/style.css
+++ b/css/style.css
@@ -93,6 +93,11 @@
transition: opacity 100ms ease 0s;
opacity: 0.6;
}
+#content .icon.detail-settings {
+ background-position: -200px -40px;
+ transition: opacity 100ms ease 0s;
+ opacity: 0.6;
+}
#content .icon.search {
background-position: -80px -20px;
transition: opacity 100ms ease 0s;
@@ -359,6 +364,9 @@
height: 20px;
line-height: 20px;
}
+#task-lists div.footer a.settings {
+ right: 0;
+}
#task-lists div.scroll {
position: absolute;
top: 37px;
@@ -931,6 +939,51 @@
#task-details .body .section.detail-reminder.date .section-description {
display: block;
}
+#modal-wrapper {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: none repeat scroll 0 0 rgba(0, 0, 0, 0.25);
+}
+#settings_modal {
+ background: url("../img/bgBig.png") repeat scroll 0 0 #f3f3f3;
+ border-radius: 6px;
+}
+#settings_modal .header h2 {
+ font-size: 17px;
+ padding: 10px;
+ text-align: center;
+}
+#settings_modal .header .button {
+ position: absolute;
+ top: 3px;
+ right: 5px;
+}
+#settings_modal .navbar {
+ border-color: #ccc;
+ border-style: solid;
+ border-width: 1px 0;
+ height: 50px;
+}
+#settings_modal .content {
+ min-height: 100px;
+}
+.button {
+ background-image: -moz-linear-gradient(center top, #5cb6e7 0px, #317cd7 100%);
+ border-color: #0c67a5;
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3) inset;
+ color: #fff;
+ font-weight: bold;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
+ line-height: 14px;
+ margin-right: 8px;
+ padding: 6px 10px 5px;
+ position: relative;
+ float: right;
+}
+.button:hover {
+ color: #CCCCCC;
+}
input,
textarea {
-moz-user-select: text;
@@ -938,6 +991,9 @@ textarea {
#content a:hover .icon.detail-trash {
opacity: 1;
}
+#content a:hover .icon.detail-settings {
+ opacity: 1;
+}
#content a:hover .icon.search {
opacity: 1;
}
diff --git a/css/style.less b/css/style.less
index d672bb7f..eec76ba7 100644
--- a/css/style.less
+++ b/css/style.less
@@ -115,6 +115,11 @@
transition: opacity 100ms ease 0s;
opacity:0.6;
}
+ &.detail-settings{
+ background-position: -200px -40px;
+ transition: opacity 100ms ease 0s;
+ opacity:0.6;
+ }
&.search {
background-position: -80px -20px;
transition: opacity 100ms ease 0s;
@@ -382,6 +387,9 @@
padding:10px;
height:20px;
line-height:20px;
+ &.settings{
+ right:0;
+ }
}
}
div.scroll{
@@ -981,6 +989,55 @@
}
}
+#modal-wrapper{
+ position: absolute;
+ width:100%;
+ height: 100%;
+ background: none repeat scroll 0 0 rgba(0, 0, 0, 0.25);
+}
+
+#settings_modal{
+ background: url("../img/bgBig.png") repeat scroll 0 0 #f3f3f3;
+ border-radius: 6px;
+ .header{
+ h2{
+ font-size: 17px;
+ padding: 10px;
+ text-align: center;
+ }
+ .button{
+ position: absolute;
+ top:3px;
+ right:5px;
+ }
+ }
+ .navbar{
+ border-color: #ccc;
+ border-style: solid;
+ border-width: 1px 0;
+ height: 50px;
+ }
+ .content{
+ min-height:100px;
+ }
+}
+.button{
+ background-image: -moz-linear-gradient(center top , #5cb6e7 0px, #317cd7 100%);
+ border-color: #0c67a5;
+ box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3) inset;
+ color: #fff;
+ font-weight: bold;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
+ line-height: 14px;
+ margin-right: 8px;
+ padding: 6px 10px 5px;
+ position: relative;
+ float:right;
+ &:hover{
+ color:#CCCCCC;
+ }
+}
+
input, textarea {
-moz-user-select: text;
}
@@ -988,6 +1045,9 @@ input, textarea {
&.detail-trash{
opacity:1;
}
+ &.detail-settings{
+ opacity:1;
+ }
&.search{
opacity:1;
}
diff --git a/css/vendor/bootstrap/bootstrap.css b/css/vendor/bootstrap/bootstrap.css
new file mode 100644
index 00000000..9069bd34
--- /dev/null
+++ b/css/vendor/bootstrap/bootstrap.css
@@ -0,0 +1,173 @@
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ display: none;
+ overflow: auto;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transition: -webkit-transform .3s ease-out;
+ -moz-transition: -moz-transform .3s ease-out;
+ -o-transition: -o-transform .3s ease-out;
+ transition: transform .3s ease-out;
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ outline: none;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000;
+}
+.modal-backdrop.fade {
+ filter: alpha(opacity=0);
+ opacity: 0;
+}
+.modal-backdrop.in {
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.modal-header {
+ min-height: 16.42857143px;
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 20px;
+}
+.modal-footer {
+ padding: 19px 20px 20px;
+ margin-top: 15px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 500px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+ul.nav-tabs{
+ border-color: #ccc;
+ border-style: solid;
+ border-width: 1px 0;
+ clear: both;
+ content: " ";
+ display: table;
+ width: 100%;
+}
+.nav-tabs > li{
+ display: block;
+ float: left;
+ height: 50px;
+ padding: 0 10px;
+ position: relative;
+}
+.nav-tabs > li.active{
+ background: url("../../../img/bgSettingsActive.png") repeat scroll 0 0 #4a99db;
+}
+.nav-tabs >li.active a{
+ color:white;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
+}
+.nav-tabs > li a{
+ font-weight: bold;
+ display: block;
+ height: 50px;
+ line-height: 50px;
+}
+.nav-tabs > li:first-child{
+ margin-left: 20px;
+}
+.tabbable .tab-pane{
+ padding:20px;
+}
+.tab-pane select{
+ background-color: rgba(0, 0, 0, 0);
+ border: 1px solid #ccc;
+ border-radius: 0;
+ font-weight: normal;
+ margin: 0;
+ padding: 0;
+ width: 98px;
+ float:right;
+}
+.tab-pane li{
+ padding: 10px 0;
+}
+.tab-pane li span.title{
+ padding-left: 10px;
+ position: relative;
+ top: 2px;
+}
+}
\ No newline at end of file
diff --git a/img/bgSettingsActive.png b/img/bgSettingsActive.png
new file mode 100644
index 00000000..6c363e88
Binary files /dev/null and b/img/bgSettingsActive.png differ
diff --git a/img/sprites.svg b/img/sprites.svg
index 7cd220e4..c01c354e 100644
--- a/img/sprites.svg
+++ b/img/sprites.svg
@@ -697,22 +697,22 @@
-
+
-
+
-
+
-
+
@@ -1554,4 +1554,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/app/app.coffee b/js/app/app.coffee
index 5e11f714..b76e4e36 100644
--- a/js/app/app.coffee
+++ b/js/app/app.coffee
@@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public
License along with this library. If not, see .
###
-angular.module('Tasks',['OC','ngRoute','ngAnimate'])
+angular.module('Tasks',['OC','ngRoute','ngAnimate','ui.bootstrap'])
.config ['$provide','$routeProvider', '$interpolateProvider',
($provide, $routeProvider, $interpolateProvider) ->
$provide.value 'Config', config =
@@ -30,6 +30,7 @@ angular.module('Tasks',['OC','ngRoute','ngAnimate'])
.when('/lists/:listID',{})
.when('/lists/:listID/edit/:listparameter',{})
.when('/lists/:listID/tasks/:taskID',{})
+ .when('/lists/:listID/tasks/:taskID/settings',{})
.when('/lists/:listID/tasks/:taskID/edit/:parameter',{})
.when('/search/:searchString',{})
.when('/search/:searchString/tasks/:taskID',{})
@@ -71,6 +72,7 @@ angular.module('Tasks').run ['Config', '$timeout',
timeOutUpdate = ->
$timeout update, Config.taskUpdateInterval
if init
+ # CollectionsBusinessLayer.updateModel()
ListsBusinessLayer.updateModel()
TasksBusinessLayer.updateModel()
init = true
diff --git a/js/app/controllers/appcontroller.coffee b/js/app/controllers/appcontroller.coffee
index b5834e7f..4fbea00d 100644
--- a/js/app/controllers/appcontroller.coffee
+++ b/js/app/controllers/appcontroller.coffee
@@ -23,14 +23,15 @@ License along with this library. If not, see .
angular.module('Tasks').controller 'AppController',
['$scope', 'Persistence', '$route', 'Status', '$timeout',
-'$location', '$routeParams', 'Loading',
+'$location', '$routeParams', 'Loading','$modal','SettingsModel',
($scope, Persistence, $route, status, $timeout, $location,
-$routeParams, Loading) ->
+$routeParams, Loading, $modal, SettingsModel) ->
class AppController
constructor: (@_$scope, @_persistence, @_$route, @_$status,
- @_$timeout, @_$location, @_$routeparams, @_Loading) ->
+ @_$timeout, @_$location, @_$routeparams, @_Loading,
+ @_$modal,@_$settingsmodel) ->
@_$scope.initialized = false
@@ -40,6 +41,8 @@ $routeParams, Loading) ->
@_$scope.status.newListName = ""
+ @_$scope.settingsmodel = @_$settingsmodel
+
successCallback = =>
@_$scope.initialized = true
@@ -58,7 +61,15 @@ $routeParams, Loading) ->
@_$scope.isLoading = () ->
return _Loading.isLoading()
+ @_$scope.showSettings = () ->
+ _$scope.modalInstance = _$modal.open({
+ templateUrl: 'part.settings.html',
+ controller: 'SettingsController',
+ backdrop: true,
+ windowClass: 'test'
+ })
+
return new AppController($scope, Persistence, $route, status, $timeout,
- $location, $routeParams, Loading)
+ $location, $routeParams, Loading, $modal, SettingsModel)
]
\ No newline at end of file
diff --git a/js/app/controllers/listcontroller.coffee b/js/app/controllers/listcontroller.coffee
index 90f1ae69..0b61733b 100644
--- a/js/app/controllers/listcontroller.coffee
+++ b/js/app/controllers/listcontroller.coffee
@@ -132,6 +132,16 @@ CollectionsModel, ListsBusinessLayer, $location) ->
@_$scope.getCollectionCount = (collectionID) ->
return _$collectionsmodel.getCount(collectionID)
+ @_$scope.hideCollection = (collectionID) ->
+ collection = _$collectionsmodel.getById(collectionID)
+ switch collection.show
+ when 0
+ return true
+ when 1
+ return false
+ when 2
+ return (@getCollectionCount(collectionID) < 1)
+
@_$scope.getCollectionString = (collectionID) ->
return _$collectionsmodel.getCountString(collectionID)
@@ -144,6 +154,7 @@ CollectionsModel, ListsBusinessLayer, $location) ->
@_$scope.update = () ->
if not _$scope.isLoading()
+ # _$collectionsbusinesslayer.updateModel()
_$tasksbusinesslayer.updateModel()
_$listsbusinesslayer.updateModel()
diff --git a/js/app/controllers/settingscontroller.coffee b/js/app/controllers/settingscontroller.coffee
new file mode 100644
index 00000000..831898cc
--- /dev/null
+++ b/js/app/controllers/settingscontroller.coffee
@@ -0,0 +1,60 @@
+###
+
+ownCloud - Tasks
+
+@author Raimund Schlüßler
+@copyright 2013
+
+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','$modalInstance',
+'CollectionsModel', 'SettingsBusinessLayer',
+($scope, $window, Status, $location, $modalInstance,CollectionsModel,
+ SettingsBusinessLayer) ->
+
+ class SettingsController
+
+ constructor: (@_$scope, @_$window, @_$status,
+ @_$location, @_$modalInstance, @_$collectionsmodel,
+ @_$settingsbusinesslayer) ->
+
+ @_$scope.status = @_$status.getStatus()
+
+ @_$scope.collections = @_$collectionsmodel.getAll()
+
+ @_$scope.collectionOptions = [
+ {
+ id: 0,
+ name: t('tasks_enhanced','Hidden')},
+ {
+ id: 1,
+ name: t('tasks_enhanced','Visible')},
+ {
+ id: 2,
+ name: t('tasks_enhanced','Automatic')}
+ ]
+
+ @_$scope.ok = () =>
+ $modalInstance.close()
+
+ @_$scope.setVisibility = (collectionID) =>
+ collection = _$collectionsmodel.getById(collectionID)
+ _$settingsbusinesslayer.setVisibility(collectionID,collection.show)
+
+
+ return new SettingsController($scope, $window, Status, $location,
+ $modalInstance, CollectionsModel, SettingsBusinessLayer)
+]
\ No newline at end of file
diff --git a/js/app/controllers/taskscontroller.coffee b/js/app/controllers/taskscontroller.coffee
index 4cfffe0d..8fdf8c78 100644
--- a/js/app/controllers/taskscontroller.coffee
+++ b/js/app/controllers/taskscontroller.coffee
@@ -22,14 +22,16 @@ License along with this library. If not, see .
angular.module('Tasks').controller 'TasksController',
['$scope', '$window', '$routeParams', 'TasksModel', 'ListsModel',
'CollectionsModel', 'TasksBusinessLayer', '$location',
+'SettingsBusinessLayer',
($scope, $window, $routeParams, TasksModel, ListsModel,
-CollectionsModel, TasksBusinessLayer, $location) ->
+CollectionsModel, TasksBusinessLayer, $location,
+SettingsBusinessLayer) ->
class TasksController
constructor: (@_$scope,@_$window,@_$routeParams,
@_$tasksmodel,@_$listsmodel,@_$collectionsmodel,
- @_tasksbusinesslayer, @$location) ->
+ @_tasksbusinesslayer, @$location, @_settingsbusinesslayer) ->
@_$scope.tasks = @_$tasksmodel.getAll()
@_$scope.lists = @_$listsmodel.getAll()
@@ -100,7 +102,7 @@ CollectionsModel, TasksBusinessLayer, $location) ->
_tasksbusinesslayer.starTask(taskID)
@_$scope.toggleHidden = () ->
- _$scope.status.showhidden = !_$scope.status.showhidden
+ _settingsbusinesslayer.toggle('various','showHidden')
@_$scope.filterTasks = () ->
return (task) ->
@@ -180,5 +182,6 @@ CollectionsModel, TasksBusinessLayer, $location) ->
return task.due
return new TasksController($scope, $window, $routeParams,
- TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location)
+ TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location,
+ SettingsBusinessLayer)
]
\ No newline at end of file
diff --git a/js/app/directives/pane.coffee b/js/app/directives/pane.coffee
new file mode 100644
index 00000000..7d282c4b
--- /dev/null
+++ b/js/app/directives/pane.coffee
@@ -0,0 +1,34 @@
+###
+
+ownCloud - Music
+
+@author Raimund Schlüßler
+@copyright 2013
+
+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 'pane', ->
+ directive =
+ scope:
+ title: '@'
+ require: '^tabs'
+ restrict: 'E'
+ transclude: true
+ replace: true
+ link: (scope, element, attrs, tabsCtrl) ->
+ tabsCtrl.addPane(scope)
+ template: '
[[ ]]
'
diff --git a/js/app/directives/tabs.coffee b/js/app/directives/tabs.coffee
new file mode 100644
index 00000000..d8eb78b5
--- /dev/null
+++ b/js/app/directives/tabs.coffee
@@ -0,0 +1,36 @@
+###
+
+ownCloud - Music
+
+@author Raimund Schlüßler
+@copyright 2013
+
+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 'tabs', ->
+ directive =
+ restrict: 'E',
+ scope: {},
+ controller: ($scope, $element) ->
+ panes = $scope.panes = []
+ $scope.select = (pane) ->
+ angular.forEach(panes, (pane) ->
+ pane.selected = false
+ )
+ pane.selected = true
+ this.addPane = (pane) ->
+ $scope.select(pane) if (panes.length == 0)
+ panes.push(pane)
\ No newline at end of file
diff --git a/js/app/services/businesslayer/settingsbusinesslayer.coffee b/js/app/services/businesslayer/settingsbusinesslayer.coffee
new file mode 100644
index 00000000..44ea4d99
--- /dev/null
+++ b/js/app/services/businesslayer/settingsbusinesslayer.coffee
@@ -0,0 +1,47 @@
+###
+
+ownCloud - News
+
+@author Bernhard Posselt
+@copyright 2012 Bernhard Posselt dev@bernhard-posselt.com
+
+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',
+(Persistence, SettingsModel) ->
+
+ class SettingsBusinessLayer
+
+ constructor: (@_persistence, @_$settingsmodel) ->
+
+ updateModel: () ->
+ success = () =>
+
+ @_persistence.getCollections(success, true)
+
+ setVisibility: (collectionID, visibility) ->
+ @_persistence.setVisibility(collectionID, visibility)
+
+ toggle: (type, setting) ->
+ @_$settingsmodel.toggle(type, setting)
+ value = @_$settingsmodel.getById(type)[setting]
+ @_persistence.setting(type, setting, value)
+
+ return new SettingsBusinessLayer(Persistence, SettingsModel)
+
+]
\ No newline at end of file
diff --git a/js/app/services/businesslayer/tasksbusinesslayer.coffee b/js/app/services/businesslayer/tasksbusinesslayer.coffee
index 84b998b5..dffe5156 100644
--- a/js/app/services/businesslayer/tasksbusinesslayer.coffee
+++ b/js/app/services/businesslayer/tasksbusinesslayer.coffee
@@ -79,6 +79,8 @@ angular.module('Tasks').factory 'TasksBusinessLayer',
due.hour(date.hour()).minute(date.minute())
else
due = date
+ else if type == 'all'
+ due = date
else
return
@_$tasksmodel.setDueDate(taskID,due.format('YYYYMMDDTHHmmss'))
@@ -308,7 +310,7 @@ angular.module('Tasks').factory 'TasksBusinessLayer',
when 'uncompleted'
@uncompleteTask(taskID)
when 'today'
- @setDueDate(taskID,moment().format("YYYYMMDDTHHmmss"))
+ @setDue(taskID,moment().startOf('day').add('h',12),'all')
when 'week', 'all'
else
@changeCalendarId(taskID,listID)
@@ -319,6 +321,9 @@ angular.module('Tasks').factory 'TasksBusinessLayer',
@_$tasksmodel.removeVoid()
@_persistence.getTasks(success, true)
+ setShowHidden: (showHidden) ->
+ @_persistence.setShowHidden(showHidden)
+
return new TasksBusinessLayer(TasksModel, Persistence)
diff --git a/js/app/services/models/collectionsmodel.coffee b/js/app/services/models/collectionsmodel.coffee
index c804deac..5debf5a4 100644
--- a/js/app/services/models/collectionsmodel.coffee
+++ b/js/app/services/models/collectionsmodel.coffee
@@ -21,41 +21,13 @@ License along with this library. If not, see .
###
angular.module('Tasks').factory 'CollectionsModel',
-['TasksModel', '_Model', '_EqualQuery', 'Utils',
-(TasksModel, _Model, _EqualQuery, Utils) ->
+['TasksModel', '_Model',
+(TasksModel, _Model) ->
class CollectionsModel extends _Model
- constructor: (@_$tasksmodel, @_utils) ->
+ constructor: (@_$tasksmodel) ->
@_nameCache = {}
- @_$collections = [
- {
- id: "starred"
- displayname: t('tasks_enhanced','Important')
- },
- {
- id: "today"
- displayname: t('tasks_enhanced', 'Today')
- },
- {
- id: "week"
- displayname: t('tasks_enhanced', 'Week')
- },
- {
- id: "all",
- displayname: t('tasks_enhanced', 'All')
- },
- {
- id: "current",
- displayname: t('tasks_enhanced', 'Current')
- },
- {
- id: "completed"
- displayname: t('tasks_enhanced', 'Done')
- }
- ]
super()
- for collection in @_$collections
- @add(collection)
add: (data, clearCache=true) ->
@_nameCache[data.displayname] = data
@@ -92,5 +64,5 @@ angular.module('Tasks').factory 'CollectionsModel',
else
return ''
- return new CollectionsModel(TasksModel, Utils)
+ return new CollectionsModel(TasksModel)
]
\ No newline at end of file
diff --git a/js/app/services/models/settingsmodel.coffee b/js/app/services/models/settingsmodel.coffee
new file mode 100644
index 00000000..df8e28c0
--- /dev/null
+++ b/js/app/services/models/settingsmodel.coffee
@@ -0,0 +1,42 @@
+###
+
+ownCloud - Tasks
+
+@author Raimund Schlüßler
+@copyright 2013
+
+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 'SettingsModel',
+['_Model',
+(_Model) ->
+ class SettingsModel extends _Model
+
+ constructor: () ->
+ @_nameCache = {}
+ super()
+
+ add: (data, clearCache=true) ->
+ @_nameCache[data.displayname] = data
+ if angular.isDefined(data.id)
+ super(data, clearCache)
+
+ toggle: (type, setting) ->
+ set = @getById(type)
+ @getById(type)[setting] = !set[setting]
+
+ return new SettingsModel()
+]
\ No newline at end of file
diff --git a/js/app/services/persistence.coffee b/js/app/services/persistence.coffee
index dbfbeba3..212e6b58 100644
--- a/js/app/services/persistence.coffee
+++ b/js/app/services/persistence.coffee
@@ -34,11 +34,76 @@ angular.module('Tasks').factory 'Persistence',
successCallback = =>
@deferred.resolve()
+ @getCollections()
+ @getSettings()
@getLists()
@getTasks(successCallback)
@deferred.promise
+ getCollections: (onSuccess, showLoading=true) ->
+ onSuccess or= ->
+
+ if showLoading
+ @_Loading.increase()
+ successCallbackWrapper = (data) =>
+ onSuccess()
+ @_Loading.decrease()
+ failureCallbackWrapper = (data) =>
+ @_Loading.decrease()
+ else
+ successCallbackWrapper = (data) =>
+ onSuccess()
+ failureCallbackWrapper = (data) =>
+
+ params =
+ onSuccess: successCallbackWrapper
+ onFailure: failureCallbackWrapper
+
+ @_request.get '/apps/tasks_enhanced/collections', params
+
+ getSettings: (onSuccess, showLoading=true) ->
+ onSuccess or= ->
+
+ if showLoading
+ @_Loading.increase()
+ successCallbackWrapper = (data) =>
+ onSuccess()
+ @_Loading.decrease()
+ failureCallbackWrapper = (data) =>
+ @_Loading.decrease()
+ else
+ successCallbackWrapper = (data) =>
+ onSuccess()
+ failureCallbackWrapper = (data) =>
+
+ params =
+ onSuccess: successCallbackWrapper
+ onFailure: failureCallbackWrapper
+
+ @_request.get '/apps/tasks_enhanced/settings', params
+
+ setVisibility: (collectionID, visibility) ->
+ params =
+ routeParams:
+ collectionID: collectionID
+ visibility: visibility
+
+ @_request.post '/apps/tasks_enhanced/collection/
+ {collectionID}/visibility/{visibility}', params
+
+ setting: (type, setting, value) ->
+ params =
+ routeParams:
+ type: type
+ setting: setting
+ value: +value
+
+ @_request.post '/apps/tasks_enhanced/settings/
+ {type}/{setting}/{value}', params
+
+
+
getLists: (onSuccess, showLoading=true, which='all') ->
onSuccess or= ->
@@ -244,6 +309,14 @@ angular.module('Tasks').factory 'Persistence',
@_request.post '/apps/tasks_enhanced/tasks/{taskID}/note', params
+ setShowHidden: (showHidden) ->
+ params =
+ routeParams:
+ showHidden: +showHidden
+
+ @_request.post '/apps/tasks_enhanced/settings/showhidden/{showHidden}',
+ params
+
return new Persistence(Request, Loading, $rootScope)
]
\ No newline at end of file
diff --git a/js/app/services/services.coffee b/js/app/services/services.coffee
index e3a15aa8..9b09229a 100644
--- a/js/app/services/services.coffee
+++ b/js/app/services/services.coffee
@@ -37,11 +37,13 @@ angular.module('Tasks').factory 'Loading', ['_Loading', (_Loading) ->
# ]
angular.module('Tasks').factory 'Publisher',
-['_Publisher', 'ListsModel', 'TasksModel',
-(_Publisher, ListsModel, TasksModel) ->
+['_Publisher', 'ListsModel', 'TasksModel', 'CollectionsModel', 'SettingsModel',
+(_Publisher, ListsModel, TasksModel, CollectionsModel, SettingsModel) ->
# register items at publisher to automatically add incoming items
publisher = new _Publisher()
+ publisher.subscribeObjectTo(CollectionsModel, 'collections')
+ publisher.subscribeObjectTo(SettingsModel, 'settings')
publisher.subscribeObjectTo(ListsModel, 'lists')
publisher.subscribeObjectTo(TasksModel, 'tasks')
diff --git a/js/app/services/status.coffee b/js/app/services/status.coffee
index aefa3eee..3c660c0d 100644
--- a/js/app/services/status.coffee
+++ b/js/app/services/status.coffee
@@ -26,7 +26,6 @@ angular.module('Tasks').factory 'Status',
constructor: () ->
@_$status = {
- showhidden: true
searchActive: false
addingList: false
focusTaskInput: false
diff --git a/js/public/app.js b/js/public/app.js
index 328f04a8..f3673a41 100644
--- a/js/public/app.js
+++ b/js/public/app.js
@@ -12,14 +12,14 @@
(function() {
- angular.module('Tasks', ['OC', 'ngRoute', 'ngAnimate']).config([
+ angular.module('Tasks', ['OC', 'ngRoute', 'ngAnimate', 'ui.bootstrap']).config([
'$provide', '$routeProvider', '$interpolateProvider', function($provide, $routeProvider, $interpolateProvider) {
var config;
$provide.value('Config', config = {
markReadTimeout: 500,
taskUpdateInterval: 1000 * 600
});
- $routeProvider.when('/lists/:listID', {}).when('/lists/:listID/edit/:listparameter', {}).when('/lists/:listID/tasks/:taskID', {}).when('/lists/:listID/tasks/:taskID/edit/:parameter', {}).when('/search/:searchString', {}).when('/search/:searchString/tasks/:taskID', {}).when('/search/:searchString/tasks/:taskID/edit/:parameter', {}).otherwise({
+ $routeProvider.when('/lists/:listID', {}).when('/lists/:listID/edit/:listparameter', {}).when('/lists/:listID/tasks/:taskID', {}).when('/lists/:listID/tasks/:taskID/settings', {}).when('/lists/:listID/tasks/:taskID/edit/:parameter', {}).when('/search/:searchString', {}).when('/search/:searchString/tasks/:taskID', {}).when('/search/:searchString/tasks/:taskID/edit/:parameter', {}).otherwise({
redirectTo: '/lists/all'
});
/*
@@ -227,6 +227,26 @@
}).call(this);
+(function() {
+ angular.module('Tasks').directive('pane', function() {
+ var directive;
+ return directive = {
+ scope: {
+ title: '@'
+ },
+ require: '^tabs',
+ restrict: 'E',
+ transclude: true,
+ replace: true,
+ link: function(scope, element, attrs, tabsCtrl) {
+ return tabsCtrl.addPane(scope);
+ },
+ template: '[[ ]]
'
+ };
+ });
+
+}).call(this);
+
(function() {
angular.module('Tasks').directive('stopEvent', function() {
return {
@@ -241,6 +261,33 @@
}).call(this);
+(function() {
+ angular.module('Tasks').directive('tabs', function() {
+ var directive;
+ return directive = {
+ restrict: 'E',
+ scope: {},
+ controller: function($scope, $element) {
+ var panes;
+ panes = $scope.panes = [];
+ $scope.select = function(pane) {
+ angular.forEach(panes, function(pane) {
+ return pane.selected = false;
+ });
+ return pane.selected = true;
+ };
+ return this.addPane = function(pane) {
+ if (panes.length === 0) {
+ $scope.select(pane);
+ }
+ return panes.push(pane);
+ };
+ }
+ };
+ });
+
+}).call(this);
+
(function() {
angular.module('Tasks').directive('timepicker', function() {
return {
@@ -283,10 +330,10 @@
(function() {
angular.module('Tasks').controller('AppController', [
- '$scope', 'Persistence', '$route', 'Status', '$timeout', '$location', '$routeParams', 'Loading', function($scope, Persistence, $route, status, $timeout, $location, $routeParams, Loading) {
+ '$scope', 'Persistence', '$route', 'Status', '$timeout', '$location', '$routeParams', 'Loading', '$modal', 'SettingsModel', function($scope, Persistence, $route, status, $timeout, $location, $routeParams, Loading, $modal, SettingsModel) {
var AppController;
AppController = (function() {
- function AppController(_$scope, _persistence, _$route, _$status, _$timeout, _$location, _$routeparams, _Loading) {
+ function AppController(_$scope, _persistence, _$route, _$status, _$timeout, _$location, _$routeparams, _Loading, _$modal, _$settingsmodel) {
var successCallback,
_this = this;
this._$scope = _$scope;
@@ -297,10 +344,13 @@
this._$location = _$location;
this._$routeparams = _$routeparams;
this._Loading = _Loading;
+ this._$modal = _$modal;
+ this._$settingsmodel = _$settingsmodel;
this._$scope.initialized = false;
this._$scope.status = this._$status.getStatus();
this._$scope.route = this._$routeparams;
this._$scope.status.newListName = "";
+ this._$scope.settingsmodel = this._$settingsmodel;
successCallback = function() {
return _this._$scope.initialized = true;
};
@@ -318,12 +368,20 @@
this._$scope.isLoading = function() {
return _Loading.isLoading();
};
+ this._$scope.showSettings = function() {
+ return _$scope.modalInstance = _$modal.open({
+ templateUrl: 'part.settings.html',
+ controller: 'SettingsController',
+ backdrop: true,
+ windowClass: 'test'
+ });
+ };
}
return AppController;
})();
- return new AppController($scope, Persistence, $route, status, $timeout, $location, $routeParams, Loading);
+ return new AppController($scope, Persistence, $route, status, $timeout, $location, $routeParams, Loading, $modal, SettingsModel);
}
]);
@@ -699,6 +757,18 @@
this._$scope.getCollectionCount = function(collectionID) {
return _$collectionsmodel.getCount(collectionID);
};
+ this._$scope.hideCollection = function(collectionID) {
+ var collection;
+ collection = _$collectionsmodel.getById(collectionID);
+ switch (collection.show) {
+ case 0:
+ return true;
+ case 1:
+ return false;
+ case 2:
+ return this.getCollectionCount(collectionID) < 1;
+ }
+ };
this._$scope.getCollectionString = function(collectionID) {
return _$collectionsmodel.getCountString(collectionID);
};
@@ -773,12 +843,59 @@
}).call(this);
+(function() {
+ angular.module('Tasks').controller('SettingsController', [
+ '$scope', '$window', 'Status', '$location', '$modalInstance', 'CollectionsModel', 'SettingsBusinessLayer', function($scope, $window, Status, $location, $modalInstance, CollectionsModel, SettingsBusinessLayer) {
+ var SettingsController;
+ SettingsController = (function() {
+ function SettingsController(_$scope, _$window, _$status, _$location, _$modalInstance, _$collectionsmodel, _$settingsbusinesslayer) {
+ var _this = this;
+ this._$scope = _$scope;
+ this._$window = _$window;
+ this._$status = _$status;
+ this._$location = _$location;
+ this._$modalInstance = _$modalInstance;
+ this._$collectionsmodel = _$collectionsmodel;
+ this._$settingsbusinesslayer = _$settingsbusinesslayer;
+ this._$scope.status = this._$status.getStatus();
+ this._$scope.collections = this._$collectionsmodel.getAll();
+ this._$scope.collectionOptions = [
+ {
+ id: 0,
+ name: t('tasks_enhanced', 'Hidden')
+ }, {
+ id: 1,
+ name: t('tasks_enhanced', 'Visible')
+ }, {
+ id: 2,
+ name: t('tasks_enhanced', 'Automatic')
+ }
+ ];
+ this._$scope.ok = function() {
+ return $modalInstance.close();
+ };
+ this._$scope.setVisibility = function(collectionID) {
+ var collection;
+ collection = _$collectionsmodel.getById(collectionID);
+ return _$settingsbusinesslayer.setVisibility(collectionID, collection.show);
+ };
+ }
+
+ return SettingsController;
+
+ })();
+ return new SettingsController($scope, $window, Status, $location, $modalInstance, CollectionsModel, SettingsBusinessLayer);
+ }
+ ]);
+
+}).call(this);
+
(function() {
angular.module('Tasks').controller('TasksController', [
- '$scope', '$window', '$routeParams', 'TasksModel', 'ListsModel', 'CollectionsModel', 'TasksBusinessLayer', '$location', function($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location) {
+ '$scope', '$window', '$routeParams', 'TasksModel', 'ListsModel', 'CollectionsModel', 'TasksBusinessLayer', '$location', 'SettingsBusinessLayer', function($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location, SettingsBusinessLayer) {
var TasksController;
TasksController = (function() {
- function TasksController(_$scope, _$window, _$routeParams, _$tasksmodel, _$listsmodel, _$collectionsmodel, _tasksbusinesslayer, $location) {
+ function TasksController(_$scope, _$window, _$routeParams, _$tasksmodel, _$listsmodel, _$collectionsmodel, _tasksbusinesslayer, $location, _settingsbusinesslayer) {
this._$scope = _$scope;
this._$window = _$window;
this._$routeParams = _$routeParams;
@@ -787,6 +904,7 @@
this._$collectionsmodel = _$collectionsmodel;
this._tasksbusinesslayer = _tasksbusinesslayer;
this.$location = $location;
+ this._settingsbusinesslayer = _settingsbusinesslayer;
this._$scope.tasks = this._$tasksmodel.getAll();
this._$scope.lists = this._$listsmodel.getAll();
this._$scope.days = [0, 1, 2, 3, 4, 5, 6];
@@ -853,7 +971,7 @@
}
};
this._$scope.toggleHidden = function() {
- return _$scope.status.showhidden = !_$scope.status.showhidden;
+ return _settingsbusinesslayer.toggle('various', 'showHidden');
};
this._$scope.filterTasks = function() {
return function(task) {
@@ -942,7 +1060,7 @@
return TasksController;
})();
- return new TasksController($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location);
+ return new TasksController($scope, $window, $routeParams, TasksModel, ListsModel, CollectionsModel, TasksBusinessLayer, $location, SettingsBusinessLayer);
}
]);
@@ -1010,6 +1128,43 @@
}).call(this);
+(function() {
+ angular.module('Tasks').factory('SettingsBusinessLayer', [
+ 'Persistence', 'SettingsModel', function(Persistence, SettingsModel) {
+ var SettingsBusinessLayer;
+ 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) {
+ var value;
+ this._$settingsmodel.toggle(type, setting);
+ value = this._$settingsmodel.getById(type)[setting];
+ return this._persistence.setting(type, setting, value);
+ };
+
+ return SettingsBusinessLayer;
+
+ })();
+ return new SettingsBusinessLayer(Persistence, SettingsModel);
+ }
+ ]);
+
+}).call(this);
+
(function() {
angular.module('Tasks').factory('TasksBusinessLayer', [
'TasksModel', 'Persistence', function(TasksModel, Persistence) {
@@ -1093,6 +1248,8 @@
} else {
due = date;
}
+ } else if (type === 'all') {
+ due = date;
} else {
return;
}
@@ -1376,7 +1533,7 @@
case 'uncompleted':
return this.uncompleteTask(taskID);
case 'today':
- return this.setDueDate(taskID, moment().format("YYYYMMDDTHHmmss"));
+ return this.setDue(taskID, moment().startOf('day').add('h', 12), 'all');
case 'week':
case 'all':
break;
@@ -1395,6 +1552,10 @@
return this._persistence.getTasks(success, true);
};
+ TasksBusinessLayer.prototype.setShowHidden = function(showHidden) {
+ return this._persistence.setShowHidden(showHidden);
+ };
+
return TasksBusinessLayer;
})();
@@ -1409,43 +1570,15 @@
__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; };
angular.module('Tasks').factory('CollectionsModel', [
- 'TasksModel', '_Model', '_EqualQuery', 'Utils', function(TasksModel, _Model, _EqualQuery, Utils) {
+ 'TasksModel', '_Model', function(TasksModel, _Model) {
var CollectionsModel;
CollectionsModel = (function(_super) {
__extends(CollectionsModel, _super);
- function CollectionsModel(_$tasksmodel, _utils) {
- var collection, _i, _len, _ref;
+ function CollectionsModel(_$tasksmodel) {
this._$tasksmodel = _$tasksmodel;
- this._utils = _utils;
this._nameCache = {};
- this._$collections = [
- {
- id: "starred",
- displayname: t('tasks_enhanced', 'Important')
- }, {
- id: "today",
- displayname: t('tasks_enhanced', 'Today')
- }, {
- id: "week",
- displayname: t('tasks_enhanced', 'Week')
- }, {
- id: "all",
- displayname: t('tasks_enhanced', 'All')
- }, {
- id: "current",
- displayname: t('tasks_enhanced', 'Current')
- }, {
- id: "completed",
- displayname: t('tasks_enhanced', 'Done')
- }
- ];
CollectionsModel.__super__.constructor.call(this);
- _ref = this._$collections;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- collection = _ref[_i];
- this.add(collection);
- }
}
CollectionsModel.prototype.add = function(data, clearCache) {
@@ -1513,7 +1646,7 @@
return CollectionsModel;
})(_Model);
- return new CollectionsModel(TasksModel, Utils);
+ return new CollectionsModel(TasksModel);
}
]);
@@ -1677,6 +1810,46 @@
}).call(this);
+(function() {
+ 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; };
+
+ angular.module('Tasks').factory('SettingsModel', [
+ '_Model', function(_Model) {
+ var SettingsModel;
+ SettingsModel = (function(_super) {
+ __extends(SettingsModel, _super);
+
+ function SettingsModel() {
+ this._nameCache = {};
+ SettingsModel.__super__.constructor.call(this);
+ }
+
+ 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);
+ }
+ };
+
+ SettingsModel.prototype.toggle = function(type, setting) {
+ var set;
+ set = this.getById(type);
+ return this.getById(type)[setting] = !set[setting];
+ };
+
+ return SettingsModel;
+
+ })(_Model);
+ return new SettingsModel();
+ }
+ ]);
+
+}).call(this);
+
(function() {
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; };
@@ -1925,11 +2098,96 @@
successCallback = function() {
return _this.deferred.resolve();
};
+ this.getCollections();
+ this.getSettings();
this.getLists();
this.getTasks(successCallback);
return this.deferred.promise;
};
+ Persistence.prototype.getCollections = function(onSuccess, showLoading) {
+ var failureCallbackWrapper, params, successCallbackWrapper,
+ _this = this;
+ if (showLoading == null) {
+ showLoading = true;
+ }
+ 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_enhanced/collections', params);
+ };
+
+ Persistence.prototype.getSettings = function(onSuccess, showLoading) {
+ var failureCallbackWrapper, params, successCallbackWrapper,
+ _this = this;
+ if (showLoading == null) {
+ showLoading = true;
+ }
+ 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_enhanced/settings', params);
+ };
+
+ Persistence.prototype.setVisibility = function(collectionID, visibility) {
+ var params;
+ params = {
+ routeParams: {
+ collectionID: collectionID,
+ visibility: visibility
+ }
+ };
+ return this._request.post('/apps/tasks_enhanced/collection/\
+ {collectionID}/visibility/{visibility}', params);
+ };
+
+ Persistence.prototype.setting = function(type, setting, value) {
+ var params;
+ params = {
+ routeParams: {
+ type: type,
+ setting: setting,
+ value: +value
+ }
+ };
+ return this._request.post('/apps/tasks_enhanced/settings/\
+ {type}/{setting}/{value}', params);
+ };
+
Persistence.prototype.getLists = function(onSuccess, showLoading, which) {
var failureCallbackWrapper, params, successCallbackWrapper,
_this = this;
@@ -2223,6 +2481,16 @@
return this._request.post('/apps/tasks_enhanced/tasks/{taskID}/note', params);
};
+ Persistence.prototype.setShowHidden = function(showHidden) {
+ var params;
+ params = {
+ routeParams: {
+ showHidden: +showHidden
+ }
+ };
+ return this._request.post('/apps/tasks_enhanced/settings/showhidden/{showHidden}', params);
+ };
+
return Persistence;
})();
@@ -2246,9 +2514,11 @@
]);
angular.module('Tasks').factory('Publisher', [
- '_Publisher', 'ListsModel', 'TasksModel', function(_Publisher, ListsModel, TasksModel) {
+ '_Publisher', 'ListsModel', 'TasksModel', 'CollectionsModel', 'SettingsModel', function(_Publisher, ListsModel, TasksModel, CollectionsModel, SettingsModel) {
var publisher;
publisher = new _Publisher();
+ publisher.subscribeObjectTo(CollectionsModel, 'collections');
+ publisher.subscribeObjectTo(SettingsModel, 'settings');
publisher.subscribeObjectTo(ListsModel, 'lists');
publisher.subscribeObjectTo(TasksModel, 'tasks');
return publisher;
@@ -2264,7 +2534,6 @@
Status = (function() {
function Status() {
this._$status = {
- showhidden: true,
searchActive: false,
addingList: false,
focusTaskInput: false
diff --git a/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.js b/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.js
new file mode 100644
index 00000000..a5b865d2
--- /dev/null
+++ b/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.js
@@ -0,0 +1,817 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 0.10.0 - 2014-01-15
+ * License: MIT
+ */
+angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.modal","ui.bootstrap.tabs"]);
+angular.module("ui.bootstrap.tpls", ["template/modal/backdrop.html","template/modal/window.html","template/tabs/tab.html","template/tabs/tabset.html"]);
+angular.module('ui.bootstrap.transition', [])
+
+/**
+ * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
+ * @param {DOMElement} element The DOMElement that will be animated.
+ * @param {string|object|function} trigger The thing that will cause the transition to start:
+ * - As a string, it represents the css class to be added to the element.
+ * - As an object, it represents a hash of style attributes to be applied to the element.
+ * - As a function, it represents a function to be called that will cause the transition to occur.
+ * @return {Promise} A promise that is resolved when the transition finishes.
+ */
+.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
+
+ var $transition = function(element, trigger, options) {
+ options = options || {};
+ var deferred = $q.defer();
+ var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
+
+ var transitionEndHandler = function(event) {
+ $rootScope.$apply(function() {
+ element.unbind(endEventName, transitionEndHandler);
+ deferred.resolve(element);
+ });
+ };
+
+ if (endEventName) {
+ element.bind(endEventName, transitionEndHandler);
+ }
+
+ // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
+ $timeout(function() {
+ if ( angular.isString(trigger) ) {
+ element.addClass(trigger);
+ } else if ( angular.isFunction(trigger) ) {
+ trigger(element);
+ } else if ( angular.isObject(trigger) ) {
+ element.css(trigger);
+ }
+ //If browser does not support transitions, instantly resolve
+ if ( !endEventName ) {
+ deferred.resolve(element);
+ }
+ });
+
+ // Add our custom cancel function to the promise that is returned
+ // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
+ // i.e. it will therefore never raise a transitionEnd event for that transition
+ deferred.promise.cancel = function() {
+ if ( endEventName ) {
+ element.unbind(endEventName, transitionEndHandler);
+ }
+ deferred.reject('Transition cancelled');
+ };
+
+ return deferred.promise;
+ };
+
+ // Work out the name of the transitionEnd event
+ var transElement = document.createElement('trans');
+ var transitionEndEventNames = {
+ 'WebkitTransition': 'webkitTransitionEnd',
+ 'MozTransition': 'transitionend',
+ 'OTransition': 'oTransitionEnd',
+ 'transition': 'transitionend'
+ };
+ var animationEndEventNames = {
+ 'WebkitTransition': 'webkitAnimationEnd',
+ 'MozTransition': 'animationend',
+ 'OTransition': 'oAnimationEnd',
+ 'transition': 'animationend'
+ };
+ function findEndEventName(endEventNames) {
+ for (var name in endEventNames){
+ if (transElement.style[name] !== undefined) {
+ return endEventNames[name];
+ }
+ }
+ }
+ $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
+ $transition.animationEndEventName = findEndEventName(animationEndEventNames);
+ return $transition;
+}]);
+
+angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])
+
+/**
+ * A helper, internal data structure that acts as a map but also allows getting / removing
+ * elements in the LIFO order
+ */
+ .factory('$$stackedMap', function () {
+ return {
+ createNew: function () {
+ var stack = [];
+
+ return {
+ add: function (key, value) {
+ stack.push({
+ key: key,
+ value: value
+ });
+ },
+ get: function (key) {
+ for (var i = 0; i < stack.length; i++) {
+ if (key == stack[i].key) {
+ return stack[i];
+ }
+ }
+ },
+ keys: function() {
+ var keys = [];
+ for (var i = 0; i < stack.length; i++) {
+ keys.push(stack[i].key);
+ }
+ return keys;
+ },
+ top: function () {
+ return stack[stack.length - 1];
+ },
+ remove: function (key) {
+ var idx = -1;
+ for (var i = 0; i < stack.length; i++) {
+ if (key == stack[i].key) {
+ idx = i;
+ break;
+ }
+ }
+ return stack.splice(idx, 1)[0];
+ },
+ removeTop: function () {
+ return stack.splice(stack.length - 1, 1)[0];
+ },
+ length: function () {
+ return stack.length;
+ }
+ };
+ }
+ };
+ })
+
+/**
+ * A helper directive for the $modal service. It creates a backdrop element.
+ */
+ .directive('modalBackdrop', ['$timeout', function ($timeout) {
+ return {
+ restrict: 'EA',
+ replace: true,
+ templateUrl: 'template/modal/backdrop.html',
+ link: function (scope) {
+
+ scope.animate = false;
+
+ //trigger CSS transitions
+ $timeout(function () {
+ scope.animate = true;
+ });
+ }
+ };
+ }])
+
+ .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
+ return {
+ restrict: 'EA',
+ scope: {
+ index: '@',
+ animate: '='
+ },
+ replace: true,
+ transclude: true,
+ templateUrl: 'template/modal/window.html',
+ link: function (scope, element, attrs) {
+ scope.windowClass = attrs.windowClass || '';
+
+ $timeout(function () {
+ // trigger CSS transitions
+ scope.animate = true;
+ // focus a freshly-opened modal
+ element[0].focus();
+ });
+
+ scope.close = function (evt) {
+ var modal = $modalStack.getTop();
+ if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ $modalStack.dismiss(modal.key, 'backdrop click');
+ }
+ };
+ }
+ };
+ }])
+
+ .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
+ function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
+
+ var OPENED_MODAL_CLASS = 'modal-open';
+
+ var backdropDomEl, backdropScope;
+ var openedWindows = $$stackedMap.createNew();
+ var $modalStack = {};
+
+ function backdropIndex() {
+ var topBackdropIndex = -1;
+ var opened = openedWindows.keys();
+ for (var i = 0; i < opened.length; i++) {
+ if (openedWindows.get(opened[i]).value.backdrop) {
+ topBackdropIndex = i;
+ }
+ }
+ return topBackdropIndex;
+ }
+
+ $rootScope.$watch(backdropIndex, function(newBackdropIndex){
+ if (backdropScope) {
+ backdropScope.index = newBackdropIndex;
+ }
+ });
+
+ function removeModalWindow(modalInstance) {
+
+ var body = $document.find('#tasks_enhanced_wrapper').eq(0);
+ var modalWindow = openedWindows.get(modalInstance).value;
+
+ //clean up the stack
+ openedWindows.remove(modalInstance);
+
+ //remove window DOM element
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop);
+ body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
+ }
+
+ function checkRemoveBackdrop() {
+ //remove backdrop if no longer needed
+ if (backdropDomEl && backdropIndex() == -1) {
+ var backdropScopeRef = backdropScope;
+ removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
+ backdropScopeRef.$destroy();
+ backdropScopeRef = null;
+ });
+ backdropDomEl = undefined;
+ backdropScope = undefined;
+ }
+ }
+
+ function removeAfterAnimate(domEl, scope, emulateTime, done) {
+ // Closing animation
+ scope.animate = false;
+
+ var transitionEndEventName = $transition.transitionEndEventName;
+ if (transitionEndEventName) {
+ // transition out
+ var timeout = $timeout(afterAnimating, emulateTime);
+
+ domEl.bind(transitionEndEventName, function () {
+ $timeout.cancel(timeout);
+ afterAnimating();
+ scope.$apply();
+ });
+ } else {
+ // Ensure this call is async
+ $timeout(afterAnimating, 0);
+ }
+
+ function afterAnimating() {
+ if (afterAnimating.done) {
+ return;
+ }
+ afterAnimating.done = true;
+
+ domEl.remove();
+ if (done) {
+ done();
+ }
+ }
+ }
+
+ $document.bind('keydown', function (evt) {
+ var modal;
+
+ if (evt.which === 27) {
+ modal = openedWindows.top();
+ if (modal && modal.value.keyboard) {
+ $rootScope.$apply(function () {
+ $modalStack.dismiss(modal.key);
+ });
+ }
+ }
+ });
+
+ $modalStack.open = function (modalInstance, modal) {
+
+ openedWindows.add(modalInstance, {
+ deferred: modal.deferred,
+ modalScope: modal.scope,
+ backdrop: modal.backdrop,
+ keyboard: modal.keyboard
+ });
+
+ var body = $document.find('#tasks_enhanced_wrapper').eq(0),
+ currBackdropIndex = backdropIndex();
+
+ if (currBackdropIndex >= 0 && !backdropDomEl) {
+ backdropScope = $rootScope.$new(true);
+ backdropScope.index = currBackdropIndex;
+ backdropDomEl = $compile('
')(backdropScope);
+ body.append(backdropDomEl);
+ }
+
+ var angularDomEl = angular.element('
');
+ angularDomEl.attr('window-class', modal.windowClass);
+ angularDomEl.attr('index', openedWindows.length() - 1);
+ angularDomEl.attr('animate', 'animate');
+ angularDomEl.html(modal.content);
+
+ var modalDomEl = $compile(angularDomEl)(modal.scope);
+ openedWindows.top().value.modalDomEl = modalDomEl;
+ body.append(modalDomEl);
+ body.addClass(OPENED_MODAL_CLASS);
+ };
+
+ $modalStack.close = function (modalInstance, result) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ if (modalWindow) {
+ modalWindow.deferred.resolve(result);
+ removeModalWindow(modalInstance);
+ }
+ };
+
+ $modalStack.dismiss = function (modalInstance, reason) {
+ var modalWindow = openedWindows.get(modalInstance).value;
+ if (modalWindow) {
+ modalWindow.deferred.reject(reason);
+ removeModalWindow(modalInstance);
+ }
+ };
+
+ $modalStack.dismissAll = function (reason) {
+ var topModal = this.getTop();
+ while (topModal) {
+ this.dismiss(topModal.key, reason);
+ topModal = this.getTop();
+ }
+ };
+
+ $modalStack.getTop = function () {
+ return openedWindows.top();
+ };
+
+ return $modalStack;
+ }])
+
+ .provider('$modal', function () {
+
+ var $modalProvider = {
+ options: {
+ backdrop: true, //can be also false or 'static'
+ keyboard: true
+ },
+ $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
+ function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
+
+ var $modal = {};
+
+ function getTemplatePromise(options) {
+ return options.template ? $q.when(options.template) :
+ $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
+ return result.data;
+ });
+ }
+
+ function getResolvePromises(resolves) {
+ var promisesArr = [];
+ angular.forEach(resolves, function (value, key) {
+ if (angular.isFunction(value) || angular.isArray(value)) {
+ promisesArr.push($q.when($injector.invoke(value)));
+ }
+ });
+ return promisesArr;
+ }
+
+ $modal.open = function (modalOptions) {
+
+ var modalResultDeferred = $q.defer();
+ var modalOpenedDeferred = $q.defer();
+
+ //prepare an instance of a modal to be injected into controllers and returned to a caller
+ var modalInstance = {
+ result: modalResultDeferred.promise,
+ opened: modalOpenedDeferred.promise,
+ close: function (result) {
+ $modalStack.close(modalInstance, result);
+ },
+ dismiss: function (reason) {
+ $modalStack.dismiss(modalInstance, reason);
+ }
+ };
+
+ //merge and clean up options
+ modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
+ modalOptions.resolve = modalOptions.resolve || {};
+
+ //verify options
+ if (!modalOptions.template && !modalOptions.templateUrl) {
+ throw new Error('One of template or templateUrl options is required.');
+ }
+
+ var templateAndResolvePromise =
+ $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
+
+
+ templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {
+
+ var modalScope = (modalOptions.scope || $rootScope).$new();
+ modalScope.$close = modalInstance.close;
+ modalScope.$dismiss = modalInstance.dismiss;
+
+ var ctrlInstance, ctrlLocals = {};
+ var resolveIter = 1;
+
+ //controllers
+ if (modalOptions.controller) {
+ ctrlLocals.$scope = modalScope;
+ ctrlLocals.$modalInstance = modalInstance;
+ angular.forEach(modalOptions.resolve, function (value, key) {
+ ctrlLocals[key] = tplAndVars[resolveIter++];
+ });
+
+ ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
+ }
+
+ $modalStack.open(modalInstance, {
+ scope: modalScope,
+ deferred: modalResultDeferred,
+ content: tplAndVars[0],
+ backdrop: modalOptions.backdrop,
+ keyboard: modalOptions.keyboard,
+ windowClass: modalOptions.windowClass
+ });
+
+ }, function resolveError(reason) {
+ modalResultDeferred.reject(reason);
+ });
+
+ templateAndResolvePromise.then(function () {
+ modalOpenedDeferred.resolve(true);
+ }, function () {
+ modalOpenedDeferred.reject(false);
+ });
+
+ return modalInstance;
+ };
+
+ return $modal;
+ }]
+ };
+
+ return $modalProvider;
+ });
+
+
+/**
+ * @ngdoc overview
+ * @name ui.bootstrap.tabs
+ *
+ * @description
+ * AngularJS version of the tabs directive.
+ */
+
+angular.module('ui.bootstrap.tabs', [])
+
+.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
+ var ctrl = this,
+ tabs = ctrl.tabs = $scope.tabs = [];
+
+ ctrl.select = function(tab) {
+ angular.forEach(tabs, function(tab) {
+ tab.active = false;
+ });
+ tab.active = true;
+ };
+
+ ctrl.addTab = function addTab(tab) {
+ tabs.push(tab);
+ if (tabs.length === 1 || tab.active) {
+ ctrl.select(tab);
+ }
+ };
+
+ ctrl.removeTab = function removeTab(tab) {
+ var index = tabs.indexOf(tab);
+ //Select a new tab if the tab to be removed is selected
+ if (tab.active && tabs.length > 1) {
+ //If this is the last tab, select the previous tab. else, the next tab.
+ var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;
+ ctrl.select(tabs[newActiveIndex]);
+ }
+ tabs.splice(index, 1);
+ };
+}])
+
+/**
+ * @ngdoc directive
+ * @name ui.bootstrap.tabs.directive:tabset
+ * @restrict EA
+ *
+ * @description
+ * Tabset is the outer container for the tabs directive
+ *
+ * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.
+ * @param {boolean=} justified Whether or not to use justified styling for the tabs.
+ *
+ * @example
+
+
+
+ First Content!
+ Second Content!
+
+
+
+ First Vertical Content!
+ Second Vertical Content!
+
+
+ First Justified Content!
+ Second Justified Content!
+
+
+
+ */
+.directive('tabset', function() {
+ return {
+ restrict: 'EA',
+ transclude: true,
+ replace: true,
+ scope: {},
+ controller: 'TabsetController',
+ templateUrl: 'template/tabs/tabset.html',
+ link: function(scope, element, attrs) {
+ scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;
+ scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;
+ scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs';
+ }
+ };
+})
+
+/**
+ * @ngdoc directive
+ * @name ui.bootstrap.tabs.directive:tab
+ * @restrict EA
+ *
+ * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.
+ * @param {string=} select An expression to evaluate when the tab is selected.
+ * @param {boolean=} active A binding, telling whether or not this tab is selected.
+ * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.
+ *
+ * @description
+ * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.
+ *
+ * @example
+
+
+
+
+ Select item 1, using active binding
+
+
+ Enable/disable item 2, using disabled binding
+
+
+
+ First Tab
+
+ Alert me!
+ Second Tab, with alert callback and html heading!
+
+
+ {{item.content}}
+
+
+
+
+
+ function TabsDemoCtrl($scope) {
+ $scope.items = [
+ { title:"Dynamic Title 1", content:"Dynamic Item 0" },
+ { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true }
+ ];
+
+ $scope.alertMe = function() {
+ setTimeout(function() {
+ alert("You've selected the alert tab!");
+ });
+ };
+ };
+
+
+ */
+
+/**
+ * @ngdoc directive
+ * @name ui.bootstrap.tabs.directive:tabHeading
+ * @restrict EA
+ *
+ * @description
+ * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.
+ *
+ * @example
+
+
+
+
+ HTML in my titles?!
+ And some content, too!
+
+
+ Icon heading?!?
+ That's right.
+
+
+
+
+ */
+.directive('tab', ['$parse', function($parse) {
+ return {
+ require: '^tabset',
+ restrict: 'EA',
+ replace: true,
+ templateUrl: 'template/tabs/tab.html',
+ transclude: true,
+ scope: {
+ heading: '@',
+ onSelect: '&select', //This callback is called in contentHeadingTransclude
+ //once it inserts the tab's content into the dom
+ onDeselect: '&deselect'
+ },
+ controller: function() {
+ //Empty controller so other directives can require being 'under' a tab
+ },
+ compile: function(elm, attrs, transclude) {
+ return function postLink(scope, elm, attrs, tabsetCtrl) {
+ var getActive, setActive;
+ if (attrs.active) {
+ getActive = $parse(attrs.active);
+ setActive = getActive.assign;
+ scope.$parent.$watch(getActive, function updateActive(value, oldVal) {
+ // Avoid re-initializing scope.active as it is already initialized
+ // below. (watcher is called async during init with value ===
+ // oldVal)
+ if (value !== oldVal) {
+ scope.active = !!value;
+ }
+ });
+ scope.active = getActive(scope.$parent);
+ } else {
+ setActive = getActive = angular.noop;
+ }
+
+ scope.$watch('active', function(active) {
+ // Note this watcher also initializes and assigns scope.active to the
+ // attrs.active expression.
+ setActive(scope.$parent, active);
+ if (active) {
+ tabsetCtrl.select(scope);
+ scope.onSelect();
+ } else {
+ scope.onDeselect();
+ }
+ });
+
+ scope.disabled = false;
+ if ( attrs.disabled ) {
+ scope.$parent.$watch($parse(attrs.disabled), function(value) {
+ scope.disabled = !! value;
+ });
+ }
+
+ scope.select = function() {
+ if ( ! scope.disabled ) {
+ scope.active = true;
+ }
+ };
+
+ tabsetCtrl.addTab(scope);
+ scope.$on('$destroy', function() {
+ tabsetCtrl.removeTab(scope);
+ });
+
+
+ //We need to transclude later, once the content container is ready.
+ //when this link happens, we're inside a tab heading.
+ scope.$transcludeFn = transclude;
+ };
+ }
+ };
+}])
+
+.directive('tabHeadingTransclude', [function() {
+ return {
+ restrict: 'A',
+ require: '^tab',
+ link: function(scope, elm, attrs, tabCtrl) {
+ scope.$watch('headingElement', function updateHeadingElement(heading) {
+ if (heading) {
+ elm.html('');
+ elm.append(heading);
+ }
+ });
+ }
+ };
+}])
+
+.directive('tabContentTransclude', function() {
+ return {
+ restrict: 'A',
+ require: '^tabset',
+ link: function(scope, elm, attrs) {
+ var tab = scope.$eval(attrs.tabContentTransclude);
+
+ //Now our tab is ready to be transcluded: both the tab heading area
+ //and the tab content area are loaded. Transclude 'em both.
+ tab.$transcludeFn(tab.$parent, function(contents) {
+ angular.forEach(contents, function(node) {
+ if (isTabHeading(node)) {
+ //Let tabHeadingTransclude know.
+ tab.headingElement = node;
+ } else {
+ elm.append(node);
+ }
+ });
+ });
+ }
+ };
+ function isTabHeading(node) {
+ return node.tagName && (
+ node.hasAttribute('tab-heading') ||
+ node.hasAttribute('data-tab-heading') ||
+ node.tagName.toLowerCase() === 'tab-heading' ||
+ node.tagName.toLowerCase() === 'data-tab-heading'
+ );
+ }
+})
+
+;
+
+angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/modal/backdrop.html",
+ "
");
+}]);
+
+angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/modal/window.html",
+ "");
+}]);
+
+angular.module("template/tabs/pane.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/tabs/pane.html",
+ "
\n" +
+ "");
+}]);
+
+angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/tabs/tab.html",
+ "\n" +
+ " {{heading}} \n" +
+ " \n" +
+ "");
+}]);
+
+angular.module("template/tabs/tabs.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/tabs/tabs.html",
+ "\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "");
+}]);
+
+angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/tabs/tabset-titles.html",
+ "\n" +
+ "");
+}]);
+
+angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
+ $templateCache.put("template/tabs/tabset.html",
+ "\n" +
+ "\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "");
+}]);
diff --git a/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min.js b/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min.js
new file mode 100644
index 00000000..5b18245c
--- /dev/null
+++ b/js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min.js
@@ -0,0 +1,8 @@
+/*
+ * angular-ui-bootstrap
+ * http://angular-ui.github.io/bootstrap/
+
+ * Version: 0.10.0 - 2014-01-15
+ * License: MIT
+ */
+angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.modal","ui.bootstrap.tabs"]),angular.module("ui.bootstrap.tpls",["template/modal/backdrop.html","template/modal/window.html","template/tabs/tab.html","template/tabs/tabset.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0)}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g,0)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&e.$apply(function(){o.dismiss(b.key)}))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("#tasks_enhanced_wrapper").eq(0),h=g();h>=0&&!k&&(l=e.$new(!0),l.index=h,k=d("
")(l),f.append(k));var i=angular.element("
");i.attr("window-class",b.windowClass),i.attr("index",n.length()-1),i.attr("animate","animate"),i.html(b.content);var j=d(i)(b.scope);n.top().value.modalDomEl=j,f.append(j),f.addClass(m)},o.close=function(a,b){var c=n.get(a).value;c&&(c.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a).value;c&&(c.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(a){a.active=!1}),a.active=!0},b.addTab=function(a){c.push(a),(1===c.length||a.active)&&b.select(a)},b.removeTab=function(a){var d=c.indexOf(a);if(a.active&&c.length>1){var e=d==c.length-1?d-1:d+1;b.select(c[e])}c.splice(d,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1,a.type=angular.isDefined(c.type)?a.$parent.$eval(c.type):"tabs"}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){var g,h;e.active?(g=a(e.active),h=g.assign,b.$parent.$watch(g,function(a,c){a!==c&&(b.active=!!a)}),b.active=g(b.$parent)):h=g=angular.noop,b.$watch("active",function(a){h(b.$parent,a),a?(f.select(b),b.onSelect()):b.onDeselect()}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'
')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'')}]),angular.module("template/tabs/pane.html",[]).run(["$templateCache",function(a){a.put("template/tabs/pane.html",'
\n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'\n {{heading}} \n \n')}]),angular.module("template/tabs/tabs.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabs.html",'\n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset-titles.html","\n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'\n\n')}]);
\ No newline at end of file
diff --git a/l10n/de.php b/l10n/de.php
index 2280dd6e..87e789a5 100644
--- a/l10n/de.php
+++ b/l10n/de.php
@@ -1,6 +1,12 @@
"Ungültige Datums-/Zeitangabe",
"Search..." => "Suche...",
+"Settings" => "Einstellungen",
+"General" => "Allgemein",
+"Visible" => "Sichtbar",
+"Hidden" => "Versteckt",
+"Automatic" => "Automatisch",
+"Visibility of Smart Collections" => "Sichtbarkeit der Smart-Collections",
"Tasks" => "Aufgaben",
"Today" => "Heute",
"Important" => "Wichtig",
diff --git a/lib/controller/collectionscontroller.php b/lib/controller/collectionscontroller.php
new file mode 100644
index 00000000..43da2b82
--- /dev/null
+++ b/lib/controller/collectionscontroller.php
@@ -0,0 +1,93 @@
+.
+*
+*/
+
+namespace OCA\Tasks_enhanced\Controller;
+
+use OCA\Tasks_enhanced\Controller,
+ OCP\AppFramework\Http\JSONResponse;
+
+class CollectionsController extends Controller {
+
+ /**
+ * @NoAdminRequired
+ */
+ public function getCollections(){
+ $l = \OCP\Util::getL10N('tasks_enhanced');
+ $collections = array(
+ array(
+ 'id' => "starred",
+ 'displayname' => (string)$l->t('Important'),
+ 'show' => 2),
+ array(
+ 'id' => "today",
+ 'displayname' => (string)$l->t('Today'),
+ 'show' => 2),
+ array(
+ 'id' => "week",
+ 'displayname' => (string)$l->t('Week'),
+ 'show' => 2),
+ array(
+ 'id' => "all",
+ 'displayname' => (string)$l->t('All'),
+ 'show' => 2),
+ array(
+ 'id' => "current",
+ 'displayname' => (string)$l->t('Current'),
+ 'show' => 2),
+ array(
+ 'id' => "completed",
+ 'displayname' => (string)$l->t('Done'),
+ 'show' => 2)
+ );
+ foreach ($collections as $key => $collection){
+ try{
+ $tmp = (int)\OCP\Config::getUserValue($this->api->getUserId(), 'tasks_enhanced','show_'.$collection['id']);
+ if (!in_array($tmp, array(0,1,2))) {
+ $tmp = 2;
+ \OCP\Config::setUserValue($this->api->getUserId(), 'tasks_enhanced','show_'.$collection['id'],$tmp);
+ }
+ $collections[$key]['show'] = $tmp;
+ }catch(\Exception $e) {
+ \OCP\Util::writeLog('tasks_enhanced', $e->getMessage(), \OCP\Util::ERROR);
+ }
+ }
+ $result = array(
+ 'data' => array(
+ 'collections' => $collections
+ )
+ );
+ $response = new JSONResponse();
+ $response->setData($result);
+ return $response;
+ }
+
+ public function setVisibility(){
+ $collectionId = (string) $this->params('collectionID');
+ $vis = (int) $this->params('visibility');
+ if (in_array($vis, array(0,1,2))){
+ \OCP\Config::setUserValue($this->api->getUserId(), 'tasks_enhanced','show_'.$collectionId,$vis);
+ }
+ $response = new JSONResponse();
+ return $response;
+ }
+}
\ No newline at end of file
diff --git a/lib/controller/pagecontroller.php b/lib/controller/pagecontroller.php
index 06df01ff..294316cd 100644
--- a/lib/controller/pagecontroller.php
+++ b/lib/controller/pagecontroller.php
@@ -29,16 +29,19 @@ class PageController extends Controller {
\OCP\Util::addScript('tasks_enhanced', 'vendor/angularjs/angular-route');
\OCP\Util::addScript('tasks_enhanced', 'vendor/angularjs/angular-animate');
\OCP\Util::addScript('tasks_enhanced', 'vendor/momentjs/moment');
+ \OCP\Util::addScript('tasks_enhanced', 'vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0');
} else {
\OCP\Util::addScript('tasks_enhanced', 'vendor/angularjs/angular.min');
\OCP\Util::addScript('tasks_enhanced', 'vendor/angularjs/angular-route.min');
\OCP\Util::addScript('tasks_enhanced', 'vendor/angularjs/angular-animate.min');
\OCP\Util::addScript('tasks_enhanced', 'vendor/momentjs/moment.min');
+ \OCP\Util::addScript('tasks_enhanced', 'vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min');
}
\OCP\Util::addScript('tasks_enhanced', 'public/app');
\OCP\Util::addScript('tasks_enhanced', 'vendor/appframework/app');
\OCP\Util::addScript('tasks_enhanced', 'vendor/timepicker/jquery.ui.timepicker');
\OCP\Util::addStyle('tasks_enhanced', 'style');
+ \OCP\Util::addStyle('tasks_enhanced', 'vendor/bootstrap/bootstrap');
$date = new \DateTimeZone(\OC_Calendar_App::getTimezone());
$day = new \DateTime('today', $date);
diff --git a/lib/controller/settingscontroller.php b/lib/controller/settingscontroller.php
new file mode 100644
index 00000000..e440e279
--- /dev/null
+++ b/lib/controller/settingscontroller.php
@@ -0,0 +1,59 @@
+.
+*
+*/
+
+namespace OCA\Tasks_enhanced\Controller;
+
+use OCA\Tasks_enhanced\Controller,
+ OCP\AppFramework\Http\JSONResponse;
+
+class SettingsController extends Controller {
+
+ /**
+ * @NoAdminRequired
+ */
+ public function getSettings(){
+ $settings = array(
+ array(
+ 'id' => 'various',
+ 'showHidden' => (int)\OCP\Config::getUserValue($this->api->getUserId(), 'tasks_enhanced','various_showHidden'))
+ );
+ $result = array(
+ 'data' => array(
+ 'settings' => $settings
+ )
+ );
+ $response = new JSONResponse();
+ $response->setData($result);
+ return $response;
+ }
+
+ /**
+ * @NoAdminRequired
+ */
+ public function set(){
+ \OCP\Config::setUserValue($this->api->getUserId(), 'tasks_enhanced',$this->params('type').'_'.$this->params('setting'), $this->params('value'));
+ $response = new JSONResponse();
+ $response->setData();
+ return $response;
+ }
+}
\ No newline at end of file
diff --git a/lib/dispatcher.php b/lib/dispatcher.php
index 594edc5c..545cf865 100644
--- a/lib/dispatcher.php
+++ b/lib/dispatcher.php
@@ -13,8 +13,10 @@ namespace OCA\Tasks_enhanced;
use OCP\AppFramework\App as MainApp,
OCP\AppFramework\IAppContainer,
OCA\Tasks_enhanced\Controller\PageController,
+ OCA\Tasks_enhanced\Controller\CollectionsController,
OCA\Tasks_enhanced\Controller\ListsController,
- OCA\Tasks_enhanced\Controller\TasksController;
+ OCA\Tasks_enhanced\Controller\TasksController,
+ OCA\Tasks_enhanced\Controller\SettingsController;
/**
* This class manages our app actions
@@ -38,12 +40,18 @@ class Dispatcher extends MainApp {
$this->container->registerService('PageController', function(IAppContainer $container) {
return new PageController($container);
});
+ $this->container->registerService('CollectionsController', function(IAppContainer $container) {
+ return new CollectionsController($container);
+ });
$this->container->registerService('ListsController', function(IAppContainer $container) {
return new ListsController($container);
});
$this->container->registerService('TasksController', function(IAppContainer $container) {
return new TasksController($container);
});
+ $this->container->registerService('SettingsController', function(IAppContainer $container) {
+ return new SettingsController($container);
+ });
}
}
diff --git a/templates/main.php b/templates/main.php
index 3ba5be46..525976c9 100644
--- a/templates/main.php
+++ b/templates/main.php
@@ -1,4 +1,4 @@
-
+
-
+
inc('part.tasklist')); ?>
inc('part.collectionall')); ?>
inc('part.collectionweek')); ?>
-
+
\ No newline at end of file
diff --git a/templates/part.details.php b/templates/part.details.php
index ebe369ae..d01cb082 100644
--- a/templates/part.details.php
+++ b/templates/part.details.php
@@ -1,101 +1,101 @@
-
-
-
-
-
-
-
-
{{ task.name }}
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ task.start | startDetails }}
+
+
+
+
+
+
+
+
-
-
-
-
-
-
{{ task.start | startDetails }}
+
+
+
+
+ {{ task.due | dateDetails }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ task.reminder | reminderDetails:this }}
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- {{ task.due | dateDetails }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ task.reminder | reminderDetails:this }}
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/templates/part.settings.php b/templates/part.settings.php
new file mode 100644
index 00000000..cf0dd348
--- /dev/null
+++ b/templates/part.settings.php
@@ -0,0 +1,29 @@
+
+
+
+
+
+ t('General')); ?>
+ Allgemeine Einstellungen
+
+
+ t('Smart Collections')); ?>
+ t('Visibility of Smart Collections')); ?>
+
+
+
+ {{ collection.displayname }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file