1+ import { inject , onMounted , ref } from "vue"
2+ import { useClient , useFormatters } from "@servicestack/vue"
3+ import { QueryDb , QueryResponse } from "../dtos.mjs"
4+
5+ export class GetCrudEvents extends QueryDb
6+ {
7+ /** @param {{authSecret?:string,model?:string,modelId?:string} } [init] */
8+ constructor ( init ) { super ( init ) ; Object . assign ( this , init ) }
9+ /** @type {string } */
10+ authSecret ;
11+ /** @type {string } */
12+ model ;
13+ /** @type {string } */
14+ modelId ;
15+ getTypeName ( ) { return 'GetCrudEvents' }
16+ getMethod ( ) { return 'GET' }
17+ createResponse ( ) { return new QueryResponse ( ) }
18+ }
19+
20+ export const AuditEvents = {
21+ template :/*html*/ `
22+ <div v-if="events.length">
23+ <div class="flex justify-center">
24+ <button type="button" @click="open=!open"
25+ class="px-1 py-1.5 group text-gray-700 font-medium flex items-center" aria-expanded="false">
26+ <svg class="flex-none w-5 h-5 mr-2 text-gray-400 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
27+ <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M3 3v5h5"/><path d="M3.05 13A9 9 0 1 0 6 5.3L3 8"/><path d="M12 7v5l4 2"/></g>
28+ </svg>
29+ <span class="mr-1">
30+ {{eventsCount}} Audit {{ eventsCount === 1 ? 'Event' : 'Events' }}
31+ </span>
32+ <svg v-if="!open"
33+ class="h-5 w-5 text-gray-400 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
34+ <path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" />
35+ </svg>
36+ <svg v-else
37+ class="h-5 w-5 text-gray-400 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
38+ <path fill-rule="evenodd" d="M5 10a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1z" clip-rule="evenodd" />
39+ </svg>
40+ </button>
41+ </div>
42+ <div v-if="open" class="flex">
43+ <ul v-if="events.length" class="divide-y divide-gray-200 border-t w-full">
44+ <li v-for="x in events" :key="x.id" class="py-4 cursor-pointer" @click="toggle(x.id)">
45+ <div class="flex justify-between">
46+ <div class="pl-4 uppercase inline-block w-20">{{ x.eventType }}</div>
47+ <div>
48+ <span :title="'User ' + x.userAuthId">{{ x.userAuthName }}</span>
49+ </div>
50+ <div>
51+ <span :title="formatDate(x.eventDate)">{{ relativeTime(x.eventDate) }}</span>
52+ <div class="ml-3 inline-block w-5 align-middle">
53+ <svg v-if="!expanded(x.id)" class="h-5 w-5 flex-none text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
54+ <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
55+ </svg>
56+ </div>
57+ </div>
58+ </div>
59+ <div class="flex space-x-3">
60+ <div class="flex-1 flex flex-col">
61+ <div v-if="expanded(x.id)" class="p-4">
62+ <table>
63+ <tr>
64+ <td class="font-medium">API</td>
65+ <td>{{ x.requestType }}</td>
66+ </tr>
67+ <tr>
68+ <td class="pr-4 font-medium">User Id</td>
69+ <td>{{ x.userAuthId }}</td>
70+ </tr>
71+ <tr>
72+ <td class="pr-4 font-medium">Date</td>
73+ <td>{{ formatDate(x.eventDate) }}</td>
74+ </tr>
75+ <tr>
76+ <td class="pr-4 font-medium">IP</td>
77+ <td>{{ x.remoteIp }}</td>
78+ </tr>
79+ </table>
80+ </div>
81+ </div>
82+ <div class="flex-1">
83+ <div v-if="expanded(x.id)" class="p-4">
84+ <PreviewFormat :value="JSON.parse(x.requestBody)" />
85+ </div>
86+ </div>
87+ </div>
88+ </li>
89+ </ul>
90+ </div>
91+ </div>
92+ ` ,
93+ props :[ 'type' , 'id' ] ,
94+ setup ( props ) {
95+ const store = inject ( 'store' )
96+ const server = inject ( 'server' )
97+ const client = useClient ( )
98+
99+ const open = ref ( false )
100+ const eventsCount = ref ( 0 )
101+ const events = ref ( [ ] )
102+ const expand = ref ( { } )
103+ const { formatDate, relativeTime } = useFormatters ( )
104+ function expanded ( id ) {
105+ return ! ! expand . value [ id ]
106+ }
107+ function toggle ( id ) {
108+ expand . value [ id ] = ! expand . value [ id ]
109+ }
110+
111+ onMounted ( async ( ) => {
112+ const request = new GetCrudEvents ( {
113+ modelId : props . id ,
114+ model : props . type ,
115+ include : 'total' ,
116+ orderBy : '-Id'
117+ } )
118+ const api = await client . api ( request )
119+ eventsCount . value = 0
120+ events . value = [ ]
121+ if ( api . succeeded ) {
122+ eventsCount . value = api . response . total
123+ events . value = api . response . results
124+ }
125+ } )
126+
127+ return { open, events, eventsCount, formatDate, relativeTime, expanded, toggle }
128+ }
129+ }
130+
131+ export default AuditEvents
0 commit comments