Skip to content

Commit dfe92b5

Browse files
authored
Templates pagination (#2292)
1 parent 98281db commit dfe92b5

File tree

6 files changed

+188
-169
lines changed

6 files changed

+188
-169
lines changed

services/web/client/source/class/osparc/dashboard/ExploreBrowser.js

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,7 @@
2525
qx.Class.define("osparc.dashboard.ExploreBrowser", {
2626
extend: osparc.dashboard.ResourceBrowserBase,
2727

28-
statics: {
29-
sortTemplateList: function(studyList) {
30-
let sortByProperty = function(prop) {
31-
return function(a, b) {
32-
if (prop === "lastChangeDate") {
33-
return new Date(b[prop]) - new Date(a[prop]);
34-
}
35-
if (typeof a[prop] == "number") {
36-
return a[prop] - b[prop];
37-
}
38-
if (a[prop] < b[prop]) {
39-
return -1;
40-
} else if (a[prop] > b[prop]) {
41-
return 1;
42-
}
43-
return 0;
44-
};
45-
};
46-
studyList.sort(sortByProperty("lastChangeDate"));
47-
}
48-
},
49-
5028
members: {
51-
__templatesContainer: null,
5229
__servicesContainer: null,
5330
__templates: null,
5431
__services: null,
@@ -57,8 +34,8 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
5734
* Function that resets the selected item
5835
*/
5936
resetSelection: function() {
60-
if (this.__templatesContainer) {
61-
this.__templatesContainer.resetSelection();
37+
if (this._studiesContainer) {
38+
this._studiesContainer.resetSelection();
6239
}
6340
if (this.__servicesContainer) {
6441
this.__servicesContainer.resetSelection();
@@ -102,15 +79,9 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
10279
/**
10380
* Function that asks the backend for the list of template studies and sets it
10481
*/
105-
reloadTemplates: function() {
82+
reloadStudies: function() {
10683
if (osparc.data.Permissions.getInstance().canDo("studies.templates.read")) {
107-
osparc.data.Resources.get("templates")
108-
.then(templates => {
109-
this._resetTemplatesList(templates);
110-
})
111-
.catch(err => {
112-
console.error(err);
113-
});
84+
this._requestStudies(true);
11485
} else {
11586
this._resetTemplatesList([]);
11687
}
@@ -137,27 +108,27 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
137108

138109
// overriden
139110
_initResources: function() {
140-
this._showLoadingPage(this.tr("Discovering Templates and Apps"));
111+
this._showLoadingPage(this.tr("Starting..."));
141112

142113
this.__templates = [];
143114
this.__services = [];
144-
const servicesTags = this.__getTags();
115+
const resourcePromises = [];
145116
const store = osparc.store.Store.getInstance();
146-
const servicesPromise = store.getServicesDAGs(true);
117+
resourcePromises.push(store.getServicesDAGs(true));
118+
if (osparc.data.Permissions.getInstance().canDo("study.tag")) {
119+
resourcePromises.push(osparc.data.Resources.get("tags"));
120+
}
147121

148-
Promise.all([
149-
servicesTags,
150-
servicesPromise
151-
])
122+
Promise.all(resourcePromises)
152123
.then(() => {
153-
this._hideLoadingPage();
154124
this.__createResourcesLayout();
155125
this.__reloadResources();
126+
this._hideLoadingPage();
156127
});
157128
},
158129

159130
__reloadResources: function() {
160-
this.reloadTemplates();
131+
this.reloadStudies();
161132
this.__reloadServices();
162133
},
163134

@@ -168,18 +139,6 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
168139
});
169140
},
170141

171-
__getTags: function() {
172-
return new Promise((resolve, reject) => {
173-
if (osparc.data.Permissions.getInstance().canDo("study.tag")) {
174-
osparc.data.Resources.get("tags")
175-
.catch(console.error)
176-
.finally(() => resolve());
177-
} else {
178-
resolve();
179-
}
180-
});
181-
},
182-
183142
__createResourcesLayout: function() {
184143
const exploreBrowserLayout = new qx.ui.container.Composite(new qx.ui.layout.VBox(16));
185144

@@ -194,6 +153,10 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
194153
this._add(scrollStudies, {
195154
flex: 1
196155
});
156+
157+
scrollStudies.getChildControl("pane").addListener("scrollY", () => {
158+
this._moreStudiesRequired();
159+
}, this);
197160
},
198161

199162
__createButtonsLayout: function(title, content) {
@@ -207,9 +170,17 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
207170
},
208171

209172
__createTemplatesLayout: function() {
210-
const templateStudyContainer = this.__templatesContainer = this.__createResourceListLayout();
173+
const templateStudyContainer = this._studiesContainer = this.__createResourceListLayout();
211174
osparc.utils.Utils.setIdToWidget(templateStudyContainer, "templateStudiesList");
212175
const tempStudyLayout = this.__createButtonsLayout(this.tr("Templates"), templateStudyContainer);
176+
177+
const loadingTemplatesBtn = this._loadingStudiesBtn = new osparc.dashboard.StudyBrowserButtonLoadMore();
178+
templateStudyContainer.add(loadingTemplatesBtn);
179+
180+
templateStudyContainer.addListener("changeVisibility", e => {
181+
this._moreStudiesRequired();
182+
}, this);
183+
213184
return tempStudyLayout;
214185
},
215186

@@ -345,8 +316,8 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
345316

346317
_resetTemplatesList: function(tempStudyList) {
347318
this.__templates = tempStudyList;
348-
this.__templatesContainer.removeAll();
349-
this.self().sortTemplateList(tempStudyList);
319+
this._studiesContainer.removeAll();
320+
osparc.dashboard.ResourceBrowserBase.sortStudyList(tempStudyList);
350321
tempStudyList.forEach(tempStudy => {
351322
tempStudy["resourceType"] = "template";
352323
const templateItem = this.__createStudyItem(tempStudy);
@@ -355,8 +326,32 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
355326
updatedTemplateData["resourceType"] = "template";
356327
this._resetTemplateItem(updatedTemplateData);
357328
}, this);
358-
this.__templatesContainer.add(templateItem);
329+
this._studiesContainer.add(templateItem);
330+
});
331+
osparc.component.filter.UIFilterController.dispatch("sideSearchFilter");
332+
},
333+
334+
_addStudiesToList: function(newTemplatesList) {
335+
osparc.dashboard.ResourceBrowserBase.sortStudyList(newTemplatesList);
336+
const templatesList = this._studiesContainer.getChildren();
337+
newTemplatesList.forEach(template => {
338+
if (this.__templates.indexOf(template) === -1) {
339+
this.__templates.push(template);
340+
}
341+
342+
template["resourceType"] = "template";
343+
const idx = templatesList.findIndex(card => card instanceof osparc.dashboard.StudyBrowserButtonItem && card.getUuid() === template["uuid"]);
344+
if (idx !== -1) {
345+
return;
346+
}
347+
const templateItem = this.__createStudyItem(template);
348+
this._studiesContainer.add(templateItem);
359349
});
350+
osparc.dashboard.ResourceBrowserBase.sortStudyList(templatesList.filter(card => card instanceof osparc.dashboard.StudyBrowserButtonItem));
351+
const idx = templatesList.findIndex(card => card instanceof osparc.dashboard.StudyBrowserButtonLoadMore);
352+
if (idx !== -1) {
353+
templatesList.push(templatesList.splice(idx, 1)[0]);
354+
}
360355
osparc.component.filter.UIFilterController.dispatch("sideSearchFilter");
361356
},
362357

@@ -388,7 +383,7 @@ qx.Class.define("osparc.dashboard.ExploreBrowser", {
388383
},
389384

390385
__removeFromStudyList: function(studyId) {
391-
const studyContainer = this.__templatesContainer;
386+
const studyContainer = this._studiesContainer;
392387
const items = studyContainer.getChildren();
393388
for (let i=0; i<items.length; i++) {
394389
const item = items[i];

services/web/client/source/class/osparc/dashboard/ResourceBrowserBase.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,97 @@ qx.Class.define("osparc.dashboard.ResourceBrowserBase", {
3434
this._setLayout(new qx.ui.layout.VBox(10));
3535

3636
this._initResources();
37+
38+
this.addListener("appear", () => {
39+
this._moreStudiesRequired();
40+
});
3741
},
3842

3943
events: {
4044
"startStudy": "qx.event.type.Data"
4145
},
4246

47+
statics: {
48+
sortStudyList: function(studyList) {
49+
const sortByProperty = function(prop) {
50+
return function(a, b) {
51+
if (prop === "lastChangeDate") {
52+
return new Date(b[prop]) - new Date(a[prop]);
53+
}
54+
if (typeof a[prop] == "number") {
55+
return a[prop] - b[prop];
56+
}
57+
if (a[prop] < b[prop]) {
58+
return -1;
59+
} else if (a[prop] > b[prop]) {
60+
return 1;
61+
}
62+
return 0;
63+
};
64+
};
65+
studyList.sort(sortByProperty("lastChangeDate"));
66+
},
67+
68+
PAGINATED_STUDIES: 10,
69+
MIN_FILTERED_STUDIES: 15
70+
},
71+
4372
members: {
73+
_studiesContainer: null,
74+
_loadingStudiesBtn: null,
75+
4476
_initResources: function() {
4577
throw new Error("Abstract method called!");
4678
},
4779

80+
_requestStudies: function(templates = false) {
81+
if (this._loadingStudiesBtn.isFetching()) {
82+
return;
83+
}
84+
this._loadingStudiesBtn.setFetching(true);
85+
const params = {
86+
url: {
87+
offset: this._studiesContainer.nStudies || 0,
88+
limit: osparc.dashboard.ResourceBrowserBase.PAGINATED_STUDIES
89+
}
90+
};
91+
const resolveWResponse = true;
92+
osparc.data.Resources.fetch(templates ? "templates" : "studies", "getPage", params, undefined, resolveWResponse)
93+
.then(resp => {
94+
const studies = resp["data"];
95+
const tStudies = resp["_meta"]["total"];
96+
this._studiesContainer.nStudies = (this._studiesContainer.nStudies || 0) + studies.length;
97+
this._studiesContainer.noMoreStudies = this._studiesContainer.nStudies >= tStudies;
98+
this._addStudiesToList(studies);
99+
})
100+
.catch(err => {
101+
console.error(err);
102+
})
103+
.finally(() => {
104+
this._loadingStudiesBtn.setFetching(false);
105+
this._loadingStudiesBtn.setVisibility(this._studiesContainer.noMoreStudies ? "excluded" : "visible");
106+
this._moreStudiesRequired();
107+
});
108+
},
109+
110+
_addStudiesToList: function() {
111+
throw new Error("Abstract method called!");
112+
},
113+
114+
_moreStudiesRequired: function() {
115+
if (this._studiesContainer &&
116+
!this._studiesContainer.noMoreStudies &&
117+
(this._studiesContainer.getVisibles().length < osparc.dashboard.ResourceBrowserBase.MIN_FILTERED_STUDIES ||
118+
this._loadingStudiesBtn.checkIsOnScreen())
119+
) {
120+
this.reloadStudies();
121+
}
122+
},
123+
124+
reloadStudies: function() {
125+
throw new Error("Abstract method called!");
126+
},
127+
48128
_getMoreInfoMenuButton: function(resourceData) {
49129
const moreInfoButton = new qx.ui.menu.Button(this.tr("More Info"));
50130
osparc.utils.Utils.setIdToWidget(moreInfoButton, "moreInfoBtn");

0 commit comments

Comments
 (0)