1+
2+ import { LitElement , html , css } from 'lit' ;
3+ import { columnBodyRenderer } from '@vaadin/grid/lit.js' ;
4+ import { until } from 'lit/directives/until.js' ;
5+ import { notifier } from 'notifier' ;
6+ import { JsonRpc } from 'jsonrpc' ;
7+ import '@vaadin/grid' ;
8+ import '@vaadin/text-field' ;
9+
10+ /**
11+ * This component shows the scheduled methods.
12+ */
13+ export class QwcSchedulerScheduledMethods extends LitElement {
14+
15+ jsonRpc = new JsonRpc ( "Scheduler" ) ;
16+
17+ static styles = css `
18+ :host {
19+ display: flex;
20+ flex-direction: column;
21+ gap: 10px;
22+ }
23+
24+ .schedules-table {
25+ padding-bottom: 10px;
26+ }
27+
28+ code {
29+ font-size: 85%;
30+ }
31+
32+ .annotation {
33+ color: var(--lumo-contrast-50pct);
34+ }
35+ vaadin-button {
36+ cursor:pointer;
37+ }
38+
39+ .topBar {
40+ display: flex;
41+ justify-content: space-between;
42+ }
43+ .searchField {
44+ width: 30%;
45+ padding-left: 20px;
46+ }
47+ .scheduler {
48+ padding-right: 20px;
49+ }
50+
51+ ` ;
52+
53+ static properties = {
54+ _scheduledMethods : { state : true } ,
55+ _filteredScheduledMethods : { state : true } ,
56+ _schedulerRunning : { state : true }
57+ } ;
58+
59+ connectedCallback ( ) {
60+ super . connectedCallback ( ) ;
61+ this . jsonRpc . getScheduledMethods ( )
62+ . then ( jsonResponse => {
63+ this . _scheduledMethods = jsonResponse . result ;
64+ this . _filteredScheduledMethods = this . _scheduledMethods ;
65+ } )
66+ . then ( ( ) => {
67+ this . _runningStatusStream = this . jsonRpc . streamRunningStatus ( ) . onNext ( jsonResponse => {
68+ this . _schedulerRunning = jsonResponse . result [ "q_scheduler" ] ;
69+ this . _scheduledMethods = this . _scheduledMethods . map ( scheduledMethod => {
70+ scheduledMethod . schedules . forEach ( schedule => {
71+ if ( schedule . identity ) {
72+ schedule . running = jsonResponse . result [ schedule . identity ] ;
73+ }
74+ } ) ;
75+ return scheduledMethod ;
76+ } ) ;
77+ this . _filteredScheduledMethods = this . _scheduledMethods ;
78+ }
79+ ) } ) ;
80+ }
81+
82+ disconnectedCallback ( ) {
83+ super . disconnectedCallback ( ) ;
84+ this . _runningStatusStream . cancel ( ) ;
85+ }
86+
87+ render ( ) {
88+ return html `${ until ( this . _renderScheduledMethods ( ) , html `< span > Loading scheduled methods...</ span > ` ) } ` ;
89+ }
90+
91+ _renderScheduledMethods ( ) {
92+ if ( this . _scheduledMethods ) {
93+ let schedulerButton ;
94+ if ( this . _schedulerRunning ) {
95+ schedulerButton = html `< vaadin-button class ="scheduler " theme ="tertiary " @click =${ ( ) => this . _pauseScheduler ( ) } >
96+ < vaadin-icon icon ="font-awesome-solid:circle-pause "> </ vaadin-icon >
97+ Pause scheduler</ vaadin-button > ` ;
98+ } else {
99+ schedulerButton = html `< vaadin-button class ="scheduler " theme ="tertiary " @click =${ ( ) => this . _resumeScheduler ( ) } >
100+ < vaadin-icon icon ="font-awesome-solid:circle-play "> </ vaadin-icon >
101+ Resume scheduler</ vaadin-button > ` ;
102+ }
103+
104+ const searchBox = html `
105+ < vaadin-text-field class ="searchField "
106+ placeholder ="Search "
107+ @value-changed ="${ e => {
108+ const searchTerm = ( e . detail . value || '' ) . trim ( ) . toLowerCase ( ) ;
109+ this . _filteredScheduledMethods = this . _scheduledMethods . filter ( method => this . _matchesTerm ( method , searchTerm ) ) ;
110+ } } "
111+ >
112+ < vaadin-icon slot ="prefix " icon ="font-awesome-solid:magnifying-glass "> </ vaadin-icon >
113+ </ vaadin-text-field >
114+ `
115+
116+ return html `
117+ < div class ="topBar ">
118+ ${ searchBox }
119+ ${ schedulerButton }
120+ </ div >
121+ < vaadin-grid .items ="${ this . _filteredScheduledMethods } " class ="schedules-table " theme ="no-border ">
122+ < vaadin-grid-column auto-width
123+ header ="Scheduled Method "
124+ ${ columnBodyRenderer ( this . _methodRenderer , [ ] ) }
125+ resizable >
126+ </ vaadin-grid-column >
127+ < vaadin-grid-column auto-width
128+ header ="Triggers "
129+ ${ columnBodyRenderer ( this . _scheduleRenderer , [ ] ) }
130+ resizable >
131+ </ vaadin-grid-column >
132+ </ vaadin-grid >
133+ ` ;
134+ }
135+ }
136+
137+ _scheduleRenderer ( scheduledMethod ) {
138+ if ( scheduledMethod . schedules . length > 1 ) {
139+ const triggers = scheduledMethod . schedules . map ( s => this . _trigger ( s ) ) ;
140+ return html `< ul >
141+ ${ triggers . map ( trigger =>
142+ html `< li > ${ trigger } </ li > `
143+ ) } </ ul > `;
144+ } else {
145+ return this . _trigger ( scheduledMethod . schedules [ 0 ] ) ;
146+ }
147+ }
148+
149+ _trigger ( schedule ) {
150+ let trigger ;
151+ if ( schedule . identity ) {
152+ if ( schedule . running ) {
153+ trigger = html `< vaadin-button theme ="small " @click =${ ( ) => this . _pauseJob ( schedule . identity ) } >
154+ < vaadin-icon icon ="font-awesome-solid:circle-pause "> </ vaadin-icon >
155+ Pause</ vaadin-button > ` ;
156+ } else {
157+ trigger = html `< vaadin-button theme ="small " @click =${ ( ) => this . _resumeJob ( schedule . identity ) } >
158+ < vaadin-icon icon ="font-awesome-solid:circle-play "> </ vaadin-icon >
159+ Resume</ vaadin-button > ` ;
160+ }
161+ }
162+ if ( schedule . cron ) {
163+ trigger = schedule . cronConfig ? html `${ trigger } < code > ${ schedule . cron } </ code > configured as < code > ${ schedule . cronConfig } </ code > ` : html `${ trigger } < code > ${ schedule . cron } </ code > ` ;
164+ } else {
165+ trigger = schedule . everyConfig ? html `${ trigger } Every < code > ${ schedule . every } </ code > configured as < code > ${ schedule . everyConfig } </ code > ` : html `${ trigger } Every < code > ${ schedule . every } </ code > ` ;
166+ }
167+ if ( schedule . identity ) {
168+ trigger = schedule . identityConfig ? html `${ trigger } with identity < code > ${ schedule . identity } </ code > configured as < code > ${ scheduledMethod . identityConfig } </ code > ` : html `${ trigger } with identity < code > ${ schedule . identity } </ code > ` ;
169+ }
170+ if ( schedule . delayed > 0 ) {
171+ trigger = html `${ trigger } (with delay ${ schedule . delayed } ${ schedule . delayedUnit } )` ;
172+ } else if ( schedule . delayed ) {
173+ trigger = schedule . delayedConfig ? html `${ trigger } (delayed for < code > ${ schedule . delayed } </ code > configured as < code > ${ schedule . delayedConfig } </ code > )` : html `${ trigger } (delayed for < code > ${ schedule . delayed } </ code > )` ;
174+ }
175+ return trigger ;
176+ }
177+
178+ _methodRenderer ( scheduledMethod ) {
179+ return html `
180+ < vaadin-button theme ="small " @click =${ ( ) => this . _executeMethod ( scheduledMethod . methodDescription ) } >
181+ < vaadin-icon icon ="font-awesome-solid:bolt "> </ vaadin-icon >
182+ Execute
183+ </ vaadin-button >
184+ < code > ${ scheduledMethod . declaringClassName } .${ scheduledMethod . methodName } ()</ code >
185+ ` ;
186+ }
187+
188+ _pauseJob ( identity ) {
189+ this . jsonRpc . pauseJob ( { "identity" : identity } ) . then ( jsonResponse => {
190+ if ( jsonResponse . result . success ) {
191+ this . _updateIdentityStatus ( identity , false ) ;
192+ notifier . showSuccessMessage ( jsonResponse . result . message ) ;
193+ } else {
194+ notifier . showErrorMessage ( jsonResponse . result . message ) ;
195+ }
196+ } ) ;
197+ }
198+
199+ _resumeJob ( identity ) {
200+ this . jsonRpc . resumeJob ( { "identity" : identity } ) . then ( jsonResponse => {
201+ if ( jsonResponse . result . success ) {
202+ this . _updateIdentityStatus ( identity , true ) ;
203+ notifier . showSuccessMessage ( jsonResponse . result . message ) ;
204+ } else {
205+ notifier . showErrorMessage ( jsonResponse . result . message , "bottom-stretch" ) ;
206+ }
207+ } ) ;
208+ }
209+
210+ _pauseScheduler ( ) {
211+ this . jsonRpc . pauseScheduler ( ) . then ( jsonResponse => {
212+ if ( jsonResponse . result . success ) {
213+ this . _schedulerRunning = false ;
214+ notifier . showSuccessMessage ( jsonResponse . result . message ) ;
215+ } else {
216+ notifier . showErrorMessage ( jsonResponse . result . message ) ;
217+ }
218+ } ) ;
219+ }
220+
221+ _resumeScheduler ( ) {
222+ this . jsonRpc . resumeScheduler ( ) . then ( jsonResponse => {
223+ if ( jsonResponse . result . success ) {
224+ this . _schedulerRunning = true ;
225+ notifier . showSuccessMessage ( jsonResponse . result . message ) ;
226+ } else {
227+ notifier . showErrorMessage ( jsonResponse . result . message ) ;
228+ }
229+ } ) ;
230+ }
231+
232+ _executeMethod ( methodDescription ) {
233+ this . jsonRpc . executeJob ( { "methodDescription" : methodDescription } ) . then ( jsonResponse => {
234+ if ( jsonResponse . result . success ) {
235+ notifier . showSuccessMessage ( jsonResponse . result . message ) ;
236+ } else {
237+ notifier . showErrorMessage ( jsonResponse . result . message ) ;
238+ }
239+ } ) ;
240+ }
241+
242+ _updateIdentityStatus ( identity , running ) {
243+ this . _filteredScheduledMethods = this . _filteredScheduledMethods . map ( scheduledMethod => {
244+ scheduledMethod . schedules . forEach ( schedule => {
245+ if ( schedule . identity === identity ) {
246+ schedule . running = running ;
247+ }
248+ } ) ;
249+ return scheduledMethod ;
250+ } ) ;
251+ }
252+
253+ _matchesTerm ( scheduledMethod , searchTerm ) {
254+ if ( ! searchTerm
255+ || scheduledMethod . declaringClassName . toLowerCase ( ) . includes ( searchTerm )
256+ || scheduledMethod . methodName . toLowerCase ( ) . includes ( searchTerm ) ) {
257+ return true ;
258+ }
259+ // schedules
260+ return scheduledMethod . schedules . filter ( s => {
261+ return s . identity && s . identity . toLowerCase ( ) . includes ( searchTerm ) ||
262+ s . identityConfig && s . identityConfig . toLowerCase ( ) . includes ( searchTerm ) ||
263+ s . cron && s . cron . toLowerCase ( ) . includes ( searchTerm ) ||
264+ s . cronConfig && s . cronConfig . toLowerCase ( ) . includes ( searchTerm ) ||
265+ s . every && s . every . toLowerCase ( ) . includes ( searchTerm ) ||
266+ s . everyConfig && s . everyConfig . toLowerCase ( ) . includes ( searchTerm )
267+ } ) . length > 0 ;
268+ }
269+
270+ }
271+ customElements . define ( 'qwc-scheduler-scheduled-methods' , QwcSchedulerScheduledMethods ) ;
0 commit comments