Add settings dialog
This commit is contained in:
parent
62472e1662
commit
62b8b9ca03
31 changed files with 2145 additions and 187 deletions
|
@ -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');
|
||||
}
|
||||
);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
173
css/vendor/bootstrap/bootstrap.css
vendored
Normal file
173
css/vendor/bootstrap/bootstrap.css
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
BIN
img/bgSettingsActive.png
Normal file
BIN
img/bgSettingsActive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
|
@ -697,22 +697,22 @@
|
|||
<g>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_99_" x="80" y="19" width="20" height="20"/>
|
||||
<rect id="SVGID_99_" x="80" y="20" width="20" height="20"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_100_">
|
||||
<use xlink:href="#SVGID_99_" overflow="visible"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#SVGID_100_)">
|
||||
<defs>
|
||||
<rect id="SVGID_101_" x="80" y="19" width="20" height="20"/>
|
||||
<rect id="SVGID_101_" x="80" y="20" width="20" height="20"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_102_">
|
||||
<use xlink:href="#SVGID_101_" overflow="visible"/>
|
||||
</clipPath>
|
||||
|
||||
<circle clip-path="url(#SVGID_102_)" fill="none" stroke="#8F9090" stroke-width="2" stroke-miterlimit="10" cx="87.724" cy="26.724" r="3.898"/>
|
||||
<circle clip-path="url(#SVGID_102_)" fill="none" stroke="#8F9090" stroke-width="2" stroke-miterlimit="10" cx="87.724" cy="27.724" r="3.898"/>
|
||||
|
||||
<line clip-path="url(#SVGID_102_)" fill="none" stroke="#8F9090" stroke-width="2" stroke-miterlimit="10" x1="90.481" y1="29.481" x2="96.956" y2="35.956"/>
|
||||
<line clip-path="url(#SVGID_102_)" fill="none" stroke="#8F9090" stroke-width="2" stroke-miterlimit="10" x1="90.481" y1="30.481" x2="96.956" y2="36.956"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
@ -1554,4 +1554,34 @@
|
|||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_215_" x="200" y="40" width="20" height="20"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_216_">
|
||||
<use xlink:href="#SVGID_215_" overflow="visible"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#SVGID_216_)">
|
||||
<defs>
|
||||
<rect id="SVGID_217_" x="200" y="40" width="20" height="20"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_218_">
|
||||
<use xlink:href="#SVGID_217_" overflow="visible"/>
|
||||
</clipPath>
|
||||
<path clip-path="url(#SVGID_218_)" fill="#FFFFFF" d="M217.171,50.996c0-0.538-0.071-1.06-0.194-1.562l1.754-1.401l-1.685-2.794
|
||||
l-2.146,0.755c-0.795-0.715-1.756-1.26-2.827-1.57l-0.388-2.147h-3.371l-0.388,2.147c-1.093,0.316-2.071,0.876-2.876,1.612
|
||||
l-2.095-0.738l-1.685,2.794l1.74,1.39c-0.115,0.488-0.181,0.994-0.181,1.514c0,0.555,0.076,1.092,0.207,1.611l-1.767,1.409
|
||||
l1.685,2.797l2.192-0.773c0.783,0.691,1.723,1.221,2.769,1.524l0.399,2.21h3.371l0.398-2.21c1.045-0.303,1.982-0.832,2.766-1.523
|
||||
l2.194,0.772l1.685-2.794l-1.767-1.41C217.096,52.091,217.171,51.552,217.171,50.996 M210,54.256c-1.88,0-3.404-1.459-3.404-3.26
|
||||
c0-1.801,1.524-3.261,3.404-3.261c1.882,0,3.406,1.46,3.406,3.261C213.406,52.797,211.882,54.256,210,54.256"/>
|
||||
<path clip-path="url(#SVGID_218_)" fill="#8F9090" d="M217.171,49.971c0-0.538-0.071-1.06-0.194-1.562l1.754-1.401l-1.685-2.794
|
||||
l-2.146,0.755c-0.795-0.715-1.756-1.26-2.827-1.57l-0.388-2.147h-3.371l-0.388,2.147c-1.093,0.316-2.071,0.875-2.876,1.611
|
||||
l-2.095-0.737l-1.685,2.794l1.74,1.39c-0.115,0.488-0.181,0.993-0.181,1.514c0,0.555,0.076,1.092,0.207,1.61l-1.767,1.41
|
||||
l1.685,2.797l2.192-0.773c0.783,0.691,1.723,1.22,2.769,1.524l0.399,2.21h3.371l0.398-2.21c1.045-0.304,1.982-0.832,2.766-1.523
|
||||
l2.194,0.772l1.685-2.795l-1.767-1.409C217.096,51.064,217.171,50.526,217.171,49.971 M210,53.23c-1.88,0-3.404-1.459-3.404-3.26
|
||||
c0-1.802,1.524-3.261,3.404-3.261c1.882,0,3.406,1.459,3.406,3.261C213.406,51.771,211.882,53.23,210,53.23"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 79 KiB |
|
@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public
|
|||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
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
|
||||
|
|
|
@ -23,14 +23,15 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
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)
|
||||
|
||||
]
|
|
@ -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()
|
||||
|
||||
|
|
60
js/app/controllers/settingscontroller.coffee
Normal file
60
js/app/controllers/settingscontroller.coffee
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
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)
|
||||
]
|
|
@ -22,14 +22,16 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
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)
|
||||
]
|
34
js/app/directives/pane.coffee
Normal file
34
js/app/directives/pane.coffee
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
|
||||
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: '<div class="tab-pane" ng-class="{active: selected}"'+
|
||||
'ng-transclude>[[ ]]</div>'
|
36
js/app/directives/tabs.coffee
Normal file
36
js/app/directives/tabs.coffee
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
|
||||
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)
|
47
js/app/services/businesslayer/settingsbusinesslayer.coffee
Normal file
47
js/app/services/businesslayer/settingsbusinesslayer.coffee
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
|
||||
|
||||
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)
|
||||
|
||||
]
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -21,41 +21,13 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
###
|
||||
|
||||
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)
|
||||
]
|
42
js/app/services/models/settingsmodel.coffee
Normal file
42
js/app/services/models/settingsmodel.coffee
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
###
|
||||
|
||||
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()
|
||||
]
|
|
@ -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)
|
||||
|
||||
]
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ angular.module('Tasks').factory 'Status',
|
|||
|
||||
constructor: () ->
|
||||
@_$status = {
|
||||
showhidden: true
|
||||
searchActive: false
|
||||
addingList: false
|
||||
focusTaskInput: false
|
||||
|
|
355
js/public/app.js
355
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: '<div class="tab-pane" ng-class="{active: selected}"' + 'ng-transclude>[[ ]]</div>'
|
||||
};
|
||||
});
|
||||
|
||||
}).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
|
||||
|
|
817
js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.js
vendored
Normal file
817
js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.js
vendored
Normal file
|
@ -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('<div modal-backdrop></div>')(backdropScope);
|
||||
body.append(backdropDomEl);
|
||||
}
|
||||
|
||||
var angularDomEl = angular.element('<div modal-window></div>');
|
||||
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
|
||||
<example module="ui.bootstrap">
|
||||
<file name="index.html">
|
||||
<tabset>
|
||||
<tab heading="Tab 1"><b>First</b> Content!</tab>
|
||||
<tab heading="Tab 2"><i>Second</i> Content!</tab>
|
||||
</tabset>
|
||||
<hr />
|
||||
<tabset vertical="true">
|
||||
<tab heading="Vertical Tab 1"><b>First</b> Vertical Content!</tab>
|
||||
<tab heading="Vertical Tab 2"><i>Second</i> Vertical Content!</tab>
|
||||
</tabset>
|
||||
<tabset justified="true">
|
||||
<tab heading="Justified Tab 1"><b>First</b> Justified Content!</tab>
|
||||
<tab heading="Justified Tab 2"><i>Second</i> Justified Content!</tab>
|
||||
</tabset>
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
.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
|
||||
<example module="ui.bootstrap">
|
||||
<file name="index.html">
|
||||
<div ng-controller="TabsDemoCtrl">
|
||||
<button class="btn btn-small" ng-click="items[0].active = true">
|
||||
Select item 1, using active binding
|
||||
</button>
|
||||
<button class="btn btn-small" ng-click="items[1].disabled = !items[1].disabled">
|
||||
Enable/disable item 2, using disabled binding
|
||||
</button>
|
||||
<br />
|
||||
<tabset>
|
||||
<tab heading="Tab 1">First Tab</tab>
|
||||
<tab select="alertMe()">
|
||||
<tab-heading><i class="icon-bell"></i> Alert me!</tab-heading>
|
||||
Second Tab, with alert callback and html heading!
|
||||
</tab>
|
||||
<tab ng-repeat="item in items"
|
||||
heading="{{item.title}}"
|
||||
disabled="item.disabled"
|
||||
active="item.active">
|
||||
{{item.content}}
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
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!");
|
||||
});
|
||||
};
|
||||
};
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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
|
||||
<example module="ui.bootstrap">
|
||||
<file name="index.html">
|
||||
<tabset>
|
||||
<tab>
|
||||
<tab-heading><b>HTML</b> in my titles?!</tab-heading>
|
||||
And some content, too!
|
||||
</tab>
|
||||
<tab>
|
||||
<tab-heading><i class="icon-heart"></i> Icon heading?!?</tab-heading>
|
||||
That's right.
|
||||
</tab>
|
||||
</tabset>
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
.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",
|
||||
"<div class=\"modal-backdrop fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1040 + index*10}\"></div>");
|
||||
}]);
|
||||
|
||||
angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/modal/window.html",
|
||||
"<div tabindex=\"-1\" class=\"modal fade {{ windowClass }}\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
|
||||
" <div class=\"modal-dialog\"><div class=\"modal-content\" ng-transclude></div></div>\n" +
|
||||
"</div>");
|
||||
}]);
|
||||
|
||||
angular.module("template/tabs/pane.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/tabs/pane.html",
|
||||
"<div class=\"tab-pane\" ng-class=\"{active: selected}\" ng-show=\"selected\" ng-transclude></div>\n" +
|
||||
"");
|
||||
}]);
|
||||
|
||||
angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/tabs/tab.html",
|
||||
"<li ng-class=\"{active: active, disabled: disabled}\">\n" +
|
||||
" <a ng-click=\"select()\" tab-heading-transclude>{{heading}}</a>\n" +
|
||||
"</li>\n" +
|
||||
"");
|
||||
}]);
|
||||
|
||||
angular.module("template/tabs/tabs.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/tabs/tabs.html",
|
||||
"<div class=\"tabbable\">\n" +
|
||||
" <ul class=\"nav nav-tabs\">\n" +
|
||||
" <li ng-repeat=\"pane in panes\" ng-class=\"{active:pane.selected}\">\n" +
|
||||
" <a ng-click=\"select(pane)\">{{pane.heading}}</a>\n" +
|
||||
" </li>\n" +
|
||||
" </ul>\n" +
|
||||
" <div class=\"tab-content\" ng-transclude></div>\n" +
|
||||
"</div>\n" +
|
||||
"");
|
||||
}]);
|
||||
|
||||
angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/tabs/tabset-titles.html",
|
||||
"<ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical}\">\n" +
|
||||
"</ul>\n" +
|
||||
"");
|
||||
}]);
|
||||
|
||||
angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/tabs/tabset.html",
|
||||
"\n" +
|
||||
"<div class=\"tabbable\">\n" +
|
||||
" <ul class=\"nav {{type && 'nav-' + type}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
|
||||
" <div class=\"tab-content\">\n" +
|
||||
" <div class=\"tab-pane\" \n" +
|
||||
" ng-repeat=\"tab in tabs\" \n" +
|
||||
" ng-class=\"{active: tab.active}\"\n" +
|
||||
" tab-content-transclude=\"tab\">\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>\n" +
|
||||
"");
|
||||
}]);
|
8
js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min.js
vendored
Normal file
8
js/vendor/bootstrap/ui-bootstrap-custom-tpls-0.10.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,12 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Invalid date/time" => "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",
|
||||
|
|
93
lib/controller/collectionscontroller.php
Normal file
93
lib/controller/collectionscontroller.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud - Tasks
|
||||
*
|
||||
* @author Raimund Schlüßler
|
||||
* @copyright 2014 Raimund Schlüßler raimund.schluessler@googlemail.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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
59
lib/controller/settingscontroller.php
Normal file
59
lib/controller/settingscontroller.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud - Tasks
|
||||
*
|
||||
* @author Raimund Schlüßler
|
||||
* @copyright 2014 Raimund Schlüßler raimund.schluessler@googlemail.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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div ng-app="Tasks" ng-cloak ng-controller="AppController" ng-click="closeAll()">
|
||||
<div ng-app="Tasks" ng-cloak ng-controller="AppController" ng-click="closeAll()" id="tasks_enhanced_wrapper">
|
||||
<div id="task-lists" ng-controller="ListController">
|
||||
<div id="task_lists_header" class="header" ng-class="{'search': status.searchActive}" ng-controller="SearchController">
|
||||
<div id="main-toolbar">
|
||||
|
@ -20,7 +20,7 @@
|
|||
<div id="task_lists_scroll" class="scroll">
|
||||
<ul id="collection_filters">
|
||||
<li ng-repeat="collection in collections" id="collection_{{ collection.id }}" rel="{{ collection.id }}"
|
||||
ng-class="{'animate-up': getCollectionCount(collection.id)<1, active: collection.id==route.listID}" oc-drop-task>
|
||||
ng-class="{'animate-up': hideCollection(collection.id), active: collection.id==route.listID}" oc-drop-task>
|
||||
<a href="#/lists/{{ collection.id }}">
|
||||
<span class="icon collection-{{ collection.id }}"><text ng-show="collection.id=='today'"><?php p($_['DOM']); ?></text></span>
|
||||
<span class="count">{{ getCollectionString(collection.id) }}</span>
|
||||
|
@ -50,6 +50,9 @@
|
|||
<a class="delete" ng-click="deleteList(route.listID)" ng-show="showDelete(route.listID)">
|
||||
<span class="icon detail-trash"></span>
|
||||
</a>
|
||||
<a class="settings" ng-click="showSettings()" stop-event="click">
|
||||
<span class="icon detail-settings"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -66,12 +69,14 @@
|
|||
ng-keydown="checkTaskInput($event)"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="task-list" ng-class="{'completed-hidden':!status.showhidden}" ng-switch="route.listID">
|
||||
<div class="task-list" ng-class="{'completed-hidden':!settingsmodel.getById('various').showHidden}" ng-switch="route.listID">
|
||||
<?php print_unescaped($this->inc('part.tasklist')); ?>
|
||||
<?php print_unescaped($this->inc('part.collectionall')); ?>
|
||||
<?php print_unescaped($this->inc('part.collectionweek')); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="task-details" ng-include="'templates/part.details.php'" ng-class="{'details-visible':route.taskID}"></div>
|
||||
<script type="text/ng-template" id="part.settings.html">
|
||||
<?php print_unescaped($this->inc('part.settings')); ?>
|
||||
</script>
|
||||
</div>
|
|
@ -1,101 +1,101 @@
|
|||
<div ng-controller="DetailsController" ng-click="endEdit()" stop-event="click">
|
||||
<a class="detail-checkbox" ng-click="toggleCompleted(task.id)">
|
||||
<span class="icon detail-checkbox" ng-class="{'detail-checked':task.completed}"></span>
|
||||
</a>
|
||||
<a class="detail-star" ng-click="toggleStarred(task.id)">
|
||||
<span class="icon detail-star" ng-class="{'detail-starred':task.starred}"></span>
|
||||
</a>
|
||||
<div class="title">
|
||||
<span class="title-text" ng-class="{'strike-through':task.completed}" ng-click="editName()" stop-event="click"
|
||||
ng-hide="route.parameter=='name'" oc-click-focus="{selector: '#editName', timeout: 0}">{{ task.name }}</span>
|
||||
<div class="expandable-container" ng-show="route.parameter=='name'" stop-event="click">
|
||||
<div class="expandingArea active">
|
||||
<pre><span>{{ task.name }}</span><br /></pre>
|
||||
<textarea id="editName" maxlength="200" ng-model="task.name" ng-keydown="endName($event)"></textarea>
|
||||
</div>
|
||||
<a class="detail-checkbox" ng-click="toggleCompleted(task.id)">
|
||||
<span class="icon detail-checkbox" ng-class="{'detail-checked':task.completed}"></span>
|
||||
</a>
|
||||
<a class="detail-star" ng-click="toggleStarred(task.id)">
|
||||
<span class="icon detail-star" ng-class="{'detail-starred':task.starred}"></span>
|
||||
</a>
|
||||
<div class="title">
|
||||
<span class="title-text" ng-class="{'strike-through':task.completed}" ng-click="editName()" stop-event="click"
|
||||
ng-hide="route.parameter=='name'" oc-click-focus="{selector: '#editName', timeout: 0}">{{ task.name }}</span>
|
||||
<div class="expandable-container" ng-show="route.parameter=='name'" stop-event="click">
|
||||
<div class="expandingArea active">
|
||||
<pre><span>{{ task.name }}</span><br /></pre>
|
||||
<textarea id="editName" maxlength="200" ng-model="task.name" ng-keydown="endName($event)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body" watch-top ng-style="{top:divTop}">
|
||||
<div class="section detail-start" ng-class="{'date':isDue(task.start), 'editing':route.parameter=='startdate'}" ng-click="editStart()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-start input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-start" ng-class="{'overdue':isOverDue(task.start)}"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.start)}" ng-hide="route.parameter=='startdate'">
|
||||
<text>{{ task.start | startDetails }}</text>
|
||||
</div>
|
||||
<a class="detail-delete" ng-click="deleteStartDate()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='startdate'">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.start | dateTaskList }}" datepicker="start">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.start | timeTaskList }}" timepicker="start" stop-event="click">
|
||||
</div>
|
||||
</div>
|
||||
<div class="body" watch-top ng-style="{top:divTop}">
|
||||
<div class="section detail-start" ng-class="{'date':isDue(task.start), 'editing':route.parameter=='startdate'}" ng-click="editStart()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-start input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-start" ng-class="{'overdue':isOverDue(task.start)}"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.start)}" ng-hide="route.parameter=='startdate'">
|
||||
<text>{{ task.start | startDetails }}</text>
|
||||
<div class="section detail-date" ng-class="{'date':isDue(task.due), 'editing':route.parameter=='duedate'}" ng-click="editDueDate()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-date input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-date" ng-class="{'overdue':isOverDue(task.due)}"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.due)}" ng-hide="route.parameter=='duedate'">
|
||||
<text>{{ task.due | dateDetails }}</text>
|
||||
</div>
|
||||
<a class="detail-delete" ng-click="deleteDueDate()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='duedate'">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.due | dateTaskList }}" datepicker="due">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.due | timeTaskList }}" timepicker="due" stop-event="click">
|
||||
</div>
|
||||
</div>
|
||||
<div class="section detail-reminder" ng-class="{'date':isDue(task.reminder.date), 'editing':route.parameter=='reminder'}" ng-click="editReminder()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-reminder input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-reminder" ng-class="{'overdue':isOverDue(task.reminder.date)}"></span>
|
||||
<span class="icon detail-remindertype" ng-click="changeReminderType(task)" ng-show="task.due || task.start"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.reminder.date)}" ng-hide="route.parameter=='reminder'">
|
||||
<text rel="">{{ task.reminder | reminderDetails:this }}</text>
|
||||
</div>
|
||||
<!-- <div class="section-description" ng-hide="route.parameter=='reminder'">{{ task.reminder.date | dateDetailsShort }}</div> -->
|
||||
<a class="detail-delete" ng-click="deleteReminder()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='reminder'" ng-switch='reminderType(task)'>
|
||||
<div ng-switch-when="DATE-TIME">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.reminder.date | dateTaskList }}" datepicker="reminder">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.reminder.date | timeTaskList }}" timepicker="reminder" stop-event="click">
|
||||
</div>
|
||||
<a class="detail-delete" ng-click="deleteStartDate()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
<div ng-switch-when="DURATION">
|
||||
<input ng-change="setReminderDuration(task.id)" class="duration-input medium focus" type="number" key-value="" placeholder="" ng-model="task.reminder.duration[task.reminder.duration.token]">
|
||||
<select ng-model="task.reminder.duration.token" ng-options="duration.id as duration.names for duration in durations"></select>
|
||||
<select ng-change="setReminderDuration(task.id)" ng-model="task.reminder.duration.params" ng-options="param as param.name for param in params(task) track by param.id"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <ul class="subtasks buffer"></ul> -->
|
||||
<div class="note">
|
||||
<div class="note-body selectable" ng-click="editNote()" stop-event="click" oc-click-focus="{selector: '.expandingArea textarea', timeout: 0}">
|
||||
<!--
|
||||
<a class="open-fullscreen-note">
|
||||
<span class="icon note-fullscreen"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='startdate'">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.start | dateTaskList }}" datepicker="start">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.start | timeTaskList }}" timepicker="start" stop-event="click">
|
||||
</div>
|
||||
</div>
|
||||
<div class="section detail-date" ng-class="{'date':isDue(task.due), 'editing':route.parameter=='duedate'}" ng-click="editDueDate()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-date input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-date" ng-class="{'overdue':isOverDue(task.due)}"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.due)}" ng-hide="route.parameter=='duedate'">
|
||||
<text>{{ task.due | dateDetails }}</text>
|
||||
</div>
|
||||
<a class="detail-delete" ng-click="deleteDueDate()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='duedate'">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.due | dateTaskList }}" datepicker="due">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.due | timeTaskList }}" timepicker="due" stop-event="click">
|
||||
</div>
|
||||
</div>
|
||||
<div class="section detail-reminder" ng-class="{'date':isDue(task.reminder.date), 'editing':route.parameter=='reminder'}" ng-click="editReminder()" stop-event="click">
|
||||
<!-- oc-click-focus="{selector: 'div.detail-reminder input.datepicker-input', timeout: 0}" -->
|
||||
<span class="icon detail-reminder" ng-class="{'overdue':isOverDue(task.reminder.date)}"></span>
|
||||
<span class="icon detail-remindertype" ng-click="changeReminderType(task)" ng-show="task.due || task.start"></span>
|
||||
<div class="section-title" ng-class="{'overdue':isOverDue(task.reminder.date)}" ng-hide="route.parameter=='reminder'">
|
||||
<text rel="">{{ task.reminder | reminderDetails:this }}</text>
|
||||
</div>
|
||||
<!-- <div class="section-description" ng-hide="route.parameter=='reminder'">{{ task.reminder.date | dateDetailsShort }}</div> -->
|
||||
<a class="detail-delete" ng-click="deleteReminder()" stop-event="click">
|
||||
<span class="icon detail-delete"></span>
|
||||
</a>
|
||||
<span class="icon detail-save" ng-click="endEdit()" stop-event="click"></span>
|
||||
<div class="section-edit" ng-show="route.parameter=='reminder'" ng-switch='reminderType(task)'>
|
||||
<div ng-switch-when="DATE-TIME">
|
||||
<input class="datepicker-input medium focus" type="text" key-value="" placeholder="dd.mm.yyyy" value="{{ task.reminder.date | dateTaskList }}" datepicker="reminder">
|
||||
<input class="timepicker-input medium focus" type="text" key-value="" placeholder="hh:mm" value="{{ task.reminder.date | timeTaskList }}" timepicker="reminder" stop-event="click">
|
||||
</div>
|
||||
<div ng-switch-when="DURATION">
|
||||
<input ng-change="setReminderDuration(task.id)" class="duration-input medium focus" type="number" key-value="" placeholder="" ng-model="task.reminder.duration[task.reminder.duration.token]">
|
||||
<select ng-model="task.reminder.duration.token" ng-options="duration.id as duration.names for duration in durations"></select>
|
||||
<select ng-change="setReminderDuration(task.id)" ng-model="task.reminder.duration.params" ng-options="param as param.name for param in params(task) track by param.id"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <ul class="subtasks buffer"></ul> -->
|
||||
<div class="note">
|
||||
<div class="note-body selectable" ng-click="editNote()" stop-event="click" oc-click-focus="{selector: '.expandingArea textarea', timeout: 0}">
|
||||
<!--
|
||||
<a class="open-fullscreen-note">
|
||||
<span class="icon note-fullscreen"></span>
|
||||
</a>
|
||||
-->
|
||||
<div class="content-fakeable">
|
||||
<div class="display-view" ng-hide="route.parameter=='note'">{{ task.note }}</div>
|
||||
<div class="edit-view" ng-show="route.parameter=='note'">
|
||||
<div class="expandingArea active">
|
||||
<pre><span>{{ task.note }}</span><br /><br /></pre>
|
||||
<textarea ng-model="task.note"></textarea>
|
||||
</div>
|
||||
-->
|
||||
<div class="content-fakeable">
|
||||
<div class="display-view" ng-hide="route.parameter=='note'">{{ task.note }}</div>
|
||||
<div class="edit-view" ng-show="route.parameter=='note'">
|
||||
<div class="expandingArea active">
|
||||
<pre><span>{{ task.note }}</span><br /><br /></pre>
|
||||
<textarea ng-model="task.note"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a class="detail-trash" ng-click="deleteTask(task.id)" stop-event="click">
|
||||
<span class="icon detail-trash"></span>
|
||||
</a>
|
||||
<a class="detail-close" ng-click="closeDetails()" stop-event="click">
|
||||
<span class="icon detail-close"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a class="detail-trash" ng-click="deleteTask(task.id)" stop-event="click">
|
||||
<span class="icon detail-trash"></span>
|
||||
</a>
|
||||
<a class="detail-close" ng-click="closeDetails()" stop-event="click">
|
||||
<span class="icon detail-close"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
29
templates/part.settings.php
Normal file
29
templates/part.settings.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<div id="settings_modal">
|
||||
<div class="header">
|
||||
<h2><?php p($l->t('Settings')); ?></h2>
|
||||
<div class="button" ng-click="ok()">
|
||||
<text><?php p($l->t('Done')); ?></text>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<tabset justified="true">
|
||||
<tab>
|
||||
<tab-heading><?php p($l->t('General')); ?></tab-heading>
|
||||
Allgemeine Einstellungen
|
||||
</tab>
|
||||
<tab>
|
||||
<tab-heading><?php p($l->t('Smart Collections')); ?></tab-heading>
|
||||
<text><?php p($l->t('Visibility of Smart Collections')); ?></text>
|
||||
<ul>
|
||||
<li ng-repeat="collection in collections">
|
||||
<span class="icon collection-{{ collection.id }}"><text ng-show="collection.id=='today'"><?php p($_['DOM']); ?></text></span>
|
||||
<span class="title"><text>{{ collection.displayname }}</text></span>
|
||||
<span>
|
||||
<select ng-change="setVisibility(collection.id)" ng-model="collection.show" ng-options="collectionOption.id as collectionOption.name for collectionOption in collectionOptions"></select>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue