55 * - webexpress.webui.Event.COLUMN_REORDER_EVENT
66 */
77webexpress . webapp . TableCtrl = class extends webexpress . webui . TableCtrl {
8+ // Helper to create DOM elements with class list
9+ _createElement ( tag , classList = [ ] ) {
10+ const el = document . createElement ( tag ) ;
11+ classList . forEach ( cls => el . classList . add ( cls ) ) ;
12+ return el ;
13+ }
14+
15+ // Helper to create the progress bar
16+ _createProgressDiv ( ) {
17+ const div = this . _createElement ( "div" , [ "progress" ] ) ;
18+ div . setAttribute ( "role" , "status" ) ;
19+ div . style . height = "0.5em" ;
20+ const bar = this . _createElement ( "div" , [
21+ "progress-bar" ,
22+ "progress-bar-striped" ,
23+ "progress-bar-animated" ,
24+ ] ) ;
25+ bar . style . width = "100%" ;
26+ div . appendChild ( bar ) ;
27+ return div ;
28+ }
29+
30+ // Fields
831 _restUri = "" ;
9- _titleDiv = $ ( "<h3>" ) . addClass ( "me-auto" ) ;
10- _progressDiv = $ ( "<div role='status' style='height: 0.5em'>" )
11- . addClass ( "progress" )
12- . append ( $ ( "<div class='progress-bar progress-bar-striped progress-bar-animated' style='width: 100%'>" ) ) ;
13- _filterDiv = $ ( "<div class='col-3'>" ) ;
32+ _titleDiv = this . _createElement ( "h3" , [ "me-auto" ] ) ;
33+ _progressDiv = this . _createProgressDiv ( ) ;
34+ _filterDiv = this . _createElement ( "div" , [ "col-3" ] ) ;
1435 _filterCtrl = null ;
15- _statusDiv = $ ( "< span> ") ;
16- _paginationDiv = $ ( "< div class=' justify-content-end'>" ) ;
36+ _statusDiv = this . _createElement ( " span") ;
37+ _paginationDiv = this . _createElement ( " div" , [ " justify-content-end" ] ) ;
1738 _paginationCtrl = null ;
1839 _filter = null ;
1940 _page = 0 ;
20- _previewColumns = [
21- { label : "<span class='placeholder col-6 placeholder-lg'></span>" } ,
22- { label : "<span class='placeholder col-6 placeholder-lg'></span>" } ,
23- { label : "<span class='placeholder col-6 placeholder-lg'></span>" } ] ;
41+ _hasOptions = false ;
42+ _columns = [ ] ;
43+ _rows = [ ] ;
44+ _options = [ ] ;
45+
46+ // Placeholder columns and rows for loading state
47+ _previewColumns = [
48+ { label : "<span class='placeholder col-6 placeholder-lg'></span>" } ,
49+ { label : "<span class='placeholder col-6 placeholder-lg'></span>" } ,
50+ { label : "<span class='placeholder col-6 placeholder-lg'></span>" }
51+ ] ;
2452 _previewBody = [
25- { cells : [ { text : "<span class='placeholder col-7'></span>" } , { text : "<span class='placeholder col-5'></span>" } , { text : "<span class='placeholder col-6'></span>" } ] } ,
26- { cells : [ { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-7'></span>" } , { text : "<span class='placeholder col-5'></span>" } ] } ,
27- { cells : [ { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-7'></span>" } ] } ] ;
53+ { cells : [ { text : "<span class='placeholder col-7'></span>" } , { text : "<span class='placeholder col-5'></span>" } , { text : "<span class='placeholder col-6'></span>" } ] } ,
54+ { cells : [ { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-7'></span>" } , { text : "<span class='placeholder col-5'></span>" } ] } ,
55+ { cells : [ { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-6'></span>" } , { text : "<span class='placeholder col-7'></span>" } ] }
56+ ] ;
2857
2958 /**
30- * Constructor
31- * @param {HTMLElement } element - The DOM element associated with the modal control.
59+ * Constructor for the TableCtrl class.
60+ * @param {HTMLElement } element - The DOM element associated with the control.
3261 */
3362 constructor ( element ) {
3463 super ( element ) ;
3564
36- this . _restUri = $ ( element ) . data ( "uri" ) ?? "" ; // Retrieve the URI for loading content
37-
38- // Cleanup the DOM element
39- $ ( this . _element )
40- . removeAttr ( "data-uri" ) ;
65+ // Get REST URI from data attribute or fallback to empty string
66+ this . _restUri = element . dataset . uri || "" ;
67+
68+ // Remove REST URI attribute from DOM for security/cleanliness
69+ element . removeAttribute ( "data-uri" ) ;
70+
71+ // Build the toolbar (title and filter)
72+ const toolbar = this . _createElement ( "div" , [ "wx-table-toolbar" ] ) ;
73+ toolbar . appendChild ( this . _titleDiv ) ;
74+ toolbar . appendChild ( this . _filterDiv ) ;
75+
76+ // Insert toolbar and progress bar at the top of the element
77+ element . prepend ( toolbar , this . _progressDiv ) ;
78+
79+ // Build the status bar (status and pagination)
80+ const statusbar = this . _createElement ( "div" , [ "wx-table-statusbar" ] ) ;
81+ statusbar . appendChild ( this . _statusDiv ) ;
82+ statusbar . appendChild ( this . _paginationDiv ) ;
4183
42- // Show placeholder while loading content
43- $ ( this . _element ) . prepend ( $ ( "<div>" ) . addClass ( "wx-table-toolbar" ) . append ( this . _titleDiv , this . _filterDiv ) , this . _progressDiv ) ;
44- $ ( this . _element ) . append ( $ ( "<div>" ) . addClass ( "wx-table-statusbar" ) . append ( this . _statusDiv , this . _paginationDiv ) ) ;
45-
84+ // Append status bar at the bottom of the element
85+ element . appendChild ( statusbar ) ;
86+
87+ // Show placeholder columns and rows while loading
4688 this . _columns = this . _previewColumns ;
4789 this . _rows = this . _previewBody ;
48-
49- this . _table . addClass ( "placeholder-glow" ) ;
50-
90+ this . _table . classList . add ( "placeholder-glow" ) ;
5191 this . render ( ) ;
52-
53- this . _filterCtrl = new webexpress . webui . SearchCtrl ( this . _filterDiv [ 0 ] ) ;
54- $ ( document ) . on ( webexpress . webui . Event . CHANGE_FILTER_EVENT , ( event , data ) => {
55- if ( data . sender && data . sender === this . _filterDiv [ 0 ] ) {
92+
93+ // Initialize filter control
94+ this . _filterCtrl = new webexpress . webui . SearchCtrl ( this . _filterDiv ) ;
95+
96+ // Listen for filter changes
97+ document . addEventListener ( webexpress . webui . Event . CHANGE_FILTER_EVENT , ( event ) => {
98+ const data = event . detail || { } ;
99+ if ( data . sender && data . sender === this . _filterDiv ) {
56100 this . _filter = data . value ;
57101 this . _receiveData ( ) ;
58102 }
59103 } ) ;
60-
61- this . _paginationCtrl = new webexpress . webui . PaginationCtrl ( this . _paginationDiv [ 0 ] ) ;
62- $ ( document ) . on ( webexpress . webui . Event . CHANGE_PAGE_EVENT , ( event , data ) => {
63- if ( data . sender && data . sender === this . _paginationDiv [ 0 ] ) {
104+
105+ // Initialize pagination control
106+ this . _paginationCtrl = new webexpress . webui . PaginationCtrl ( this . _paginationDiv ) ;
107+
108+ // Listen for pagination changes
109+ document . addEventListener ( webexpress . webui . Event . CHANGE_PAGE_EVENT , ( event ) => {
110+ const data = event . detail || { } ;
111+ if ( data . sender && data . sender === this . _paginationDiv ) {
64112 this . _page = data . page ;
65113 this . _receiveData ( ) ;
66-
67- // scroll to the top of the table
68- window . scrollTo ( 0 , $ ( this . _element ) . offset ( ) . top ) ;
114+ // Scroll to top of the table
115+ window . scrollTo ( 0 , element . offsetTop ) ;
69116 }
70117 } ) ;
71-
118+
119+ // Initial data load
72120 this . _receiveData ( ) ;
73121 }
74122
75123 /**
76- * Retrieve data from rest api .
124+ * Retrieve data from REST API and update the table .
77125 */
78126 _receiveData ( ) {
79- this . _progressDiv . css ( "visibility" , "visible" ) ;
80-
81- $ . get ( `${ this . _restUri } ?filter=${ this . _filter } &page=${ this . _page } ` )
82- . done ( ( response ) => {
83-
84- const page = response . page ?? 0 ; // current page number
85- const pageSize = response . pageSize ?? 50 ; // number of items per page
86- const total = response . total ?? 0 ; // total number of items
87- const totalPages = Math . ceil ( total / pageSize ) ; // calculate the total number of pages
88- const startIndex = page * pageSize + 1 ; // calculate the index of the first item on the current page
89- const endIndex = Math . min ( startIndex + pageSize - 1 , total ) ; // calculate the index of the last item on the current page
127+ this . _progressDiv . style . visibility = "visible" ;
128+
129+ const filter = encodeURIComponent ( this . _filter ?? "" ) ;
130+ const url = `${ this . _restUri } ?filter=${ filter } &page=${ this . _page } ` ;
131+
132+ fetch ( url )
133+ . then ( res => {
134+ if ( ! res . ok ) throw new Error ( "Request failed" ) ;
135+ return res . json ( ) ;
136+ } )
137+ . then ( response => {
138+ // Extract paging and data info with fallback defaults
139+ const page = response . page ?? 0 ;
140+ const pageSize = response . pageSize ?? 50 ;
141+ const total = response . total ?? 0 ;
142+ const totalPages = Math . ceil ( total / pageSize ) ;
143+ const startIndex = page * pageSize + 1 ;
144+ const endIndex = Math . min ( startIndex + pageSize - 1 , total ) ;
90145
91146 this . _columns = response . columns ;
92- this . _titleDiv . text ( response . title ) ;
93- this . _statusDiv . text ( `${ startIndex } - ${ endIndex } / ${ total } ` ) ;
94-
95- // Trigger event when data has successfully arrived
96- $ ( this . _element ) . trigger ( webexpress . webui . Event . DATA_ARRIVED_EVENT , {
97- id : $ ( this . _element ) . attr ( "id" ) ,
98- response : response
147+ this . _titleDiv . textContent = response . title ;
148+ this . _statusDiv . textContent = `${ startIndex } - ${ endIndex } / ${ total } ` ;
149+
150+ // Fire event for data arrival
151+ const evt = new CustomEvent ( webexpress . webui . Event . DATA_ARRIVED_EVENT , {
152+ detail : {
153+ id : this . _element . id ,
154+ response : response
155+ }
99156 } ) ;
157+ this . _element . dispatchEvent ( evt ) ;
158+
159+ // Update pagination control
100160 this . _paginationCtrl . total = totalPages ;
101161 this . _paginationCtrl . page = page ;
102-
103- this . _table . removeClass ( "placeholder-glow" ) ;
104162
105- // Bind actions to existing commands
163+ this . _table . classList . remove ( "placeholder-glow" ) ;
164+
165+ // Bind edit/delete actions to each row, if applicable
106166 this . _rows = response . rows . map ( row => {
107167 if ( Array . isArray ( row . options ) ) {
108168 this . _hasOptions = true ;
109169 row . options . forEach ( option => {
170+ if ( option . command === "edit" ) {
171+ option . action = ( ) => this . _editRow ( row . id , option . uri ) ;
172+ }
110173 if ( option . command === "delete" ) {
111- option . action = ( ) => this . _deleteRow . call ( this , row . id ) ;
174+ option . action = ( ) => this . _deleteRow ( row . id ) ;
112175 }
113176 } ) ;
114177 }
@@ -118,18 +181,41 @@ webexpress.webapp.TableCtrl = class extends webexpress.webui.TableCtrl {
118181 if ( this . _options ?. length > 0 ) {
119182 this . _hasOptions = true ;
120183 }
121-
184+
122185 this . render ( ) ;
123-
124- this . _progressDiv . css ( "visibility" , "hidden" ) ;
186+ this . _progressDiv . style . visibility = "hidden" ;
125187 } )
126- . fail ( ( error ) => {
188+ . catch ( error => {
189+ // Log any errors in retrieving data
127190 console . error ( "The request could not be completed successfully:" , error ) ;
128191 } ) ;
129192 }
130193
131194 /**
132- * Function to delete a row from the table and send a DELETE request to the REST API.
195+ * Edit a row and send a PUT request to the REST API.
196+ * @param {number } rowId - The ID of the row to be edited.
197+ * @param {string } uri - The uri for the form to be used for editing.
198+ */
199+ _editRow ( rowId , uri ) {
200+ const editModal = new webexpress . webapp . ModalFormCtrl ( ) ;
201+ editModal . _uri = uri ;
202+ editModal . _selector = uri ?. includes ( "#" ) ? "#" + uri . split ( "#" ) [ 1 ] : "form" ;
203+
204+ // Bind form submission logic
205+ editModal . _form . addEventListener ( "submit" , ( event ) => {
206+ fetch ( `${ this . _restUri } ?id=${ rowId } ` , { method : "PUT" } )
207+ . then ( response => {
208+ if ( ! response . ok ) throw new Error ( "Failed to edit row" ) ;
209+ this . _receiveData ( ) ;
210+ } )
211+ . catch ( error => console . error ( `Failed to edit row with ID ${ rowId } .` , error ) ) ;
212+ } ) ;
213+
214+ editModal . show ( ) ;
215+ }
216+
217+ /**
218+ * Delete a row and send a DELETE request to the REST API.
133219 * @param {number } rowId - The ID of the row to be deleted.
134220 */
135221 _deleteRow ( rowId ) {
@@ -139,7 +225,6 @@ webexpress.webapp.TableCtrl = class extends webexpress.webui.TableCtrl {
139225 fetch ( `${ this . _restUri } ?id=${ rowId } ` , { method : "DELETE" } )
140226 . then ( response => {
141227 if ( ! response . ok ) throw new Error ( "Failed to delete row" ) ;
142-
143228 this . _receiveData ( ) ;
144229 } )
145230 . catch ( error => console . error ( `Failed to delete row with ID ${ rowId } .` , error ) ) ;
0 commit comments