Skip to content

Commit 036790d

Browse files
authored
Merge branch 'master' into mai/pytest-upgrade-repo-wide
2 parents c92037c + 04ffd16 commit 036790d

File tree

2 files changed

+168
-117
lines changed

2 files changed

+168
-117
lines changed

services/static-webserver/client/source/class/osparc/po/POCenter.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ qx.Class.define("osparc.po.POCenter", {
2727
this.addWidgetToTabs(miniProfile);
2828

2929
this.__addActiveUsersPage();
30-
if (osparc.utils.Utils.isDevelopmentPlatform()) {
31-
this.__addPendingUsersPage();
32-
}
30+
this.__addReviewUsersPage();
3331
this.__addPreRegistrationPage();
3432
this.__addInvitationsPage();
3533
this.__addProductPage();
@@ -44,8 +42,8 @@ qx.Class.define("osparc.po.POCenter", {
4442
this.addTab(title, iconSrc, users);
4543
},
4644

47-
__addPendingUsersPage: function() {
48-
const title = this.tr("Pending Users");
45+
__addReviewUsersPage: function() {
46+
const title = this.tr("Review Users");
4947
const iconSrc = "@FontAwesome5Solid/user-plus/22";
5048
const usersPending = new osparc.po.UsersPending();
5149
this.addTab(title, iconSrc, usersPending);

services/static-webserver/client/source/class/osparc/po/UsersPending.js

Lines changed: 165 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -56,77 +56,6 @@ qx.Class.define("osparc.po.UsersPending", {
5656
return form;
5757
},
5858

59-
createApproveButton: function(email) {
60-
const button = new qx.ui.form.Button(qx.locale.Manager.tr("Approve"));
61-
button.addListener("execute", () => {
62-
const form = this.createInvitationForm(false);
63-
const approveBtn = new osparc.ui.form.FetchButton(qx.locale.Manager.tr("Approve"));
64-
approveBtn.set({
65-
appearance: "form-button"
66-
});
67-
form.addButton(approveBtn);
68-
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
69-
const invitationForm = new qx.ui.form.renderer.Single(form);
70-
layout.add(invitationForm);
71-
const win = osparc.ui.window.Window.popUpInWindow(layout, email, 350, 150).set({
72-
clickAwayClose: false,
73-
resizable: false,
74-
showClose: true
75-
});
76-
win.open();
77-
approveBtn.addListener("execute", () => {
78-
if (!osparc.data.Permissions.getInstance().canDo("user.invitation.generate", true)) {
79-
return;
80-
}
81-
if (form.validate()) {
82-
approveBtn.setFetching(true);
83-
const params = {
84-
data: {
85-
email,
86-
},
87-
};
88-
params.data["invitation"] = {};
89-
const extraCreditsInUsd = form.getItems()["credits"].getValue();
90-
if (extraCreditsInUsd > 0) {
91-
params.data["invitation"]["extraCreditsInUsd"] = extraCreditsInUsd;
92-
}
93-
if (form.getItems()["withExpiration"].getValue()) {
94-
params.data["invitation"]["trialAccountDays"] = form.getItems()["trialDays"].getValue();
95-
}
96-
osparc.data.Resources.fetch("poUsers", "approveUser", params)
97-
.then(() => {
98-
osparc.FlashMessenger.logAs(qx.locale.Manager.tr("User approved"), "INFO");
99-
})
100-
.catch(err => osparc.FlashMessenger.logError(err))
101-
.finally(() => {
102-
approveBtn.setFetching(false);
103-
win.close();
104-
});
105-
}
106-
});
107-
});
108-
return button;
109-
},
110-
111-
createRejectButton: function(email) {
112-
const button = new osparc.ui.form.FetchButton(qx.locale.Manager.tr("Reject"));
113-
button.addListener("execute", () => {
114-
button.setFetching(true);
115-
const params = {
116-
data: {
117-
email,
118-
},
119-
};
120-
osparc.data.Resources.fetch("poUsers", "rejectUser", params)
121-
.then(() => {
122-
osparc.FlashMessenger.logAs(qx.locale.Manager.tr("User denied"), "INFO");
123-
})
124-
.catch(err => osparc.FlashMessenger.logError(err))
125-
.finally(() => button.setFetching(false));
126-
});
127-
return button;
128-
},
129-
13059
createResendEmailButton: function(email) {
13160
const button = new osparc.ui.form.FetchButton(qx.locale.Manager.tr("Resend Email"));
13261
button.addListener("execute", () => {
@@ -147,7 +76,7 @@ qx.Class.define("osparc.po.UsersPending", {
14776
},
14877

14978
createInfoButton: function(infoMetadata) {
150-
const infoButton = new qx.ui.form.Button(null, "@MaterialIcons/info_outline/16");
79+
const infoButton = new qx.ui.form.Button(null, "@MaterialIcons/info_outline/14");
15180
infoButton.addListener("execute", () => {
15281
const container = new qx.ui.container.Scroll();
15382
container.add(new osparc.ui.basic.JsonTreeWidget(infoMetadata, "pendingUserInfo"));
@@ -165,10 +94,7 @@ qx.Class.define("osparc.po.UsersPending", {
16594
control = new qx.ui.form.Button(this.tr("Reload")).set({
16695
allowGrowX: false,
16796
});
168-
control.addListener("execute", () => {
169-
this.getChildControl("pending-users-layout").removeAll();
170-
this.__populatePendingUsersLayout();
171-
});
97+
control.addListener("execute", () => this.__reload());
17298
this._add(control);
17399
break;
174100
case "pending-users-container":
@@ -190,7 +116,7 @@ qx.Class.define("osparc.po.UsersPending", {
190116
_buildLayout: function() {
191117
this.getChildControl("reload-button");
192118
this.getChildControl("pending-users-container");
193-
119+
this.__addHeader();
194120
this.__populatePendingUsersLayout();
195121
},
196122

@@ -217,34 +143,16 @@ qx.Class.define("osparc.po.UsersPending", {
217143
row: 0,
218144
column: 2,
219145
});
220-
221-
pendingUsersLayout.add(new qx.ui.basic.Label(this.tr("Status")).set({
222-
font: "text-14"
223-
}), {
224-
row: 0,
225-
column: 3,
226-
});
227-
228-
pendingUsersLayout.add(new qx.ui.basic.Label(this.tr("Info")).set({
229-
font: "text-14"
230-
}), {
231-
row: 0,
232-
column: 4,
233-
});
234-
235-
pendingUsersLayout.add(new qx.ui.basic.Label(this.tr("Action")).set({
236-
font: "text-14"
237-
}), {
238-
row: 0,
239-
column: 5,
240-
});
241146
},
242147

243148
__addRows: function(pendingUsers) {
244149
const pendingUsersLayout = this.getChildControl("pending-users-layout");
150+
const grid = pendingUsersLayout.getLayout();
245151

246152
let row = 1;
247153
pendingUsers.forEach(pendingUser => {
154+
grid.setRowAlign(row, "left", "middle");
155+
248156
pendingUsersLayout.add(new qx.ui.basic.Label(pendingUser.firstName + " " + pendingUser.lastName), {
249157
row,
250158
column: 0,
@@ -253,44 +161,62 @@ qx.Class.define("osparc.po.UsersPending", {
253161
row,
254162
column: 1,
255163
});
256-
pendingUsersLayout.add(new qx.ui.basic.Label(pendingUser.date ? osparc.utils.Utils.formatDateAndTime(new Date(pendingUser.date)) : "-"), {
164+
pendingUsersLayout.add(new qx.ui.basic.Label(pendingUser.accountRequestReviewedAt ? osparc.utils.Utils.formatDateAndTime(new Date(pendingUser.accountRequestReviewedAt)) : "-"), {
257165
row,
258166
column: 2,
259167
});
260-
pendingUsersLayout.add(new qx.ui.basic.Label(pendingUser.accountRequestStatus.toLowerCase()), {
168+
const statusImage = new qx.ui.basic.Image();
169+
pendingUsersLayout.add(statusImage, {
261170
row,
262171
column: 3,
263172
});
173+
pendingUsersLayout.add(new qx.ui.basic.Label(pendingUser.accountRequestStatus.toLowerCase()), {
174+
row,
175+
column: 4,
176+
});
264177
const infoButton = this.self().createInfoButton(pendingUser);
265178
pendingUsersLayout.add(infoButton, {
266179
row,
267-
column: 4,
180+
column: 5,
268181
});
269182
const buttonsLayout = new qx.ui.container.Composite(new qx.ui.layout.HBox(5));
270183
pendingUsersLayout.add(buttonsLayout, {
271184
row,
272-
column: 5,
185+
column: 6,
273186
});
274187

275188
switch (pendingUser.accountRequestStatus) {
276189
case "PENDING": {
277-
const approveButton = this.self().createApproveButton(pendingUser.email);
190+
statusImage.set({
191+
source: "@FontAwesome5Solid/hourglass-end/14",
192+
textColor: "warning-yellow",
193+
});
194+
const approveButton = this.__createApproveButton(pendingUser.email);
278195
buttonsLayout.add(approveButton);
279-
const rejectButton = this.self().createRejectButton(pendingUser.email);
196+
const rejectButton = this.__createRejectButton(pendingUser.email);
280197
buttonsLayout.add(rejectButton);
281198
break;
282199
}
283200
case "REJECTED": {
284-
const approveButton = this.self().createApproveButton(pendingUser.email);
201+
statusImage.set({
202+
source: "@FontAwesome5Solid/times/14",
203+
textColor: "danger-red",
204+
});
205+
const approveButton = this.__createApproveButton(pendingUser.email);
206+
approveButton.setEnabled(false); // avoid changing decision for now
285207
buttonsLayout.add(approveButton);
286208
break;
287209
}
288210
case "APPROVED": {
289-
/*
211+
statusImage.set({
212+
source: "@FontAwesome5Solid/check/14",
213+
textColor: "product-color",
214+
});
290215
const resendEmailButton = this.self().createResendEmailButton(pendingUser.email);
216+
resendEmailButton.setEnabled(false);
291217
buttonsLayout.add(resendEmailButton);
292-
*/
293-
const rejectButton = this.self().createRejectButton(pendingUser.email);
218+
const rejectButton = this.__createRejectButton(pendingUser.email);
219+
rejectButton.setEnabled(false); // avoid changing decision for now
294220
buttonsLayout.add(rejectButton);
295221
break;
296222
}
@@ -307,12 +233,139 @@ qx.Class.define("osparc.po.UsersPending", {
307233
.then(resps => {
308234
const pendingUsers = resps[0];
309235
const reviewedUsers = resps[1];
310-
const pendingUsersLayout = this.getChildControl("pending-users-layout");
311-
pendingUsersLayout.removeAll();
312-
this.__addHeader();
236+
const sortByDate = (a, b) => {
237+
const dateA = a.accountRequestReviewedAt ? new Date(a.accountRequestReviewedAt) : new Date(0);
238+
const dateB = b.accountRequestReviewedAt ? new Date(b.accountRequestReviewedAt) : new Date(0);
239+
return dateB - dateA; // sort by most recent first
240+
};
241+
pendingUsers.sort(sortByDate);
242+
reviewedUsers.sort(sortByDate);
313243
this.__addRows(pendingUsers.concat(reviewedUsers));
314244
})
315245
.catch(err => osparc.FlashMessenger.logError(err));
316-
}
246+
},
247+
248+
__reload: function() {
249+
this.getChildControl("pending-users-layout").removeAll();
250+
this.__addHeader();
251+
this.__populatePendingUsersLayout();
252+
},
253+
254+
__createApproveButton: function(email) {
255+
const button = new qx.ui.form.Button(qx.locale.Manager.tr("Approve"));
256+
button.addListener("execute", () => {
257+
const form = this.self().createInvitationForm(false);
258+
const approveBtn = new osparc.ui.form.FetchButton(qx.locale.Manager.tr("Approve"));
259+
approveBtn.set({
260+
appearance: "form-button"
261+
});
262+
form.addButton(approveBtn);
263+
const layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(10));
264+
const invitationForm = new qx.ui.form.renderer.Single(form);
265+
layout.add(invitationForm);
266+
const win = osparc.ui.window.Window.popUpInWindow(layout, email, 350, 150).set({
267+
clickAwayClose: false,
268+
resizable: false,
269+
showClose: true
270+
});
271+
win.open();
272+
approveBtn.addListener("execute", () => {
273+
if (osparc.data.Permissions.getInstance().canDo("user.invitation.generate", true)) {
274+
if (form.validate()) {
275+
const extraCreditsInUsd = form.getItems()["credits"].getValue();
276+
let trialAccountDays = 0;
277+
if (form.getItems()["withExpiration"].getValue()) {
278+
trialAccountDays = form.getItems()["trialDays"].getValue();
279+
}
280+
281+
let msg = `Are you sure you want to approve ${email}`;
282+
if (extraCreditsInUsd) {
283+
msg += ` with ${extraCreditsInUsd}$ worth credits`;
284+
}
285+
if (trialAccountDays > 0) {
286+
msg += ` and ${trialAccountDays} days of trial`;
287+
}
288+
msg += "?";
289+
const confWin = new osparc.ui.window.Confirmation(msg).set({
290+
caption: "Approve User",
291+
confirmText: "Approve",
292+
confirmAction: "create"
293+
});
294+
confWin.center();
295+
confWin.open();
296+
confWin.addListener("close", () => {
297+
if (confWin.getConfirmed()) {
298+
approveBtn.setFetching(true);
299+
this.__approveUser(email, form)
300+
.then(() => {
301+
osparc.FlashMessenger.logAs("User approved", "INFO");
302+
this.__reload();
303+
})
304+
.catch(err => osparc.FlashMessenger.logError(err))
305+
.finally(() => {
306+
approveBtn.setFetching(false);
307+
win.close();
308+
});
309+
}
310+
});
311+
}
312+
}
313+
});
314+
});
315+
return button;
316+
},
317+
318+
__createRejectButton: function(email) {
319+
const button = new osparc.ui.form.FetchButton("Reject");
320+
button.addListener("execute", () => {
321+
const msg = `Are you sure you want to reject ${email}.<br>The operation cannot be reverted"`;
322+
const win = new osparc.ui.window.Confirmation(msg).set({
323+
caption: "Reject User",
324+
confirmText: "Reject",
325+
confirmAction: "delete",
326+
});
327+
win.center();
328+
win.open();
329+
win.addListener("close", () => {
330+
if (win.getConfirmed()) {
331+
button.setFetching(true);
332+
this.__rejectUser(email)
333+
.then(() => {
334+
osparc.FlashMessenger.logAs(qx.locale.Manager.tr("User denied"), "INFO");
335+
this.__reload();
336+
})
337+
.catch(err => osparc.FlashMessenger.logError(err))
338+
.finally(() => button.setFetching(false));
339+
}
340+
});
341+
});
342+
return button;
343+
},
344+
345+
__approveUser: function(email, form) {
346+
const params = {
347+
data: {
348+
email,
349+
},
350+
};
351+
params.data["invitation"] = {};
352+
const extraCreditsInUsd = form.getItems()["credits"].getValue();
353+
if (extraCreditsInUsd > 0) {
354+
params.data["invitation"]["extraCreditsInUsd"] = extraCreditsInUsd;
355+
}
356+
if (form.getItems()["withExpiration"].getValue()) {
357+
params.data["invitation"]["trialAccountDays"] = form.getItems()["trialDays"].getValue();
358+
}
359+
return osparc.data.Resources.fetch("poUsers", "approveUser", params);
360+
},
361+
362+
__rejectUser: function(email) {
363+
const params = {
364+
data: {
365+
email,
366+
},
367+
};
368+
return osparc.data.Resources.fetch("poUsers", "rejectUser", params);
369+
},
317370
}
318371
});

0 commit comments

Comments
 (0)