Add SelfServeQuestions module with pagination, routing, and admin navigation integration
- Added new `SelfServeQuestionsPagination.vue` and `SelfServeQuestionsTable.vue` components for managing self-service questions with pagination support. - Introduced routing for self-service questions in the "Self-Serve" module under admin dashboard. - Updated `NavigationMenuItemsAdmin.vue` to include "Self-Serve Questions" navigation item. - Integrated filtering and auto-load functionality to support department and lane-specific views.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<script setup>
|
||||
import { usePaginatedListInstance } from "@/components/pagination/paginatedList.vue";
|
||||
const { loadList } = usePaginatedListInstance();
|
||||
import EditableTableColumn from "@/components/displays/buttons/EditableTableColumn.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
|
||||
// Define the props
|
||||
const props = defineProps({
|
||||
objects: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table is-fullwidth is-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.id.label }}</th>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.question.label }}</th>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.description.label }}</th>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.lane.label }}</th>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.product.label }}</th>
|
||||
<th>{{ SessionUser.objects.self_serve_questions.columns.order_priority.label }}</th>
|
||||
<th class="has-text-right">{{ SessionUser.objects.global.language.actions }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="object in objects" :key="object.id">
|
||||
<td>{{ object.id }}</td>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="question"
|
||||
:edit-function="SessionUser.objects.self_serve_questions.showEditObjectFieldForm"
|
||||
:permission-check-function="SessionUser.canAccessAdmin"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="description"
|
||||
:edit-function="SessionUser.objects.self_serve_questions.showEditObjectFieldForm"
|
||||
:permission-check-function="SessionUser.canAccessAdmin"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="lane"
|
||||
:edit-function="SessionUser.objects.self_serve_questions.showEditObjectFieldForm"
|
||||
:parse-function="(laneId) => 'Bane ' + laneId"
|
||||
:permission-check-function="SessionUser.canAccessAdmin"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="product"
|
||||
:edit-function="SessionUser.objects.self_serve_questions.showEditObjectFieldForm"
|
||||
:parse-function="(productId) => 'Produkt ' + productId"
|
||||
:permission-check-function="SessionUser.canAccessAdmin"
|
||||
/>
|
||||
<EditableTableColumn
|
||||
:object="object"
|
||||
:loadList="loadList"
|
||||
column="order_priority"
|
||||
:edit-function="SessionUser.objects.self_serve_questions.showEditObjectFieldForm"
|
||||
:permission-check-function="SessionUser.canAccessAdmin"
|
||||
/>
|
||||
<!-- Actions -->
|
||||
<td class="has-text-right">
|
||||
<button class="button is-small is-danger is-light" @click="SessionUser.objects.self_serve_questions.functions.showDeleteObjectForm(object.id, loadList)">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
<script setup>
|
||||
import SelfServeQuestionsTable from "@/components/displays/department/tables/SelfServeQuestionsTable.vue";
|
||||
|
||||
const props = defineProps({
|
||||
setDepartmentFilter: {
|
||||
type: [String, Number],
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
setLaneFilter: {
|
||||
type: [String, Number],
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
hideSearch: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
autoLoad: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
import { defineProps } from "vue";
|
||||
import {
|
||||
usePaginatedList,
|
||||
PaginatedListKey
|
||||
} from "@/components/pagination/paginatedList.vue";
|
||||
import { provide } from "vue";
|
||||
const paginatedList = usePaginatedList();
|
||||
provide(PaginatedListKey, paginatedList);
|
||||
const {
|
||||
list,
|
||||
loadList,
|
||||
setEndpoint,
|
||||
setFilter,
|
||||
setHideSearchField,
|
||||
} = paginatedList;
|
||||
|
||||
import TableLabeledPagination from "@/components/displays/pagination/TableLabeledPagination.vue";
|
||||
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
||||
|
||||
setEndpoint(SessionUser.objects.self_serve_questions.meta.endpoint, false);
|
||||
|
||||
// Hide the search field, if the hideSearch prop is set
|
||||
if (props.hideSearch) {
|
||||
setHideSearchField(true);
|
||||
}
|
||||
|
||||
if (props.setDepartmentFilter) {
|
||||
setFilter(
|
||||
"department",
|
||||
props.setDepartmentFilter
|
||||
);
|
||||
}
|
||||
|
||||
if (props.setLaneFilter) {
|
||||
setFilter(
|
||||
"lane",
|
||||
props.setLaneFilter
|
||||
);
|
||||
}
|
||||
|
||||
if (props.autoLoad) {
|
||||
loadList();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableLabeledPagination :label="SessionUser.objects.self_serve_questions.meta.title">
|
||||
<template #buttons>
|
||||
<button class="button is-primary is-small" @click="SessionUser.objects.self_serve_questions.showCreateObjectForm(loadList)">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-plus"></i>
|
||||
</span>
|
||||
<span>Tilføj {{ SessionUser.objects.self_serve_questions.meta.labels.single }}</span>
|
||||
</button>
|
||||
</template>
|
||||
<SelfServeQuestionsTable :objects="list" />
|
||||
</TableLabeledPagination>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -138,6 +138,14 @@ const items = computed<NavigationItemProps[]>(() => [
|
||||
permissions: ['admin', 'list_department_wash_lanes'],
|
||||
hidden: !isDepartmentSet.value,
|
||||
},
|
||||
// Selvbetjeningsspørgsmål
|
||||
{
|
||||
label: firstToUpperCase(SessionUser.objects.self_serve_questions.meta.labels.multiple),
|
||||
to: `/admin/${department_id.value}/modules/self-serve/questions`,
|
||||
type: 'department',
|
||||
permissions: ['admin'],
|
||||
hidden: !isDepartmentSet.value,
|
||||
},
|
||||
// Notifikationer
|
||||
{
|
||||
label: firstToUpperCase(SessionUser.objects.notifications.meta.labels.multiple),
|
||||
|
||||
@@ -111,6 +111,8 @@ import DepartmentTimeBookingsNew
|
||||
from "@/views/dashboards/departmentDashboard/modules/time-bookings/book/DepartmentTimeBookingsNew.vue";
|
||||
import DepartmentWashLanes from "@/views/dashboards/departmentDashboard/modules/wash-lanes/DepartmentWashLanes.vue";
|
||||
import DepartmentWashLane from "@/views/dashboards/departmentDashboard/modules/wash-lanes/DepartmentWashLane.vue";
|
||||
import DepartmentSelfServeQuestions
|
||||
from "@/views/dashboards/departmentDashboard/modules/self-serve/DepartmentSelfServeQuestions.vue";
|
||||
import ConfigurationLimble from "@/views/dashboards/superUserDashboard/configuration/ConfigurationLimble.vue";
|
||||
import MyVehicle from "@/views/dashboards/userDashboard/vehicles/MyVehicle.vue";
|
||||
import XLVaskPage from "@/views/dashboards/superUserDashboard/XLVaskPage.vue";
|
||||
@@ -405,6 +407,12 @@ export const router = createRouter({
|
||||
component: DepartmentWashLane,
|
||||
meta: { middleware: adminMiddleware, departmentSelection: true }
|
||||
},
|
||||
{
|
||||
name: 'selfservequestions',
|
||||
path: '/admin/:departmentId/modules/self-serve/questions',
|
||||
component: DepartmentSelfServeQuestions,
|
||||
meta: { middleware: adminMiddleware, departmentSelection: true }
|
||||
},
|
||||
{
|
||||
name: 'superuser',
|
||||
path: '/superuser',
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<script setup>
|
||||
import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrapper.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import DepartmentDashboardPageWrapper from "@/views/dashboards/departmentDashboard/DepartmentDashboardPageWrapper.vue";
|
||||
import NotFoundFallBackPageWrapper from "@/components/page/wrappers/NotFoundFallBackPageWrapper.vue";
|
||||
import SelfServeQuestionsPagination from "@/components/displays/pagination/models/DepartmentDashboard/SelfServeQuestionsPagination.vue";
|
||||
import PageTitle from "@/components/global/PageTitle.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RestrictedPageWrapper :hasPermission="SessionUser.canAccessAdmin()">
|
||||
<DepartmentDashboardPageWrapper>
|
||||
<NotFoundFallBackPageWrapper :exists="SessionUser.functions.getDepartmentIdFromUrl() && SessionUser.canAccessDepartment(SessionUser.functions.getDepartmentIdFromUrl())" error="Please select a department, that you have access to. If you believe this is an error, please contact support.">
|
||||
<PageTitle :title="SessionUser.objects.self_serve_questions.meta.title" :subtitle="SessionUser.objects.self_serve_questions.meta.description" />
|
||||
<SelfServeQuestionsPagination :setDepartmentFilter="SessionUser.functions.getDepartmentIdFromUrl()" :autoLoad="true" />
|
||||
</NotFoundFallBackPageWrapper>
|
||||
</DepartmentDashboardPageWrapper>
|
||||
</RestrictedPageWrapper>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -6,6 +6,7 @@ import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrap
|
||||
import DepartmentDashboardPageWrapper from "@/views/dashboards/departmentDashboard/DepartmentDashboardPageWrapper.vue";
|
||||
import NotFoundFallBackPageWrapper from "@/components/page/wrappers/NotFoundFallBackPageWrapper.vue";
|
||||
import PageTitle from "@/components/global/PageTitle.vue";
|
||||
import SelfServeQuestionsPagination from "@/components/displays/pagination/models/DepartmentDashboard/SelfServeQuestionsPagination.vue";
|
||||
|
||||
const router = useRouter();
|
||||
const laneId = router.currentRoute.value.params.id;
|
||||
@@ -118,6 +119,14 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="box">
|
||||
<SelfServeQuestionsPagination :set-department-filter="departmentId" :set-lane-filter="laneId" :auto-load="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="isLoading" class="has-text-centered section">
|
||||
<span class="icon is-large">
|
||||
|
||||
Reference in New Issue
Block a user