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">`)(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 @@ +
+ +
+
+ {{role}} +
+
+
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