diff --git a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php
index 64ea095fd1..d325c1636b 100644
--- a/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php
+++ b/ProcessMaker/Http/Controllers/Api/UserConfigurationController.php
@@ -25,6 +25,9 @@ class UserConfigurationController extends Controller
'tasks' => [
'isMenuCollapse' => true,
],
+ 'tasks_inbox' => [
+ 'isMenuCollapse' => false,
+ ],
];
public function index()
@@ -54,6 +57,7 @@ public function store(Request $request)
'ui_configuration.cases' => 'required|array',
'ui_configuration.requests' => 'required|array',
'ui_configuration.tasks' => 'required|array',
+ 'ui_configuration.tasks_inbox' => 'required|array',
]);
$uiConfiguration = json_encode($request->input('ui_configuration'));
diff --git a/ProcessMaker/Http/Controllers/TaskController.php b/ProcessMaker/Http/Controllers/TaskController.php
index fa4c945454..63c2fb474b 100755
--- a/ProcessMaker/Http/Controllers/TaskController.php
+++ b/ProcessMaker/Http/Controllers/TaskController.php
@@ -58,7 +58,9 @@ public function index()
$taskDraftsEnabled = TaskDraft::draftsEnabled();
- return view('tasks.index', compact('title', 'userFilter', 'defaultColumns', 'taskDraftsEnabled'));
+ $userConfiguration = (new UserConfigurationController())->index()['ui_configuration'] ?? [];
+
+ return view('tasks.index', compact('title', 'userFilter', 'defaultColumns', 'taskDraftsEnabled', 'userConfiguration'));
}
public function edit(ProcessRequestToken $task, string $preview = '')
diff --git a/resources/js/tasks/components/ParticipantHomeScreen.vue b/resources/js/tasks/components/ParticipantHomeScreen.vue
new file mode 100644
index 0000000000..cc12f71978
--- /dev/null
+++ b/resources/js/tasks/components/ParticipantHomeScreen.vue
@@ -0,0 +1,533 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ inOverdueMessage }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("Inbox Rules") }}
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/js/tasks/index.js b/resources/js/tasks/index.js
index 41ad99016b..ecea920a86 100644
--- a/resources/js/tasks/index.js
+++ b/resources/js/tasks/index.js
@@ -2,12 +2,18 @@ import Vue from "vue";
import TasksList from "./components/TasksList";
import TasksListCounter from "./components/TasksListCounter.vue";
import setDefaultAdvancedFilterStatus from "../common/setDefaultAdvancedFilterStatus";
+import ParticipantHomeScreen from './components/ParticipantHomeScreen.vue';
Vue.component("TasksList", TasksList);
+Vue.component('participant-home-screen', ParticipantHomeScreen);
new Vue({
el: "#tasks",
data: {
+ showOldTaskScreen: false,
+ userConfiguration: window.ProcessMaker.userConfiguration,
+ urlConfiguration: "users/configuration",
+ showMenu: true,
columns: window.Processmaker.defaultColumns || null,
filter: "",
pmql: "",
@@ -62,7 +68,9 @@ new Vue({
if (!window.location.search.includes("filter_user_recommendation")) {
this.$nextTick(() => {
- this.$refs.taskList.fetch();
+ if (this.$refs.taskList) {
+ this.$refs.taskList.fetch();
+ }
});
}
},
diff --git a/resources/js/tasks/mixins/TasksMixin.js b/resources/js/tasks/mixins/TasksMixin.js
new file mode 100644
index 0000000000..ad96cc0a3e
--- /dev/null
+++ b/resources/js/tasks/mixins/TasksMixin.js
@@ -0,0 +1,191 @@
+export default {
+ data() {
+ return {
+ showOldTaskScreen: false,
+ urlConfiguration: "users/configuration",
+ showMenu: false,
+ columns: window.Processmaker.defaultColumns || null,
+ filter: "",
+ pmql: "",
+ urlPmql: "",
+ filtersPmql: "",
+ fullPmql: "",
+ status: [],
+ inOverdueMessage: "",
+ additions: [],
+ priorityField: "is_priority",
+ draftField: "draft",
+ isDataLoading: false,
+ inbox: true,
+ priority: false,
+ draft: false,
+ tab: "inbox",
+ inboxCount: null,
+ draftCount: null,
+ priorityCount: null,
+ priorityFilter: [
+ {
+ subject: {
+ type: "Field",
+ value: "is_priority",
+ },
+ operator: "=",
+ value: true,
+ _column_field: "is_priority",
+ _column_label: "Priority",
+ _hide_badge: true,
+ },
+ ],
+ draftFilter: [
+ {
+ subject: {
+ type: "Relationship",
+ value: "draft.id",
+ },
+ operator: ">",
+ value: 0,
+ _column_field: "draft",
+ _column_label: "Draft",
+ _hide_badge: true,
+ },
+ ],
+ };
+ },
+ computed: {
+ effectiveSavedsearchDefaultsEditRoute() {
+ return (
+ this.savedsearchDefaultsEditRoute ||
+ window.ProcessMaker.savedsearchDefaultsEditRoute
+ );
+ },
+ },
+ methods: {
+ defineUserConfiguration() {
+ this.localUserConfiguration = JSON.parse(
+ window.ProcessMaker.userConfiguration || "{}"
+ );
+ if (this.localUserConfiguration.tasks_inbox) {
+ this.showMenu = this.localUserConfiguration.tasks_inbox.isMenuCollapse;
+ } else {
+ this.showMenu = false;
+ this.localUserConfiguration.tasks_inbox = {
+ isMenuCollapse: false,
+ };
+ }
+ },
+ hideMenu() {
+ this.showMenu = !this.showMenu;
+ this.updateUserConfiguration();
+ },
+ updateUserConfiguration() {
+ this.localUserConfiguration.tasks_inbox.isMenuCollapse = this.showMenu;
+ ProcessMaker.apiClient
+ .put(this.urlConfiguration, {
+ ui_configuration: this.localUserConfiguration,
+ })
+ .catch((error) => {
+ console.error("Error", error);
+ });
+ },
+ switchTab(tab) {
+ this.tab = tab;
+ const taskListComponent = this.$refs.taskList;
+ taskListComponent.advancedFilter[this.priorityField] = [];
+ taskListComponent.advancedFilter[this.draftField] = [];
+ switch (tab) {
+ case "priority":
+ taskListComponent.advancedFilter["is_priority"] = this.priorityFilter;
+ break;
+ case "draft":
+ taskListComponent.advancedFilter["draft"] = this.draftFilter;
+ break;
+ }
+ taskListComponent.markStyleWhenColumnSetAFilter();
+ taskListComponent.storeFilterConfiguration();
+ taskListComponent.fetch(true);
+ },
+ dataLoading(value) {
+ this.isDataLoading = value;
+ },
+ onFetchTask() {
+ this.inbox = true;
+ this.priority = this.draft = false;
+ let filters = window.ProcessMaker.advanced_filter?.filters;
+ if (!Array.isArray(filters)) {
+ filters = [];
+ }
+ filters.forEach((item) => {
+ if (item._column_field === "is_priority") {
+ this.priority = true;
+ this.inbox = this.draft = false;
+ }
+ if (item._column_field === "draft") {
+ this.draft = true;
+ this.inbox = this.priority = false;
+ }
+ });
+ },
+ handleTabCount(value) {
+ if (this.tab === "inbox") {
+ this.inboxCount = value;
+ }
+ if (this.tab === "draft") {
+ this.draftCount = value;
+ }
+ if (this.tab === "priority") {
+ this.priorityCount = value;
+ }
+ },
+ onFiltersPmqlChange(value) {
+ this.filtersPmql = value[0];
+ this.fullPmql = this.getFullPmql();
+ },
+ onNLQConversion(query) {
+ this.onChange(query);
+ this.onSearch();
+ },
+ onChange(query) {
+ this.pmql = query;
+ this.fullPmql = this.getFullPmql();
+ },
+ onSearch() {
+ if (this.$refs.taskList) {
+ this.$refs.taskList.fetch(true);
+ }
+ },
+ onInboxRules() {
+ window.location.href = "/tasks/rules";
+ },
+ setInOverdueMessage(inOverdue) {
+ let inOverdueMessage = "";
+ if (inOverdue) {
+ const taskText =
+ inOverdue > 1
+ ? this.$t("Tasks").toLowerCase()
+ : this.$t("Task").toLowerCase();
+ inOverdueMessage = this.$t(
+ "You have {{ inOverDue }} overdue {{ taskText }} pending",
+ { inOverDue: inOverdue, taskText }
+ );
+ }
+ this.inOverdueMessage = inOverdueMessage;
+ },
+ getFullPmql() {
+ let fullPmqlString = "";
+
+ if (this.filtersPmql && this.filtersPmql !== "") {
+ fullPmqlString = this.filtersPmql;
+ }
+
+ if (fullPmqlString !== "" && this.pmql && this.pmql !== "") {
+ fullPmqlString = `${fullPmqlString} AND ${this.pmql}`;
+ }
+
+ if (fullPmqlString === "" && this.pmql && this.pmql !== "") {
+ fullPmqlString = this.pmql;
+ }
+
+ return fullPmqlString;
+ },
+ },
+};
diff --git a/resources/views/tasks/index.blade.php b/resources/views/tasks/index.blade.php
index cc3082c845..41cb76000e 100644
--- a/resources/views/tasks/index.blade.php
+++ b/resources/views/tasks/index.blade.php
@@ -1,7 +1,7 @@
@extends('layouts.layout')
@section('title')
- {{__($title)}}
+ {{ __($title) }}
@endsection
@section('sidebar')
@@ -9,175 +9,157 @@
@endsection
@section('breadcrumbs')
- @include('shared.breadcrumbs', ['routes' => [
- __('Tasks') => route('tasks.index'),
- __($title) => null,
- ]])
+ @include('shared.breadcrumbs', [
+ 'routes' => [
+ __('Tasks') => route('tasks.index'),
+ __($title) => null,
+ ],
+ ])
@endsection
+
@section('content')
-
-
-
-
- @{{ inOverdueMessage }}
-
-
-
+
+
+
+
+
+
+ @{{ inOverdueMessage }}
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ __('Inbox Rules') }}
-
-
-
-
-

-
-
- {!! __('Inbox Rules act as your personal task manager. You tell them what to look for, and they take care of things automatically.') !!}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ __('Inbox Rules') }}
+
+
+
+
+

