Skip to content

Commit 5f79e75

Browse files
committed
Update CasesRetentionLog listing
1 parent becd985 commit 5f79e75

4 files changed

Lines changed: 326 additions & 5 deletions

File tree

Lines changed: 238 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,240 @@
11
<template>
2-
<div>
3-
2+
<div>
3+
<div class="data-table">
4+
<data-loading
5+
v-show="shouldShowLoader"
6+
:for="/cases-retention-logs/"
7+
:empty="$t('No Data Available')"
8+
:empty-desc="$t('')"
9+
empty-icon="noData"
10+
/>
11+
<div
12+
v-show="!shouldShowLoader"
13+
class="card card-body table-card"
14+
>
15+
<vuetable
16+
:data-manager="dataManager"
17+
:css="css"
18+
:api-mode="false"
19+
:fields="fields"
20+
:data="data"
21+
data-path="data"
22+
:no-data-template="$t('No Data Available')"
23+
pagination-path="meta"
24+
@vuetable:pagination-data="onPaginationData"
25+
>
26+
<template
27+
slot="process_name"
28+
slot-scope="props"
29+
>
30+
<span v-uni-id="props.rowData.id.toString()">{{ props.rowData.name }}</span>
31+
</template>
32+
<template
33+
slot="case_id"
34+
slot-scope="props"
35+
>
36+
<span v-uni-id="`case-id-${props.rowData.id}`">{{ props.rowData.case_id }}</span>
37+
</template>
38+
<template
39+
slot="deleted_at"
40+
slot-scope="props"
41+
>
42+
{{ formatDate(props.rowData.deleted_at) }}
43+
</template>
44+
</vuetable>
45+
<pagination
46+
ref="pagination"
47+
:single="$t('Case')"
48+
:plural="$t('Cases')"
49+
:per-page-select-enabled="true"
50+
@changePerPage="changePerPage"
51+
@vuetable-pagination:change-page="onPageChange"
52+
/>
53+
</div>
454
</div>
5-
</template>
55+
</div>
56+
</template>
57+
58+
<script>
59+
import datatableMixin from "../../../components/common/mixins/datatable";
60+
import dataLoadingMixin from "../../../components/common/mixins/apiDataLoading";
61+
62+
/**
63+
* Fake data matching retention_policy_logs schema until the table/API exists.
64+
* - id, process_id, case_id (single or serialized list), deleted_at, created_at
65+
*/
66+
const FAKE_RETENTION_LOGS = [
67+
{
68+
id: 1,
69+
process_id: 101,
70+
case_id: 5001,
71+
deleted_at: "2025-03-01T14:30:00.000000Z",
72+
created_at: "2025-03-01T14:30:05.000000Z",
73+
},
74+
{
75+
id: 2,
76+
process_id: 101,
77+
case_id: 5002,
78+
deleted_at: "2025-03-02T09:15:00.000000Z",
79+
created_at: "2025-03-02T09:15:02.000000Z",
80+
},
81+
{
82+
id: 3,
83+
process_id: 204,
84+
case_id: "[7001, 7002, 7003]",
85+
deleted_at: "2025-03-03T16:45:00.000000Z",
86+
created_at: "2025-03-03T16:45:10.000000Z",
87+
},
88+
{
89+
id: 4,
90+
process_id: 305,
91+
case_id: 8010,
92+
deleted_at: "2025-03-04T11:00:00.000000Z",
93+
created_at: "2025-03-04T11:00:01.000000Z",
94+
},
95+
{
96+
id: 5,
97+
process_id: 204,
98+
case_id: 7005,
99+
deleted_at: "2025-03-05T08:22:00.000000Z",
100+
created_at: "2025-03-05T08:22:03.000000Z",
101+
},
102+
];
103+
104+
export default {
105+
name: "CasesRetentionLogs",
106+
mixins: [datatableMixin, dataLoadingMixin],
107+
props: {
108+
filter: {
109+
type: String,
110+
default: "",
111+
},
112+
},
113+
data() {
114+
return {
115+
orderBy: "name",
116+
data: [],
117+
fields: [
118+
{
119+
title: () => this.$t("Process"),
120+
name: "__slot:process_name",
121+
width: "33%",
122+
},
123+
{
124+
title: () => this.$t("Case ID"),
125+
name: "__slot:case_id",
126+
width: "33%",
127+
},
128+
{
129+
title: () => this.$t("Deleted At"),
130+
name: "__slot:deleted_at",
131+
callback: "formatDate",
132+
width: "33%",
133+
},
134+
],
135+
};
136+
},
137+
watch: {
138+
filter() {
139+
this.page = 1;
140+
this.fetch();
141+
},
142+
},
143+
methods: {
144+
fetch() {
145+
// TODO: replace with API call when retention_policy_logs table and endpoint exist
146+
// e.g. ProcessMaker.apiClient.get('/retention-policy-logs').then(r => {
147+
// this.data = r.data; // expect { data: [...], meta: { total, per_page, current_page, ... } }
148+
// }).finally(() => { this.apiDataLoading = false; });
149+
const total = FAKE_RETENTION_LOGS.length;
150+
this.data = {
151+
data: FAKE_RETENTION_LOGS,
152+
meta: {
153+
total,
154+
per_page: 15,
155+
current_page: 1,
156+
last_page: 1,
157+
from: 1,
158+
to: total,
159+
total_pages: 1,
160+
count: total,
161+
},
162+
};
163+
this.apiDataLoading = false;
164+
},
165+
reload() {
166+
this.fetch();
167+
},
168+
},
169+
};
170+
</script>
171+
172+
<style lang="scss" scoped>
173+
.data-table {
174+
.table-card {
175+
border-radius: 8px;
176+
border: 1px solid #D7DDE5;
177+
}
178+
179+
.vuetable {
180+
border-radius: 8px;
181+
overflow: hidden;
182+
183+
thead {
184+
th {
185+
background-color: #FBFBFC !important;
186+
border-bottom: 1px solid #D7DDE5 !important;
187+
border-right: 1px solid #D7DDE5 !important;
188+
font-weight: 600 !important;
189+
color: #596372 !important;
190+
padding: 12px 16px !important;
191+
font-family: 'Inter', sans-serif !important;
192+
font-weight: 600 !important;
193+
line-height: 20px !important;
194+
letter-spacing: -0.01em !important;
195+
font-size: 14px !important;
196+
197+
&:last-child {
198+
border-right: none !important;
199+
}
200+
}
201+
}
202+
}
203+
}
204+
205+
// Global override for Vuetable styles
206+
:deep(.vuetable) {
207+
thead th {
208+
background-color: #FBFBFC !important;
209+
border-bottom: 1px solid #D7DDE5 !important;
210+
border-right: 1px solid #D7DDE5 !important;
211+
font-weight: 600 !important;
212+
color: #596372 !important;
213+
padding: 12px 16px !important;
214+
font-family: 'Inter', sans-serif !important;
215+
line-height: 20px !important;
216+
font-size: 14px !important;
217+
}
218+
219+
thead th:last-child {
220+
border-right: none !important;
221+
}
222+
223+
tbody {
224+
tr {
225+
color: #4E5663 !important;
226+
border-bottom: 1px solid #E9ECEF !important;
227+
font-family: 'Inter', sans-serif !important;
228+
font-weight: 400 !important;
229+
font-size: 14px !important;
230+
line-height: 20px !important;
231+
232+
td {
233+
padding: 12px 16px !important;
234+
vertical-align: middle !important;
235+
border-bottom: 1px solid #E9ECEF !important;
236+
}
237+
}
238+
}
239+
}
240+
</style>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import CasesRetentionLogs from "./components/CasesRetentionLogs.vue";
2+
3+
// Use window.Vue from bootstrap (has vuetable, i18n, etc.)
4+
// eslint-disable-next-line no-unused-vars -- Vue app mounted for side effect
5+
const casesRetentionApp = new window.Vue({
6+
el: "#casesRetentionIndex",
7+
components: { CasesRetentionLogs },
8+
data() {
9+
return {
10+
filter: "",
11+
};
12+
},
13+
methods: {
14+
downloadRetentionLogs() {
15+
console.log("downloadRetentionLogs");
16+
},
17+
reload() {
18+
this.$refs.casesRetentionLogs.reload();
19+
},
20+
},
21+
});

