11<script >
2+ import moment from " moment" ;
3+ import _ from " lodash" ;
4+ import { SlickGrid } from " slickgrid" ;
5+ import Icon from " ../../../common/svelte/Icon.svelte" ;
26 import SubSection from " ../../../common/svelte/SubSection.svelte" ;
37 import NoData from " ../../../common/svelte/NoData.svelte" ;
4- import {createEventDispatcher } from " svelte" ;
8+ import { createEventDispatcher } from " svelte" ;
59 import MiniActions from " ../../../common/svelte/MiniActions.svelte" ;
610 import DateTime from " ../../../common/svelte/DateTime.svelte" ;
7- import _ from " lodash" ;
11+ import { mkSortFn } from " ../../../common/slick-grid-utils" ;
12+ import SearchInput from " ../../../common/svelte/SearchInput.svelte" ;
13+ import { termSearch } from " ../../../common" ;
14+ import { compareDates } from " ../../../common/sort-utils" ;
15+ import { severity } from " ../../../common/services/enums/severity" ;
816
917 export let measurableCategory;
1018 export let isAttestable = false ;
1119 export let latestAttestation = null ;
20+ export let unAttestedChanges = [];
21+ let grid;
22+ let viewData = [];
23+ let elem = null ;
24+ let searchStr = " " ;
25+ let showingUnAttestedChanges = false ;
1226
1327 const dispatcher = createEventDispatcher ();
1428
1529 const attestMiniAction = {
1630 name: " Attest Now" ,
1731 icon: " check" ,
1832 description: " Initiate Attestation" ,
19- handleAction : ctx => dispatcher (" attestationInitiated" , ctx)
33+ handleAction : (ctx ) => dispatcher (" attestationInitiated" , ctx),
34+ };
35+
36+ const options = {
37+ enableCellNavigation: false ,
38+ enableColumnReorder: false ,
2039 };
2140
22- $: actions = _ .compact ([
23- isAttestable ? attestMiniAction : null
24- ]);
41+ function initGrid (elem ) {
42+ grid = new SlickGrid (elem, [], columnDefs, options);
43+ grid .onSort .subscribe ((e , args ) => {
44+ const sortCol = args .sortCol ;
45+ grid .data .sort (mkSortFn (sortCol, args .sortAsc ));
46+ grid .invalidate ();
47+ });
48+ }
49+
50+ function mkGridData (data ) {
51+ return data;
52+ }
53+
54+ function doGridSearch (data = [], searchStr ) {
55+ return termSearch (data, searchStr, [
56+ " severity" ,
57+ " message" ,
58+ " userId" ,
59+ " createdAt" ,
60+ ]);
61+ }
62+
63+ $: actions = _ .compact ([isAttestable ? attestMiniAction : null ]);
64+
65+ $: hasEverBeenAttested = ! _ .isNil (_ .get (latestAttestation, " attestedBy" ));
66+
67+ $: columnDefs = [
68+ {
69+ id: " severity" ,
70+ field: " severity" ,
71+ name: " Severity" ,
72+ width: 50 ,
73+ sortable: true ,
74+ formatter : (row , cell , value ) => {
75+ return value
76+ ? ` <span title="${ value} ">${ severity[value].name } </span>`
77+ : " " ;
78+ },
79+ },
80+ {
81+ id: " message" ,
82+ field: " message" ,
83+ name: " Message" ,
84+ width: 200 ,
85+ formatter : (row , cell , value ) => {
86+ return ` <span title="${ value} ">${ value} </span>` ;
87+ },
88+ },
89+ {
90+ id: " userId" ,
91+ field: " userId" ,
92+ name: " User" ,
93+ width: 100 ,
94+ formatter : (row , cell , value ) => {
95+ return ` <span title="${ value} ">${ value} </span>` ;
96+ },
97+ },
98+ {
99+ id: " createdAt" ,
100+ field: " createdAt" ,
101+ name: " Timestamp" ,
102+ width: 50 ,
103+ sortable: true ,
104+ formatter : (row , cell , value ) => {
105+ if (value) {
106+ const formatStr = " YYYY-MM-DD HH:mm:ss" ;
107+ const format = (t ) =>
108+ moment .utc (t).local ().format (formatStr);
109+
110+ return ` <span>${ format (value)} </span>` ;
111+ }
112+ return " " ;
113+ },
114+ sortFn : (a , b ) => compareDates (a? .createdAt , b? .createdAt ),
115+ },
116+ ];
117+ $: {
118+ if (unAttestedChanges .length ) {
119+ viewData = mkGridData (unAttestedChanges);
120+ }
121+
122+ if (elem && ! _ .isEmpty (viewData)) {
123+ initGrid (elem);
124+ }
125+ }
25126
26- $: hasEverBeenAttested = ! _ .isNil (_ .get (latestAttestation, " attestedBy" ))
127+ $: {
128+ const data = doGridSearch (viewData, searchStr);
129+ if (grid) {
130+ grid .data = data;
131+ grid .invalidate ();
132+ }
133+ }
27134< / script>
28135
29136{#if measurableCategory}
33140 < / div>
34141 < div slot= " content" >
35142 {#if hasEverBeenAttested}
36-
37143 < table class = " table waltz-field-table waltz-field-table-border" >
38144 < tr>
39145 < td class = " wft-label" > Attested By: < / td>
42148 < tr>
43149 < td class = " wft-label" > Attested At: < / td>
44150 < td>
45- <DateTime dateTime ={latestAttestation .attestedAt }/>
151+ < DateTime dateTime= {latestAttestation .attestedAt } / >
46152 < / td>
47153 < / tr>
48154 < / table>
49-
50155 {: else }
51-
52156 < NoData type= " warning" >
53157 Never attested.
54158 {#if isAttestable}
55- <button class =" btn-link"
56- on:click ={() => attestMiniAction .handleAction (measurableCategory )}>
159+ < button
160+ class = " btn-link"
161+ on: click= {() =>
162+ attestMiniAction .handleAction (
163+ measurableCategory,
164+ )}
165+ >
57166 Attest now
58167 < / button>
59168 {/ if }
60169 < / NoData>
61-
62170 {/ if }
63171 < / div>
64172
65173 < div slot= " controls" >
66174 < div style= " float:right" class = " small" >
67175 {#if isAttestable}
68- <MiniActions actions = {actions } ctx ={measurableCategory }/>
176+ < MiniActions {actions} ctx= {measurableCategory} / >
69177 {/ if }
70178 < / div>
71179 < / div>
72-
180+ < div slot= " changes" >
181+ {#if ! _ .isEmpty (viewData)}
182+ < NoData type= {" warning" }>
183+ {#if showingUnAttestedChanges}
184+ < SearchInput bind: value= {searchStr} / >
185+ < div
186+ class = " slick-container"
187+ style= " width:100%;height:250px;"
188+ bind: this = {elem}
189+ >< / div>
190+ {: else }
191+ < Icon
192+ name= " exclamation-triangle"
193+ size= " 2x"
194+ / >
195+ Unattested changes detected
196+ < button
197+ class = " btn-link"
198+ on: click= {() => (showingUnAttestedChanges = true )}
199+ >
200+ Show the < span> {unAttestedChanges .length }< / span> unattested
201+ change/ s.
202+ < / button>
203+ {/ if }
204+ < / NoData>
205+ {: else }
206+ < NoData> No attestation changes< / NoData>
207+ {/ if }
208+ < / div>
73209 < / SubSection>
74- {/if }
210+ {/ if }
0 commit comments