diff --git a/src/app/task/task-list/accept.html b/src/app/task/task-list/accept.html
new file mode 100644
index 0000000..3e92919
--- /dev/null
+++ b/src/app/task/task-list/accept.html
@@ -0,0 +1,10 @@
+
+
{{"tasks.actions.accept.confirmation.title" | translate}}
+
+
+
+
+
+
+
+
diff --git a/src/app/task/task-list/reject.html b/src/app/task/task-list/reject.html
new file mode 100644
index 0000000..b8ca697
--- /dev/null
+++ b/src/app/task/task-list/reject.html
@@ -0,0 +1,10 @@
+
+
{{"tasks.actions.reject.confirmation.title" | translate}}
+
+
+
+
+
+
+
+
diff --git a/src/app/task/task-list/task-accept.component.ts b/src/app/task/task-list/task-accept.component.ts
new file mode 100644
index 0000000..cd9df70
--- /dev/null
+++ b/src/app/task/task-list/task-accept.component.ts
@@ -0,0 +1,21 @@
+import { Input, Inject, Component } from 'ng-forward';
+import { AddMemberTaskAcceptComponent } from "../types/add-member/add-member-task-accept.component";
+
+@Component({
+ selector: 'task-accept',
+ template: '',
+ directives: [AddMemberTaskAcceptComponent]
+})
+@Inject("$element", "$scope", "$injector", "$compile")
+export class TaskAcceptComponent {
+
+ @Input() task: noosfero.Task;
+
+ ngOnInit() {
+ let componentName = this.task.type.replace(/::/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+ componentName += "-task-accept";
+ this.$element.replaceWith(this.$compile(`<${componentName} [task]="ctrl.task">${componentName}>`)(this.$scope));
+ }
+
+ constructor(private $element: any, private $scope: ng.IScope, private $injector: ng.auto.IInjectorService, private $compile: ng.ICompileService) { }
+}
diff --git a/src/app/task/task-list/task-list.component.ts b/src/app/task/task-list/task-list.component.ts
index 0d34995..fd23600 100644
--- a/src/app/task/task-list/task-list.component.ts
+++ b/src/app/task/task-list/task-list.component.ts
@@ -1,20 +1,101 @@
-import { Component, Input } from "ng-forward";
+import { Component, Input, Inject } from "ng-forward";
+import { NotificationService } from "../../shared/services/notification.service";
+import { TaskService } from "../../../lib/ng-noosfero-api/http/task.service";
+import { TaskAcceptComponent } from "./task-accept.component";
@Component({
selector: "task-list",
templateUrl: "app/task/task-list/task-list.html",
+ directives: [TaskAcceptComponent]
})
+@Inject(NotificationService, "$scope", "$uibModal", TaskService)
export class TaskListComponent {
@Input() tasks: noosfero.Task[];
- private taskTemplates = ["AddFriend", "AddMember", "CreateCommunity"];
+ private taskTemplates = ["AddFriend", "AddMember", "CreateCommunity", "SuggestArticle", "AbuseComplaint"];
+
+ rejectionExplanation: string;
+ currentTask: noosfero.Task;
+ private modalInstance: any = null;
+
+ constructor(private notificationService: NotificationService, private $scope: ng.IScope, private $uibModal: any, private taskService: TaskService) { }
getTaskTemplate(task: noosfero.Task) {
if (this.taskTemplates.indexOf(task.type) >= 0) {
- return 'app/task/types/' + task.type + '.html';
+ let templateName = this.getTemplateName(task);
+ return `app/task/types/${templateName}/${templateName}.html`;
} else {
return 'app/task/types/default.html';
}
}
+
+ accept(task: noosfero.Task) {
+ this.currentTask = task;
+ if (task.accept_details) {
+ this.modalInstance = this.$uibModal.open({
+ templateUrl: "app/task/task-list/accept.html",
+ controller: TaskListComponent,
+ controllerAs: 'modal',
+ bindToController: true,
+ scope: this.$scope
+ });
+ } else {
+ this.callAccept();
+ }
+ }
+
+ reject(task: noosfero.Task) {
+ this.currentTask = task;
+ if (task.reject_details) {
+ this.modalInstance = this.$uibModal.open({
+ templateUrl: "app/task/task-list/reject.html",
+ controller: TaskListComponent,
+ controllerAs: 'modal',
+ bindToController: true,
+ scope: this.$scope
+ });
+ } else {
+ this.callReject();
+ }
+ }
+
+ callAccept() {
+ this.taskService.finishTask(this.currentTask).then(() => {
+ this.removeTask(this.currentTask);
+ this.notificationService.success({ title: "tasks.actions.accept.title", message: "tasks.actions.accept.message" });
+ }).finally(() => {
+ this.cancel();
+ });
+ }
+
+ callReject() {
+ this.taskService.cancelTask(this.currentTask).then(() => {
+ this.removeTask(this.currentTask);
+ this.notificationService.success({ title: "tasks.actions.reject.title", message: "tasks.actions.reject.message" });
+ }).finally(() => {
+ this.cancel();
+ });
+ }
+
+ cancel() {
+ if (this.modalInstance) {
+ this.modalInstance.close();
+ this.modalInstance = null;
+ }
+ if (this.currentTask) {
+ this.currentTask = null;
+ }
+ }
+
+ private getTemplateName(task: noosfero.Task) {
+ return task.type.replace(/::/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase());
+ }
+
+ private removeTask(task: noosfero.Task) {
+ let index = this.tasks.indexOf(task, 0);
+ if (index > -1) {
+ this.tasks.splice(index, 1);
+ }
+ }
}
diff --git a/src/app/task/task-list/task-list.html b/src/app/task/task-list/task-list.html
index cd7ac81..42ded9f 100644
--- a/src/app/task/task-list/task-list.html
+++ b/src/app/task/task-list/task-list.html
@@ -8,6 +8,14 @@
+
•
diff --git a/src/app/task/task-list/task-list.scss b/src/app/task/task-list/task-list.scss
index 5131177..4ec8912 100644
--- a/src/app/task/task-list/task-list.scss
+++ b/src/app/task/task-list/task-list.scss
@@ -1,3 +1,6 @@
+$task-action-accept-color: #77c123;
+$task-action-reject-color: #d64e18;
+
.task-list {
width: 100%;
padding: 0;
@@ -24,15 +27,36 @@
}
.task-body {
margin-left: 35px;
- padding: 3px;
+ padding: 2px;
.task {
display: inline-block;
+ color: #949494;
.task-icon {
font-size: 18px;
color: #e84e40;
}
.requestor, .target {
font-style: italic;
+ color: #676767;
+ }
+ }
+ .actions {
+ display: inline-block;
+ font-size: 19px;
+ a {
+ text-decoration: none;
+ }
+ .accept {
+ color: $task-action-accept-color;
+ &:hover {
+ color: darken($task-action-accept-color, 10%);
+ }
+ }
+ .reject {
+ color: $task-action-reject-color;
+ &:hover {
+ color: darken($task-action-reject-color, 10%);
+ }
}
}
.time {
@@ -45,3 +69,18 @@
}
}
}
+.task-confirmation {
+ @extend .form-group;
+ .confirmation-details {
+ margin-bottom: 20px;
+ }
+ .confirmation-title {
+ text-align: center;
+ font-size: 30px;
+ font-weight: bold;
+ margin-bottom: 20px;
+ }
+ .actions {
+ text-align: center;
+ }
+}
diff --git a/src/app/task/tasks-menu/tasks-menu.component.ts b/src/app/task/tasks-menu/tasks-menu.component.ts
index b599abb..919a0b1 100644
--- a/src/app/task/tasks-menu/tasks-menu.component.ts
+++ b/src/app/task/tasks-menu/tasks-menu.component.ts
@@ -11,14 +11,14 @@ export class TasksMenuComponent {
tasks: noosfero.Task[];
total: number;
- perPage: 5;
+ perPage = 5;
person: noosfero.Person;
constructor(private taskService: TaskService, private session: SessionService) { }
ngOnInit() {
this.person = this.session.currentUser() ? this.session.currentUser().person : null;
- this.taskService.getAllPending({ per_page: this.perPage }).then((result: noosfero.RestResult) => {
+ this.taskService.getAllPending({ per_page: this.perPage }).then((result: noosfero.RestResult) => {
this.total = result.headers('total');
this.tasks = result.data;
});
diff --git a/src/app/task/tasks-menu/tasks-menu.scss b/src/app/task/tasks-menu/tasks-menu.scss
index ecbb577..42bf07b 100644
--- a/src/app/task/tasks-menu/tasks-menu.scss
+++ b/src/app/task/tasks-menu/tasks-menu.scss
@@ -12,14 +12,13 @@ tasks-menu {
}
.all-tasks {
text-align: center;
- width: 97%;
+ width: 100%;
display: block;
- margin-left: auto;
- margin-right: auto;
+ line-height: 25px;
}
.task-panel {
width: 550px;
- padding-top: 0;
+ padding: 0;
}
.task-menu-header {
text-align: center;
diff --git a/src/app/task/tasks/tasks.component.ts b/src/app/task/tasks/tasks.component.ts
index 8db03b3..e0b1fc4 100644
--- a/src/app/task/tasks/tasks.component.ts
+++ b/src/app/task/tasks/tasks.component.ts
@@ -14,14 +14,14 @@ export class TasksComponent {
tasks: noosfero.Task[];
total: number;
currentPage: number;
- perPage: 5;
+ perPage = 5;
constructor(private taskService: TaskService) {
this.loadPage();
}
loadPage() {
- this.taskService.getAllPending({ page: this.currentPage, per_page: this.perPage }).then((result: noosfero.RestResult) => {
+ this.taskService.getAllPending({ page: this.currentPage, per_page: this.perPage }).then((result: noosfero.RestResult) => {
this.total = result.headers('total');
this.tasks = result.data;
});
diff --git a/src/app/task/tasks/tasks.html b/src/app/task/tasks/tasks.html
index 1725793..eb5644a 100644
--- a/src/app/task/tasks/tasks.html
+++ b/src/app/task/tasks/tasks.html
@@ -1,4 +1,4 @@
-Tarefas
+{{"tasks.header" | translate}}
diff --git a/src/app/task/types/AddFriend.html b/src/app/task/types/AddFriend.html
deleted file mode 100644
index 5201fa5..0000000
--- a/src/app/task/types/AddFriend.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-{{task.requestor.name}} wants to be friend of {{task.target.name}}
diff --git a/src/app/task/types/AddMember.html b/src/app/task/types/AddMember.html
deleted file mode 100644
index 4248c7f..0000000
--- a/src/app/task/types/AddMember.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-{{task.requestor.name}} wants to join {{task.target.name}}
diff --git a/src/app/task/types/CreateCommunity.html b/src/app/task/types/CreateCommunity.html
deleted file mode 100644
index 2583380..0000000
--- a/src/app/task/types/CreateCommunity.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-{{task.requestor.name}} wants to create a new community: {{task.data.name}}
diff --git a/src/app/task/types/abuse-complaint/abuse-complaint.html b/src/app/task/types/abuse-complaint/abuse-complaint.html
new file mode 100644
index 0000000..69cef3b
--- /dev/null
+++ b/src/app/task/types/abuse-complaint/abuse-complaint.html
@@ -0,0 +1,2 @@
+
+{{task.requestor.name}} was reported due to inappropriate behavior
diff --git a/src/app/task/types/add-friend/add-friend.html b/src/app/task/types/add-friend/add-friend.html
new file mode 100644
index 0000000..a0eb2ff
--- /dev/null
+++ b/src/app/task/types/add-friend/add-friend.html
@@ -0,0 +1,2 @@
+
+{{task.requestor.name}} wants to be friend of {{task.target.name}}
diff --git a/src/app/task/types/add-member/add-member-accept.html b/src/app/task/types/add-member/add-member-accept.html
new file mode 100644
index 0000000..6aa2cce
--- /dev/null
+++ b/src/app/task/types/add-member/add-member-accept.html
@@ -0,0 +1,8 @@
+
diff --git a/src/app/task/types/add-member/add-member-task-accept.component.ts b/src/app/task/types/add-member/add-member-task-accept.component.ts
new file mode 100644
index 0000000..112f533
--- /dev/null
+++ b/src/app/task/types/add-member/add-member-task-accept.component.ts
@@ -0,0 +1,17 @@
+import { Component, Input, Inject } from "ng-forward";
+
+@Component({
+ selector: "add-member-task-accept",
+ templateUrl: "app/task/types/add-member/add-member-accept.html",
+})
+export class AddMemberTaskAcceptComponent {
+
+ @Input() task: noosfero.Task;
+ roles: any;
+
+ constructor() {
+ //TODO list roles from API
+ this.roles = ["Profile Administrator", "Member", "Moderator"];
+ }
+
+}
diff --git a/src/app/task/types/add-member/add-member.html b/src/app/task/types/add-member/add-member.html
new file mode 100644
index 0000000..3c28a3a
--- /dev/null
+++ b/src/app/task/types/add-member/add-member.html
@@ -0,0 +1,2 @@
+
+{{task.requestor.name}} wants to join {{task.target.name}}
diff --git a/src/app/task/types/add-member/add-member.scss b/src/app/task/types/add-member/add-member.scss
new file mode 100644
index 0000000..f00d917
--- /dev/null
+++ b/src/app/task/types/add-member/add-member.scss
@@ -0,0 +1,5 @@
+.add-member-details {
+ .roles {
+ margin-left: 40px;
+ }
+}
diff --git a/src/app/task/types/create-community/create-community.html b/src/app/task/types/create-community/create-community.html
new file mode 100644
index 0000000..6240152
--- /dev/null
+++ b/src/app/task/types/create-community/create-community.html
@@ -0,0 +1,2 @@
+
+{{task.requestor.name}} wants to create a new community: {{task.data.name}}
diff --git a/src/app/task/types/suggest-article/suggest-article.html b/src/app/task/types/suggest-article/suggest-article.html
new file mode 100644
index 0000000..d35312f
--- /dev/null
+++ b/src/app/task/types/suggest-article/suggest-article.html
@@ -0,0 +1,2 @@
+
+{{task.requestor.name}} suggested a new article: {{task.data.article.name}}
diff --git a/src/languages/en.json b/src/languages/en.json
index 40b9a98..1c188f0 100644
--- a/src/languages/en.json
+++ b/src/languages/en.json
@@ -103,5 +103,17 @@
"date.on": "On",
"tasks.menu.all": "All tasks",
"tasks.menu.all": "See all tasks",
- "tasks.menu.header": "You have {tasks, plural, one{one pending task} other{# pending tasks}}"
+ "tasks.menu.header": "You have {tasks, plural, one{one pending task} other{# pending tasks}}",
+ "tasks.actions.accept": "Accept",
+ "tasks.actions.reject": "Reject",
+ "tasks.header": "Tasks",
+ "tasks.actions.accept.confirmation.title": "Confirm task acceptance?",
+ "tasks.actions.reject.confirmation.title": "Confirm task rejection?",
+ "tasks.actions.confirmation.yes": "Yes",
+ "tasks.actions.confirmation.cancel": "Cancel",
+ "tasks.actions.accept.title": "Good job!",
+ "tasks.actions.reject.title": "Good job!",
+ "tasks.actions.accept.message": "Task Accepted",
+ "tasks.actions.reject.message": "Task Rejected",
+ "tasks.actions.reject.explanation.label": "Rejection explanation"
}
diff --git a/src/languages/pt.json b/src/languages/pt.json
index 48b7f78..f3e48ab 100644
--- a/src/languages/pt.json
+++ b/src/languages/pt.json
@@ -103,5 +103,17 @@
"date.on": "Em",
"tasks.menu.all": "Todas as tarefas",
"tasks.menu.all": "Veja todas as tarefas",
- "tasks.menu.header": "Você tem {tasks, plural, one{uma tarefa pendente} other{# tarefas pendentes}}"
+ "tasks.menu.header": "Você tem {tasks, plural, one{uma tarefa pendente} other{# tarefas pendentes}}",
+ "tasks.actions.accept": "Aceitar",
+ "tasks.actions.reject": "Rejeitar",
+ "tasks.header": "Tarefas",
+ "tasks.actions.accept.confirmation.title": "Confirmar aprovação da tarefa?",
+ "tasks.actions.reject.confirmation.title": "Confirmar reprovação da tarefa?",
+ "tasks.actions.confirmation.yes": "Sim",
+ "tasks.actions.confirmation.cancel": "Cancelar",
+ "tasks.actions.accept.title": "Bom trabalho!",
+ "tasks.actions.reject.title": "Bom trabalho!",
+ "tasks.actions.accept.message": "Tarefa Aceita",
+ "tasks.actions.reject.message": "Tarefa Rejeitada",
+ "tasks.actions.reject.explanation.label": "Motivo da rejeição"
}
diff --git a/src/lib/ng-noosfero-api/http/task.service.ts b/src/lib/ng-noosfero-api/http/task.service.ts
index ba94e40..7de9136 100644
--- a/src/lib/ng-noosfero-api/http/task.service.ts
+++ b/src/lib/ng-noosfero-api/http/task.service.ts
@@ -24,4 +24,14 @@ export class TaskService extends RestangularService {
params['all_pending'] = true;
return this.list(null, params);
}
+
+ finishTask(task: noosfero.Task) {
+ let element = this.getElement(task.id);
+ return element.customPUT(null, "finish");
+ }
+
+ cancelTask(task: noosfero.Task) {
+ let element = this.getElement(task.id);
+ return element.customPUT(null, "cancel");
+ }
}
diff --git a/src/lib/ng-noosfero-api/interfaces/task.ts b/src/lib/ng-noosfero-api/interfaces/task.ts
index 3ccc7e4..4882e6d 100644
--- a/src/lib/ng-noosfero-api/interfaces/task.ts
+++ b/src/lib/ng-noosfero-api/interfaces/task.ts
@@ -7,5 +7,7 @@ namespace noosfero {
*/
export interface Task extends RestModel {
type: string;
+ accept_details: boolean;
+ reject_details: boolean;
}
}
--
libgit2 0.21.2