зеркало из https://github.com/nextcloud/deck.git
refactoring and stack undo delete early wip
Signed-off-by: Manuel Arno Korfmann <manu@korfmann.info> stack soft delete done Signed-off-by: Manuel Arno Korfmann <manu@korfmann.info> stack undo delete done Signed-off-by: Manuel Arno Korfmann <manu@korfmann.info> stack undo: code review remarks and fixes Signed-off-by: Manuel Arno Korfmann <manu@korfmann.info>
This commit is contained in:
Родитель
f2795f120b
Коммит
ef4ce31c47
|
@ -77,6 +77,14 @@
|
|||
<length>8</length>
|
||||
<notnull>false</notnull>
|
||||
</field>
|
||||
<field>
|
||||
<name>deleted_at</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<length>8</length>
|
||||
<notnull>false</notnull>
|
||||
<unsigned>true</unsigned>
|
||||
</field>
|
||||
<index>
|
||||
<name>deck_stacks_board_id_index</name>
|
||||
<field>
|
||||
|
|
|
@ -43,6 +43,7 @@ return [
|
|||
['name' => 'stack#update', 'url' => '/stacks/{stackId}', 'verb' => 'PUT'],
|
||||
['name' => 'stack#reorder', 'url' => '/stacks/{stackId}/reorder', 'verb' => 'PUT'],
|
||||
['name' => 'stack#delete', 'url' => '/stacks/{stackId}', 'verb' => 'DELETE'],
|
||||
['name' => 'stack#deleted', 'url' => '/stacks/deleted/{boardId}', 'verb' => 'GET'],
|
||||
['name' => 'stack#archived', 'url' => '/stacks/{boardId}/archived', 'verb' => 'GET'],
|
||||
|
||||
// cards
|
||||
|
|
|
@ -1215,12 +1215,18 @@ input.input-inline {
|
|||
|
||||
.tabHeaders {
|
||||
clear: both;
|
||||
overflow: hidden;
|
||||
overflow: initial;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.tabsContainer {
|
||||
margin-top: 15px;
|
||||
height: 100%;
|
||||
|
||||
.tab {
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-select-offscreen {
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
import app from '../app/App.js';
|
||||
|
@ -42,7 +42,17 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
|||
$scope.board = BoardService.getCurrent();
|
||||
$scope.uploader = FileService.uploader;
|
||||
|
||||
$scope.deletedCards = [];
|
||||
$scope.deletedCards = {};
|
||||
$scope.deletedStacks = {};
|
||||
|
||||
$scope.$watch(function() {
|
||||
return $state.current;
|
||||
}, function(currentState) {
|
||||
if(currentState.name === 'board.detail') {
|
||||
$scope.loadDeletedEntity(CardService, 'deletedCards');
|
||||
$scope.loadDeletedEntity(StackService, 'deletedStacks');
|
||||
}
|
||||
});
|
||||
|
||||
// workaround for $stateParams changes not being propagated
|
||||
$scope.$watch(function() {
|
||||
|
@ -138,9 +148,11 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
|||
});
|
||||
};
|
||||
|
||||
$scope.loadDeletedCards = function() {
|
||||
CardService.fetchDeleted($scope.id).then(function (data) {
|
||||
$scope.deletedCards = data;
|
||||
$scope.loadDeletedEntity = function(service, scopeKey) {
|
||||
service.fetchDeleted($scope.id).then(function (data) {
|
||||
for(i=0;i<data.length;i++) {
|
||||
$scope[scopeKey][data[i].id] = data[i];
|
||||
}
|
||||
}, function (error) {
|
||||
$scope.statusservice.setError('Error occured', error);
|
||||
});
|
||||
|
@ -196,30 +208,30 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
|||
});
|
||||
};
|
||||
|
||||
$scope.stackDelete = function (stack) {
|
||||
$scope.stackservice.delete(stack.id).then(function() {
|
||||
$scope.deletedStacks[stack.id] = stack;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.stackUndoDelete = function (deletedStack) {
|
||||
StackService.undoDelete(deletedStack).then(function() {
|
||||
delete $scope.deletedStacks[deletedStack.id];
|
||||
});
|
||||
}
|
||||
|
||||
$scope.cardDelete = function (card) {
|
||||
OC.dialogs.confirm(t('deck', 'Are you sure you want to delete this card with all of its data?'), t('deck', 'Delete'), function(state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
CardService.delete(card.id).then(function () {
|
||||
StackService.removeCard(card);
|
||||
$scope.deletedCards.push(card);
|
||||
});
|
||||
CardService.delete(card.id).then(function () {
|
||||
StackService.removeCard(card);
|
||||
$scope.deletedCards[card.id] = card;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cardUndoDelete = function (deletedCard) {
|
||||
CardService.undoDelete(deletedCard);
|
||||
StackService.addCard(deletedCard);
|
||||
$scope.removeFromDeletedCards(deletedCard);
|
||||
};
|
||||
|
||||
$scope.removeFromDeletedCards = function(deletedCard) {
|
||||
for(var i=0;i<$scope.deletedCards.length;i++) {
|
||||
if($scope.deletedCards[i].id === deletedCard.id) {
|
||||
$scope.deletedCards.splice(i, 1);
|
||||
}
|
||||
}
|
||||
CardService.undoDelete(deletedCard).then(function() {
|
||||
StackService.addCard(deletedCard);
|
||||
delete $scope.deletedCards[deletedCard.id];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cardArchive = function (card) {
|
||||
|
@ -262,7 +274,6 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
|||
// TODO: remove from cards
|
||||
};
|
||||
$scope.labelCreate = function (label) {
|
||||
alert(label);
|
||||
label.boardId = $scope.id;
|
||||
LabelService.create(label).then(function (data) {
|
||||
$scope.newStack.title = '';
|
||||
|
@ -410,6 +421,4 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
|
|||
}
|
||||
return card.attachmentCount;
|
||||
};
|
||||
|
||||
$scope.loadDeletedCards();
|
||||
});
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
import app from '../app/App.js';
|
||||
|
||||
|
@ -48,6 +48,19 @@ app.factory('ApiService', function ($http, $q) {
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
ApiService.prototype.fetchDeleted = function (scopeId) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
$http.get(this.baseUrl + '/deleted/' + scopeId).then(function (response) {
|
||||
var objects = response.data;
|
||||
deferred.resolve(objects);
|
||||
}, function (error) {
|
||||
deferred.reject('Fetching ' + self.endpoint + ' failed');
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
|
||||
ApiService.prototype.fetchOne = function (id) {
|
||||
|
||||
this.id = id;
|
||||
|
@ -111,20 +124,19 @@ app.factory('ApiService', function ($http, $q) {
|
|||
deferred.reject('Deleting ' + self.endpoint + ' failed');
|
||||
});
|
||||
return deferred.promise;
|
||||
|
||||
};
|
||||
|
||||
ApiService.prototype.softDelete = function (id) {
|
||||
var deferred = $q.defer();
|
||||
ApiService.prototype.undoDelete = function(entity) {
|
||||
var self = this;
|
||||
|
||||
$http.delete(this.baseUrl + '/' + id).then(function (response) {
|
||||
self.data[id].deletedAt = response.data.deletedAt;
|
||||
deferred.resolve(response.data);
|
||||
}, function (error) {
|
||||
deferred.reject('Deleting ' + self.endpoint + ' failed');
|
||||
entity.deletedAt = 0;
|
||||
|
||||
var promise = this.update(entity);
|
||||
|
||||
promise.then(function() {
|
||||
self.data[entity.id] = entity;
|
||||
});
|
||||
return deferred.promise;
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
// methods for managing data
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
import app from '../app/App.js';
|
||||
|
||||
|
@ -27,13 +27,6 @@ app.factory('CardService', function (ApiService, $http, $q) {
|
|||
};
|
||||
CardService.prototype = angular.copy(ApiService.prototype);
|
||||
|
||||
CardService.prototype.delete = CardService.prototype.softDelete;
|
||||
|
||||
CardService.prototype.undoDelete = function(card) {
|
||||
card.deletedAt = 0;
|
||||
this.update(card);
|
||||
};
|
||||
|
||||
CardService.prototype.reorder = function (card, order) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
|
@ -179,19 +172,6 @@ app.factory('CardService', function (ApiService, $http, $q) {
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
CardService.prototype.fetchDeleted = function (boardId) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
$http.get(this.baseUrl + '/deleted/' + boardId).then(function (response) {
|
||||
var objects = response.data;
|
||||
deferred.resolve(objects);
|
||||
}, function (error) {
|
||||
deferred.reject('Fetching ' + self.endpoint + ' failed');
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
|
||||
var service = new CardService($http, 'cards', $q);
|
||||
return service;
|
||||
});
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
import app from '../app/App.js';
|
||||
|
||||
|
@ -27,6 +27,7 @@ app.factory('StackService', function (ApiService, CardService, $http, $q) {
|
|||
ApiService.call(this, $http, ep, $q);
|
||||
};
|
||||
StackService.prototype = angular.copy(ApiService.prototype);
|
||||
|
||||
StackService.prototype.fetchAll = function (boardId) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
|
@ -129,27 +130,6 @@ app.factory('StackService', function (ApiService, CardService, $http, $q) {
|
|||
}
|
||||
};
|
||||
|
||||
// FIXME: Should not show popup but proper undo mechanism
|
||||
StackService.prototype.delete = function (id) {
|
||||
var deferred = $q.defer();
|
||||
var self = this;
|
||||
|
||||
OC.dialogs.confirm(t('deck', 'Are you sure you want to delete the stack with all of its data?'), t('deck', 'Delete'), function(state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
$http.delete(self.baseUrl + '/' + id).then(function (response) {
|
||||
self.remove(id);
|
||||
deferred.resolve(response.data);
|
||||
|
||||
}, function (error) {
|
||||
deferred.reject('Deleting ' + self.endpoint + ' failed');
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
var service = new StackService($http, 'stacks', $q);
|
||||
return service;
|
||||
});
|
||||
|
||||
|
|
|
@ -74,10 +74,11 @@ class StackController extends Controller {
|
|||
* @param $title
|
||||
* @param $boardId
|
||||
* @param $order
|
||||
* @param $deletedAt
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $boardId, $order) {
|
||||
return $this->stackService->update($id, $title, $boardId, $order);
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
return $this->stackService->update($id, $title, $boardId, $order, $deletedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,4 +99,14 @@ class StackController extends Controller {
|
|||
public function delete($stackId) {
|
||||
return $this->stackService->delete($stackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function deleted($boardId) {
|
||||
return $this->stackService->fetchDeleted($boardId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,12 +27,14 @@ class Stack extends RelationalEntity {
|
|||
|
||||
protected $title;
|
||||
protected $boardId;
|
||||
protected $deletedAt;
|
||||
protected $cards = array();
|
||||
protected $order;
|
||||
|
||||
public function __construct() {
|
||||
$this->addType('id', 'integer');
|
||||
$this->addType('boardId', 'integer');
|
||||
$this->addType('deletedAt', 'integer');
|
||||
$this->addType('order', 'integer');
|
||||
}
|
||||
|
||||
|
@ -47,4 +49,4 @@ class Stack extends RelationalEntity {
|
|||
}
|
||||
return $json;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,10 +51,17 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
|||
|
||||
|
||||
public function findAll($boardId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*deck_stacks` WHERE `board_id` = ? ORDER BY `order`';
|
||||
$sql = 'SELECT * FROM `*PREFIX*deck_stacks` WHERE `board_id` = ? AND deleted_at = 0 ORDER BY `order`';
|
||||
return $this->findEntities($sql, [$boardId], $limit, $offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function findDeleted($boardId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*deck_stacks` s
|
||||
WHERE `s`.`board_id` = ? AND NOT s.deleted_at = 0';
|
||||
return $this->findEntities($sql, [$boardId], $limit, $offset);
|
||||
}
|
||||
|
||||
|
||||
public function delete(Entity $entity) {
|
||||
// delete cards on stack
|
||||
|
@ -73,4 +80,4 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
|||
$entity = $this->find($stackId);
|
||||
return $entity->getBoardId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace OCA\Deck\Service;
|
|||
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Db\AssignedUsersMapper;
|
||||
use OCA\Deck\Db\Stack;
|
||||
|
@ -38,6 +39,7 @@ class StackService {
|
|||
|
||||
private $stackMapper;
|
||||
private $cardMapper;
|
||||
private $boardMapper;
|
||||
private $labelMapper;
|
||||
private $permissionService;
|
||||
private $boardService;
|
||||
|
@ -46,6 +48,7 @@ class StackService {
|
|||
|
||||
public function __construct(
|
||||
StackMapper $stackMapper,
|
||||
BoardMapper $boardMapper,
|
||||
CardMapper $cardMapper,
|
||||
LabelMapper $labelMapper,
|
||||
PermissionService $permissionService,
|
||||
|
@ -54,6 +57,7 @@ class StackService {
|
|||
AttachmentService $attachmentService
|
||||
) {
|
||||
$this->stackMapper = $stackMapper;
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->labelMapper = $labelMapper;
|
||||
$this->permissionService = $permissionService;
|
||||
|
@ -81,6 +85,11 @@ class StackService {
|
|||
return $stacks;
|
||||
}
|
||||
|
||||
public function fetchDeleted($boardId) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
return $this->stackMapper->findDeleted($boardId);
|
||||
}
|
||||
|
||||
public function findAllArchived($boardId) {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findAll($boardId);
|
||||
|
@ -115,10 +124,16 @@ class StackService {
|
|||
|
||||
public function delete($id) {
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
return $this->stackMapper->delete($this->stackMapper->find($id));
|
||||
|
||||
$stack = $this->stackMapper->find($id);
|
||||
$stack->setDeletedAt(time());
|
||||
$this->stackMapper->update($stack);
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
public function update($id, $title, $boardId, $order) {
|
||||
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
if ($this->boardService->isArchived($this->stackMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
|
@ -127,6 +142,7 @@ class StackService {
|
|||
$stack->setTitle($title);
|
||||
$stack->setBoardId($boardId);
|
||||
$stack->setOrder($order);
|
||||
$stack->setDeletedAt($deletedAt);
|
||||
return $this->stackMapper->update($stack);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</form>
|
||||
<button class="icon-delete button-inline stack-actions"
|
||||
ng-if="!s.status.editStack"
|
||||
ng-click="stackservice.delete(s.id)"></button>
|
||||
ng-click="stackDelete(s)"></button>
|
||||
</h3>
|
||||
<ul data-as-sortable="sortOptions" is-disabled="!boardservice.canEdit() || filter==='archive'" data-ng-model="s.cards" class="card-list" ng-class="{emptyStack: !s.cards.length}">
|
||||
<li class="card as-sortable-item"
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<p>{{ statusservice.text }}</p></div>
|
||||
</div>
|
||||
<div id="sidebar-header">
|
||||
<a class="icon-close" ui-sref="board" ng-click="sidebar.show=!sidebar.show" title="<?php p($l->t('Close')); ?>"> <?php
|
||||
?><span class="hidden-visually"><?php p($l->t('Close')); ?></span><?php
|
||||
<a class="icon-close" ui-sref="board" ng-click="sidebar.show=!sidebar.show" title="<?php p($l->t('Close')); ?>"> <?php
|
||||
?><span class="hidden-visually"><?php p($l->t('Close')); ?></span><?php
|
||||
?></a>
|
||||
<h3>{{ boardservice.getCurrent().title }}</h3>
|
||||
</div>
|
||||
|
@ -14,7 +14,8 @@
|
|||
<ul class="tabHeaders">
|
||||
<li class="tabHeader" ng-class="{'selected': (params.tab==0 || !params.tab)}" ui-sref="{tab: 0}"><a><?php p($l->t('Sharing')); ?></a></li>
|
||||
<li class="tabHeader" ng-class="{'selected': (params.tab==1)}" ui-sref="{tab: 1}"><a><?php p($l->t('Tags')); ?></a></li>
|
||||
<li class="tabHeader" ng-class="{'selected': (params.tab==2)}" ui-sref="{tab: 2}"><a><?php p($l->t('Deleted Cards')); ?></a></li>
|
||||
<li class="tabHeader" ng-class="{'selected': (params.tab==2)}" ui-sref="{tab: 2}"><a><?php p($l->t('Deleted Stacks')); ?></a></li>
|
||||
<li class="tabHeader" ng-class="{'selected': (params.tab==3)}" ui-sref="{tab: 3}"><a><?php p($l->t('Deleted Cards')); ?></a></li>
|
||||
</ul>
|
||||
<div class="tabsContainer">
|
||||
<div id="tabBoardShare" class="tab" ng-if="params.tab==0 || !params.tab">
|
||||
|
@ -120,17 +121,30 @@
|
|||
|
||||
</div>
|
||||
|
||||
<div id="board-detail-deleted-cards" class="tab deletedCardsTabView" ng-if="params.tab==2">
|
||||
<ul>
|
||||
<li ng-repeat="deletedCard in deletedCards">
|
||||
<dl>
|
||||
<dt>Title</dt>
|
||||
<dd>{{deletedCard.title}}<dd>
|
||||
<dt>Stack</dt>
|
||||
<dd>{{stackservice.data[deletedCard.stackId].title}}</dd>
|
||||
</dl>
|
||||
<a ng-click="cardUndoDelete(deletedCard)"><span class="icon icon-undo"></span><br /><span><?php p($l->t('Undo delete')); ?></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="board-detail-deleted-stacks" class="tab deletedStacksTabView" ng-if="params.tab==2">
|
||||
<ul>
|
||||
<li ng-repeat="deletedStack in deletedStacks">
|
||||
<dl>
|
||||
<dt>Title</dt>
|
||||
<dd>{{deletedStack.title}}<dd>
|
||||
</dl>
|
||||
<a ng-click="stackUndoDelete(deletedStack)"><span class="icon icon-undo"></span><br /><span><?php p($l->t('Undo delete')); ?></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="board-detail-deleted-cards" class="tab deletedCardsTabView" ng-if="params.tab==3">
|
||||
<ul>
|
||||
<li ng-repeat="deletedCard in deletedCards">
|
||||
<dl>
|
||||
<dt>Title</dt>
|
||||
<dd>{{deletedCard.title}}<dd>
|
||||
<dt>Stack</dt>
|
||||
<dd>{{stackservice.data[deletedCard.stackId].title}}</dd>
|
||||
</dl>
|
||||
|
||||
<a ng-click="cardUndoDelete(deletedCard)"><span class="icon icon-undo"></span><br /><span><?php p($l->t('Undo delete')); ?></span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Загрузка…
Ссылка в новой задаче