Skip to content

Commit 53d8430

Browse files
committed
feat: improved the table control
1 parent 1cf53d2 commit 53d8430

7 files changed

Lines changed: 187 additions & 108 deletions
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.wx-table-toolbar {
2+
display: flex;
3+
justify-content: space-between;
4+
margin-bottom: 0.5rem;
5+
align-items: center;
6+
color: var(--bs-body-color);
7+
}
8+
9+
.wx-table-statusbar {
10+
display: flex;
11+
justify-content: space-between;
12+
align-items: center;
13+
margin-bottom: 0.5rem;
14+
color: var(--bs-body-color);
15+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
.taskprogressbar {
1+
.wx-taskprogressbar {
22
}
3-
.taskprogressbar > .progress {
3+
.wx-taskprogressbar > .progress {
44
margin-bottom: 1em;
55
}
Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
/**
2-
* A dopdown box with features for create, read, update, and delete.
2+
* A selection box.
3+
* The following events are triggered:
4+
* - webexpress.webui.Event.CHANGE_FILTER_EVENT
5+
* - webexpress.webui.Event.CHANGE_VALUE_EVENT
6+
* - webexpress.webui.Event.DROPDOWN_SHOW_EVENT
7+
* - webexpress.webui.Event.DROPDOWN_HIDDEN_EVENT
38
*/
4-
webexpress.webapp.selectionCtrl = class extends webexpress.webui.selectionCtrl {
9+
webexpress.webapp.SelectionCtrl = class extends webexpress.webui.SelectionCtrl {
510
_optionUri = "";
6-
_spinner = $("<div class='spinner-border spinner-border-sm text-secondary' role='status'/>");
11+
_spinner = $("<div class='spinner-border spinner-border-sm text-secondary ms-2' role='status'/>");
712

813
/**
914
* Constructor
10-
* @param settings Options for styling the control:
11-
* - id Sets the id of the control.
12-
* - css The css class used to design the control.
13-
* - placeholder The placeholder text.
14-
* - hidedescription Disabled the description.
15-
* - multiselect Allows you to select multiple items.
16-
* - optionuri The uri of the rest api interface that collects the options.
15+
* @param {HTMLElement} element - The DOM element for the selection control.
1716
*/
18-
constructor(settings) {
19-
super(settings);
17+
constructor(element) {
18+
super(element);
2019

21-
this._optionUri = settings.optionuri;
20+
this._optionUri = $(element).data("uri") ?? ""; // Retrieve the URI for loading content
2221
this._optionfilter = function (x, y) { return true; };
2322

24-
this._container.on('show.bs.dropdown', function () {
23+
$(this._element).on('show.bs.dropdown', function () {
2524
this.receiveData(this._filter.val());
2625
}.bind(this));
2726
}
@@ -35,15 +34,20 @@ webexpress.webapp.selectionCtrl = class extends webexpress.webui.selectionCtrl {
3534
filter = filter !== undefined || filter != null ? filter : "";
3635
this._selection.append(this._spinner);
3736

38-
$.ajax({ type: "GET", url: this._optionUri + "?search=" + filter + "&page=0", dataType: 'json', }).then(function (response) {
39-
var data = response.data;
37+
$.get(`${this._optionUri}?search=${filter}&page=${this._page}`)
38+
.done((response) => {
39+
this.options = response.options;
40+
this.trigger('webexpress.webui.receive.complete');
4041

41-
this.options = data;
42-
this.trigger('webexpress.webui.receive.complete');
42+
//this.update();
4343

44-
//this.update();
45-
46-
this._selection.children("div").remove();
47-
}.bind(this));
44+
this._selection.children("div").remove();
45+
})
46+
.fail((error) => {
47+
console.error("The request could not be completed successfully:", error);
48+
});
4849
}
49-
}
50+
}
51+
52+
// Register the class in the controller
53+
webexpress.webui.Controller.registerClass("wx-webapp-selection", webexpress.webapp.SelectionCtrl);
Lines changed: 91 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,110 @@
11
/**
2-
* A table with functions for create, read, update, and delete.
2+
* A rest table control extending the base Control class with column reordering functionality and visual indicators.
3+
* The following events are triggered:
4+
* - webexpress.webui.Event.TABLE_SORT_EVENT
5+
* - webexpress.webui.Event.COLUMN_REORDER_EVENT
36
*/
4-
webexpress.webapp.tableCtrl = class extends webexpress.webui.tableCtrl {
7+
webexpress.webapp.TableCtrl = class extends webexpress.webui.TableCtrl {
58
_restUri = "";
6-
_searchCtrl = null;
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'>");
14+
_filterCtrl = null;
15+
_statusDiv = $("<span>");
16+
_paginationDiv = $("<div class='justify-content-end'>");
717
_paginationCtrl = null;
818
_filter = null;
919
_page = null;
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>" }];
24+
_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>" } ] }];
1028

1129
/**
1230
* Constructor
13-
* @param settings Options for styling the control:
14-
* - id Sets the id of the control.
15-
* - css The css class used to design the control.
16-
* - placeholder The placeholder text.
17-
* - resturi The uri of the rest api interface that collects the data.
31+
* @param {HTMLElement} element - The DOM element associated with the modal control.
1832
*/
19-
constructor(settings) {
20-
super(settings);
33+
constructor(element) {
34+
super(element);
2135

22-
this._restUri = settings.resturi;
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");
2341

24-
$.ajax({ type: "GET", url: this._restUri + "?columns=true", dataType: 'json', }).then(function (response) {
25-
var columns = response.Columns;
26-
this.columns = columns;
27-
}.bind(this));
28-
29-
this._searchCtrl = new webexpress.webui.searchCtrl({ Id: settings.id + "-search" });
30-
this._searchCtrl.on('webexpress.webui.change.filter', function (key) { this._filter = key; this.receiveData(); }.bind(this));
31-
this._paginationCtrl = new webexpress.webui.paginationCtrl({ Id: settings.Id + "-pagination" });
32-
this._paginationCtrl.on('webexpress.webui.change.page', function (page) { this._page = page; this.receiveData(); }.bind(this));
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+
46+
this._columns = this._previewColumns;
47+
this._rows = this._previewBody;
48+
49+
this._table.addClass("placeholder-glow");
50+
51+
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+
this._filter = data.value;
56+
this._receiveData();
57+
});
58+
59+
this._paginationCtrl = new webexpress.webui.PaginationCtrl(this._paginationDiv[0]);
60+
//this._paginationCtrl = webexpress.webui.Controller.getInstanceByElement(this._paginationDiv);
61+
$(document).on(webexpress.webui.Event.CHANGE_PAGE_EVENT, (event, data) => {
62+
this._page = data.page;
63+
this._receiveData();
64+
});
65+
66+
this._receiveData();
3367
}
3468

3569
/**
3670
* Retrieve data from rest api.
3771
*/
38-
receiveData() {
39-
if (this._filter === undefined || this._filter == null) { this._filter = ""; }
40-
if (this._page === undefined || this._page == null) { this._page = 0; }
41-
$.ajax({ type: "GET", url: this._restUri + "?search=" + this._filter + "&page=" + this._page, dataType: 'json', }).then(function (response) {
42-
var data = response.data;
43-
this.clear();
44-
this.addRange(data);
45-
this.trigger('webexpress.webui.receive.complete');
46-
var pagination = response.pagination;
47-
this._paginationCtrl.page(pagination.pagenumber, pagination.totalpage);
48-
}.bind(this));
72+
_receiveData() {
73+
this._progressDiv.css("visibility", "visible");
74+
75+
$.get(`${this._restUri}?filter=${this._filter}&page=${this._page}`)
76+
.done((response) => {
77+
78+
this._columns = response.columns;
79+
this._rows = response.rows;
80+
this._titleDiv.text(response.title);
81+
this._statusDiv.text(`${response.page * response.pageitems} - ${(response.page * response.pagecount) + response.pagecount - 1} / ${response.total}`);
82+
83+
// Trigger event when data has successfully arrived
84+
$(this._element).trigger(webexpress.webui.Event.DATA_ARRIVED_EVENT, {
85+
id: $(this._element).attr("id"),
86+
response: response
87+
});
88+
this._paginationCtrl.pagecount = response.pagecount;
89+
this._paginationCtrl.page = response.page;
90+
91+
this._table.removeClass("placeholder-glow");
92+
93+
this._hasOptions = this._rows.some(row => row.options?.length > 0);
94+
95+
if (this._options?.length > 0) {
96+
this._hasOptions = true;
97+
}
98+
99+
this.render();
100+
101+
this._progressDiv.css("visibility", "hidden");
102+
})
103+
.fail((error) => {
104+
console.error("The request could not be completed successfully:", error);
105+
});
49106
}
107+
}
50108

51-
/**
52-
* Returns the control.
53-
*/
54-
get getCtrl() {
55-
let div = $("<div/>")
56-
div.append(this._searchCtrl.getCtrl);
57-
div.append(this._table);
58-
div.append(this._paginationCtrl.getCtrl);
59-
return div;
60-
}
61-
}
109+
// Register the class in the controller
110+
webexpress.webui.Controller.registerClass("wx-webapp-table", webexpress.webapp.TableCtrl);
Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,74 @@
11
/**
22
* Progress bar of a task (WebTask).
33
* The following events are triggered:
4-
* - webexpress.webapp.finish with parameter id.
4+
* - webexpress.webui.Event.TASK_START_EVENT
5+
* - webexpress.webui.Event.TASK_UPDATE_EVENT
6+
* - webexpress.webui.Event.TASK_FINISH_EVENT
57
*/
6-
webexpress.webapp.taskProgressBarCtrl = class extends webexpress.webui.events {
8+
webexpress.webapp.TaskProgressBarCtrl = class extends webexpress.webui.Ctrl {
9+
_interval = null;
710
_restUri = "";
8-
_container = $("<div class='taskprogressbar'/>");
9-
_progress = $("<div class='progress'><div class='progress-bar progress-bar-striped progress-bar-animated' role='progressbar' style='width: 0%' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100'></div></div>");
11+
_progress = $("<div class='progress'>").append($("<div role='progressbar' style='width: 0%' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100'>"));
1012
_message = $("<div class='text-secondary'/>");
1113
_interval = null;
1214

1315
/**
1416
* Constructor
15-
* @param settings Options for styling the control:
16-
* - id Sets the id of the control.
17-
* - resturi The uri of the rest api interface that collects the data.
18-
* - intervall The interval determines the timing of the rest api requests.
17+
* @param {HTMLElement} element - The DOM element associated with the modal control.
1918
*/
20-
constructor(settings) {
21-
super();
19+
constructor(element) {
20+
super(element);
2221

23-
let id = settings.id;
24-
let interval = settings.interval ?? 15000;
25-
this._restUri = settings.resturi;
26-
27-
this._container.attr("id", id ?? "");
22+
this._interval = $(element).data("interval") ?? 15000;
23+
this._restUri = $(element).data("uri") ?? ""; // Retrieve the URI for loading content
24+
this._size = $(element).data("size") || null;
2825

29-
this._interval = setInterval(function () {
26+
this._interval = setInterval(() => {
3027
this.receiveData();
31-
}.bind(this), interval);
28+
}, this._interval);
29+
30+
// Cleanup the DOM element
31+
$(this._element)
32+
.empty()
33+
.removeAttr("data-interval data-uri data-size")
34+
.addClass("wx-taskprogressbar");
35+
36+
$(this._element).append(this._progress);
37+
$(this._element).append(this._message);
38+
39+
3240

33-
this._container.append(this._progress);
34-
this._container.append(this._message);
35-
3641
this.receiveData();
3742
}
3843

3944
/**
4045
* Retrieve data from rest api.
4146
*/
4247
receiveData() {
43-
$.ajax({ type: "GET", url: this._restUri, dataType: 'json', }).then(function (data) {
44-
let progress = data.Progress ?? 0;
45-
let type = data.Type ?? "bg-primary";
46-
let message = data.Message ?? "";
48+
$.get(this._restUri)
49+
.done((response) => {
50+
const progress = response.progress ?? 0;
51+
const type = response.tpe ?? "bg-primary";
52+
const message = response.message ?? "";
4753

48-
this._progress.children().first().width(Math.min(Math.max(progress, 0), 100) + "%");
49-
this._progress.children().first().css("progress-bar progress-bar-striped progress-bar-animated" + type);
50-
this._message.html(message);
51-
52-
if (data.State == 3) {
53-
clearInterval(this._interval);
54-
this.trigger('webexpress.webapp.finish', data.Id);
55-
}
56-
57-
}.bind(this));
54+
this._progress.children().first().width(Math.min(Math.max(progress, 0), 100) + "%");
55+
this._progress.children().first()
56+
.addClass("progress-bar progress-bar-striped progress-bar-animated")
57+
.addClass(type)
58+
.addClass(this._size);
59+
this._message.html(message);
60+
61+
if (response.state == 3) {
62+
clearInterval(this._interval);
63+
this.trigger('webexpress.webapp.finish', data.Id);
64+
}
65+
66+
})
67+
.fail((error) => {
68+
console.error("The request could not be completed successfully:", error);
69+
});
5870
}
71+
}
5972

60-
/**
61-
* Returns the control.
62-
*/
63-
get getCtrl() {
64-
return this._container;
65-
}
66-
}
73+
// Register the class in the controller
74+
webexpress.webui.Controller.registerClass("wx-webapp-taskprogressbar", webexpress.webapp.TaskProgressBarCtrl);

src/WebExpress.WebApp/WebExpress.WebApp.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@
3434
</ItemGroup>
3535

3636
<ItemGroup>
37+
<None Remove="Assets\css\webexpress.webapp.table.css" />
3738
<None Remove="Assets\css\webexpress.webapp.theme.css" />
3839
</ItemGroup>
3940

4041
<ItemGroup>
4142
<EmbeddedResource Include="Assets\css\webexpress.webapp.css" />
4243
<EmbeddedResource Include="Assets\css\webexpress.webapp.popupnotification.css" />
44+
<EmbeddedResource Include="Assets\css\webexpress.webapp.table.css" />
4345
<EmbeddedResource Include="Assets\css\webexpress.webapp.taskprogressbar.css" />
4446
<EmbeddedResource Include="Assets\css\webexpress.webapp.theme.css" />
4547
<EmbeddedResource Include="Assets\js\webexpress.webapp.popupnotification.js" />

src/WebExpress.WebApp/WebPage/VisualTreeWebApp.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public VisualTreeWebApp(IComponentHub componentHub, IPageContext pageContext)
8888

8989
AddCssLink(RouteEndpoint.Combine(applicationContext?.Route, "/assets/css/webexpress.webapp.css"));
9090
AddCssLink(RouteEndpoint.Combine(applicationContext?.Route, "/assets/css/webexpress.webapp.popupnotification.css"));
91+
AddCssLink(RouteEndpoint.Combine(applicationContext?.Route, "/assets/css/webexpress.webapp.table.css"));
9192
AddCssLink(RouteEndpoint.Combine(applicationContext?.Route, "/assets/css/webexpress.webapp.taskprogressbar.css"));
9293
AddCssLink(Theme?.ThemeStyle.ToString() ?? RouteEndpoint.Combine(applicationContext?.Route, "/assets/css/webexpress.webapp.theme.css"));
9394
AddHeaderScriptLink(RouteEndpoint.Combine(applicationContext?.Route, "assets/js/webexpress.webapp.js"));

0 commit comments

Comments
 (0)