resources/views/admin/cases-retention/index.blade.php

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,76 @@
1616
@endsection
1717
@section('content')
1818
<div class="px-3" id="cases-retention">
19-
<cases-retention-logs></cases-retention-logs>
19+
20+
</div>
21+
22+
<div class="page-content px-3 mb-0" id="casesRetentionIndex">
23+
<div class="card p-3 cases-retention-container">
24+
<h5 class="mb-3">{{ __('Cases Retention Logs') }}</h5>
25+
<div id="search-bar" class="search mb-3" vcloak>
26+
<div class="d-flex flex-column flex-md-row">
27+
<div class="flex-grow-1 d-flex">
28+
<div id="search" class="mb-3 mb-md-0 w-100 mr-3">
29+
<div class="input-group w-100">
30+
<div class="input-group-prepend d-flex align-items-center pl-3 pr-1 search">
31+
<i class="fas fa-search"></i>
32+
</div>
33+
<input
34+
id="search-box"
35+
v-model="filter"
36+
class="form-control search-box"
37+
placeholder="{{__('Search here')}}"
38+
aria-label="{{__('Search here')}}"
39+
data-test="input-search">
40+
</div>
41+
</div>
42+
<button
43+
class="btn btn-primary download-retention-logs text-nowrap"
44+
@click="downloadRetentionLogs"
45+
data-test="download-retention-logs-button">
46+
<i class="fas fa-download mr-1 mt-1" style="font-size: 14px;"></i>
47+
<span >{{ __('Download Logs') }}</span>
48+
</button>
49+
</div>
50+
</div>
51+
</div>
52+
<cases-retention-logs
53+
ref="casesRetentionLogs"
54+
:filter="filter"
55+
v-on:reload="reload">
56+
</cases-retention-logs>
57+
</div>
58+
2059
</div>
2160
@endsection
2261