+
+
+ {!! __(
+ 'Inbox Rules act as your personal task manager. You tell them what to look for, and they take care of things automatically.',
+ ) !!}
+
+
+
+ @if (
+ (Auth::user()->is_administrator || Auth::user()->hasPermission('edit-screens')) &&
+ Route::has('package.savedsearch.defaults.edit'))
+
+
+
+ @endif
+
+
+
+
+
+
+
-
- @if((
- Auth::user()->is_administrator ||
- Auth::user()->hasPermission('edit-screens')
- ) && Route::has('package.savedsearch.defaults.edit'))
-
-
-
- @endif
-
-
-
+
+
-
-
-
-
-
-
+
-
@endsection
@section('js')
-
+
@endsection
@section('css')
@@ -222,14 +204,17 @@ class="ml-md-2"
min-height: 25px;
border-radius: 50%;
}
+
.task-nav {
border-bottom: 0 !important;
}
+
.task-nav-link.active {
color: #1572C2 !important;
font-weight: 700;
font-size: 15px;
}
+
.task-nav-link {
color: #556271;
font-weight: 400;
@@ -237,25 +222,231 @@ class="ml-md-2"
border-top-left-radius: 5px !important;
border-top-right-radius: 5px !important;
}
+
.task-list-body {
border-radius: 5px;
}
+
.task-inbox-rules {
- width: max-content;
+ width: max-content;
}
+
.task-inbox-rules-content {
- display: flex;
- justify-content: space-between;
- padding: 15px;
+ display: flex;
+ justify-content: space-between;
+ padding: 15px;
}
+
.task-inbox-rules-content-text {
- width: 310px;
- padding-left: 10px;
+ width: 310px;
+ padding-left: 10px;
}
+
@endsection
diff --git a/tests/Feature/Api/UserConfigurationTest.php b/tests/Feature/Api/UserConfigurationTest.php
index 0a2b4a0c8d..95fdce0acc 100644
--- a/tests/Feature/Api/UserConfigurationTest.php
+++ b/tests/Feature/Api/UserConfigurationTest.php
@@ -55,6 +55,9 @@ public function testStoreUserConfigurationAndGetNewValues()
'tasks' => [
'isMenuCollapse' => false,
],
+ 'tasks_inbox' => [
+ 'isMenuCollapse' => false,
+ ],
];
$response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]);
@@ -74,6 +77,7 @@ public function testStoreUserConfigurationAndGetNewValues()
$this->assertEquals($uiConfig->cases->isMenuCollapse, $values['cases']['isMenuCollapse']);
$this->assertEquals($uiConfig->requests->isMenuCollapse, $values['requests']['isMenuCollapse']);
$this->assertEquals($uiConfig->tasks->isMenuCollapse, $values['tasks']['isMenuCollapse']);
+ $this->assertEquals($uiConfig->tasks_inbox->isMenuCollapse, $values['tasks_inbox']['isMenuCollapse']);
}
/**
@@ -86,7 +90,7 @@ public function testStoreUserConfigurationWithInvalidValues()
// Validate the header status code
$response->assertStatus(422);
- $this->assertEquals('The Ui configuration field is required. (and 4 more errors)', $response->json()['message']);
+ $this->assertEquals('The Ui configuration field is required. (and 5 more errors)', $response->json()['message']);
// An incomplete ui_configuration
$values = [
@@ -99,6 +103,9 @@ public function testStoreUserConfigurationWithInvalidValues()
'tasks' => [
'isMenuCollapse' => false,
],
+ 'tasks_inbox' => [
+ 'isMenuCollapse' => false,
+ ],
];
$response = $this->apiCall('PUT', self::API_TEST_URL, ['ui_configuration' => $values]);
// Validate the header status code