2362

2463
@section('js')
2564
<script src="{{mix('js/admin/cases-retention/index.js')}}"></script>
2665
@endsection
66+
67+
@section('css')
68+
<style>
69+
.cases-retention-container {
70+
border-radius: 8px;
71+
box-shadow: 0 0 9px 3px rgba(0, 0, 0, 0.04);
72+
border-color: #D7DDE5
73+
}
74+
.search input{
75+
border-radius: 8px;
76+
box-shadow: 0 3px 6px -3px rgba(0, 0, 0, 0.05);
77+
border-color: #d7dde5;
78+
border-left: 0;
79+
}
80+
.btn.download-retention-logs {
81+
text-transform: none;
82+
border-radius: 8px;
83+
}
84+
.input-group-prepend.search {
85+
border: 1px solid #d7dde5;
86+
border-radius: 8px 0 0 8px;
87+
border-right: 0;
88+
color: #596372;
89+
}
90+
</style>
91+
@endsection

routes/web.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
});
8181

8282
// Cases Retention
83-
Route::get('cases-retention', [CasesRetentionController::class, 'index'])->where(['router' => '.*'])->name('cases-retention.index');
83+
Route::get('cases-retention', [CasesRetentionController::class, 'index'])->name('cases-retention.index');
8484

8585
// temporary, should be removed
8686
Route::get('security-logs/download/all', [ProcessMaker\Http\Controllers\Api\SecurityLogController::class, 'downloadForAllUsers'])->middleware('can:view-security-logs');

0 commit comments

Comments
 (0)