Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ [Frontend] Drag&Drop: Projects and Folders I #6957

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
565681c
set layout first
odeimaiz Dec 12, 2024
20e3f3d
isValidWidget
odeimaiz Dec 12, 2024
955bf5d
[skip ci] ToggleButton -> Widget
odeimaiz Dec 12, 2024
be05ce1
[skip ci] minor
odeimaiz Dec 12, 2024
e5affe5
[skip ci] tap service button
odeimaiz Dec 12, 2024
011f9de
[skip ci] don't listen to change value
odeimaiz Dec 12, 2024
84ba8f7
[skip ci] __evalSelectedButton
odeimaiz Dec 12, 2024
7b89f36
Merge branch 'master' into feature/daraga-doropa
odeimaiz Dec 12, 2024
23a0aae
empty specific-info by default
odeimaiz Dec 12, 2024
4302f5d
not needed
odeimaiz Dec 12, 2024
b0e51d5
[skip ci] minor
odeimaiz Dec 12, 2024
8719ce8
simpler
odeimaiz Dec 12, 2024
63d496b
minors
odeimaiz Dec 12, 2024
dea32d2
refactor
odeimaiz Dec 12, 2024
4f6f2b5
[skip ci] minor
odeimaiz Dec 12, 2024
fdc8a5c
[skip ci] cleanup
odeimaiz Dec 12, 2024
7850d4f
rename files
odeimaiz Dec 12, 2024
fe21854
[skip ci] rename
odeimaiz Dec 12, 2024
0e44843
[skip ci] renaming
odeimaiz Dec 12, 2024
44713c9
prettifyMenus
odeimaiz Dec 12, 2024
288ef49
[skip ci] multiselection working
odeimaiz Dec 13, 2024
a51fc68
support null first and last name
odeimaiz Dec 13, 2024
744d96f
[skip ci] attachDragHandlers and attachDropHandlers
odeimaiz Dec 13, 2024
4022440
Merge branch 'master' into feature/daraga-doropa
odeimaiz Dec 13, 2024
1f68f7c
[skip ci] minor
odeimaiz Dec 13, 2024
35ab99d
Merge branch 'feature/daraga-doropa' of github.com:odeimaiz/osparc-si…
odeimaiz Dec 13, 2024
b560585
[skip ci] pass ordingin info in drag event
odeimaiz Dec 13, 2024
3a5bd4a
[skip ci] compatibility checks
odeimaiz Dec 13, 2024
c3622d0
move working
odeimaiz Dec 13, 2024
b3833b5
wire signals
odeimaiz Dec 13, 2024
1ff160a
[skip ci] minor
odeimaiz Dec 13, 2024
10ebce4
move study working
odeimaiz Dec 13, 2024
03f7f0f
Merge branch 'master' into feature/daraga-doropa
odeimaiz Dec 13, 2024
451f3bb
minor
odeimaiz Dec 13, 2024
884f833
not needed
odeimaiz Dec 13, 2024
afe48e5
list items are not toggle buttons
odeimaiz Dec 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
************************************************************************ */

qx.Class.define("osparc.dashboard.CardBase", {
extend: qx.ui.form.ToggleButton,
extend: qx.ui.core.Widget,
implement: [qx.ui.form.IModel, osparc.filter.IFilterable],
include: [qx.ui.form.MModelProperty, osparc.filter.MFilterable],
type: "abstract",
Expand All @@ -33,6 +33,8 @@ qx.Class.define("osparc.dashboard.CardBase", {
"pointerout",
"focusout"
].forEach(e => this.addListener(e, this._onPointerOut, this));

this.addListener("changeSelected", this.__evalSelectedButton, this);
},

events: {
Expand Down Expand Up @@ -237,6 +239,20 @@ qx.Class.define("osparc.dashboard.CardBase", {
nullable: true
},

selected: {
check: "Boolean",
init: false,
nullable: false,
event: "changeSelected",
},

icon: {
check: "String",
init: null,
nullable: true,
apply: "_applyIcon",
},

resourceData: {
check: "Object",
nullable: false,
Expand All @@ -246,7 +262,8 @@ qx.Class.define("osparc.dashboard.CardBase", {

resourceType: {
check: ["study", "template", "service"],
nullable: false,
init: true,
nullable: true,
event: "changeResourceType"
},

Expand Down Expand Up @@ -365,7 +382,7 @@ qx.Class.define("osparc.dashboard.CardBase", {
check: "Boolean",
init: false,
nullable: false,
apply: "_applyMultiSelectionMode"
apply: "__applyMultiSelectionMode"
},

fetching: {
Expand Down Expand Up @@ -444,6 +461,35 @@ qx.Class.define("osparc.dashboard.CardBase", {
});
},

__applyMultiSelectionMode: function(value) {
if (!value) {
this.setSelected(false);
}
this.__evalSelectedButton();
},

__evalSelectedButton: function() {
if (
this.isResourceType("study") ||
this.isResourceType("template") ||
this.isResourceType("service")
) {
const menuButton = this.getChildControl("menu-button");
const tick = this.getChildControl("tick-selected");
const untick = this.getChildControl("tick-unselected");
if (this.isResourceType("study") && this.isMultiSelectionMode()) {
const selected = this.getSelected();
menuButton.setVisibility("excluded");
tick.setVisibility(selected ? "visible" : "excluded");
untick.setVisibility(selected ? "excluded" : "visible");
} else {
menuButton.setVisibility("visible");
tick.setVisibility("excluded");
untick.setVisibility("excluded");
}
}
},

__applyUuid: function(value, old) {
const resourceType = this.getResourceType() || "study";
osparc.utils.Utils.setIdToWidget(this, resourceType + "BrowserListItem_" + value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
*/

/**
* Container for GridButtonItems and ListButtonItems (ToggleButtons), with some convenient methods.
* Container for GridButtons and ListButtons (CardBase, FolderButtonBase and WorkspaceButtonBase), with some convenient methods.
*/
qx.Class.define("osparc.dashboard.ToggleButtonContainer", {
qx.Class.define("osparc.dashboard.CardContainer", {
extend: qx.ui.container.Composite,

construct: function() {
Expand All @@ -22,28 +22,38 @@ qx.Class.define("osparc.dashboard.ToggleButtonContainer", {
"changeVisibility": "qx.event.type.Data"
},

statics: {
isValidCard: function(widget) {
return (
widget instanceof osparc.dashboard.CardBase ||
widget instanceof osparc.dashboard.FolderButtonBase ||
widget instanceof osparc.dashboard.WorkspaceButtonBase
);
},
},

members: {
__lastSelectedIdx: null,

// overridden
add: function(child, options) {
if (child instanceof qx.ui.form.ToggleButton) {
if (this.self().isValidCard(child)) {
if (osparc.dashboard.ResourceContainerManager.cardExists(this, child)) {
return;
}
this.base(arguments, child, options);
child.addListener("changeValue", () => this.fireDataEvent("changeSelection", this.getSelection()), this);
child.addListener("changeSelected", () => this.fireDataEvent("changeSelection", this.getSelection()), this);
child.addListener("changeVisibility", () => this.fireDataEvent("changeVisibility", this.__getVisibles()), this);
} else {
console.error("ToggleButtonContainer only allows ToggleButton as its children.");
console.error("CardContainer only allows CardBase as its children.");
}
},

/**
* Resets the selection so no toggle button is checked.
*/
resetSelection: function() {
this.getChildren().map(button => button.setValue(false));
this.getChildren().map(button => button.setSelected(false));
this.__lastSelectedIdx = null;
this.fireDataEvent("changeSelection", this.getSelection());
},
Expand All @@ -52,7 +62,7 @@ qx.Class.define("osparc.dashboard.ToggleButtonContainer", {
* Returns an array that contains all buttons that are checked.
*/
getSelection: function() {
return this.getChildren().filter(button => button.getValue());
return this.getChildren().filter(button => button.getSelected());
},

/**
Expand All @@ -63,18 +73,18 @@ qx.Class.define("osparc.dashboard.ToggleButtonContainer", {
},

/**
* Sets the given button's value to true (checks it) and unchecks all other buttons. If the given button is not present,
* every button in the container will get a false value (unchecked).
* @param {qx.ui.form.ToggleButton} child Button that will be checked
* Sets the given button's select prop to true (checks it) and unchecks all other buttons. If the given button is not present,
* every button in the container will get a unselected (unchecked).
* @param {qx.ui.form.CardBase} child Button that will be checked
*/
selectOne: function(child) {
this.getChildren().map(button => button.setValue(button === child));
this.getChildren().map(button => button.setSelected(button === child));
this.setLastSelectedIndex(this.getIndex(child));
},

/**
* Gets the index in the container of the given button.
* @param {qx.ui.form.ToggleButton} child Button that will be checked
* @param {qx.ui.form.CardBase} child Button that will be checked
*/
getIndex: function(child) {
return this.getChildren().findIndex(button => button === child);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
************************************************************************ */

qx.Class.define("osparc.dashboard.FolderButtonBase", {
extend: qx.ui.form.ToggleButton,
extend: qx.ui.core.Widget,
implement: [qx.ui.form.IModel, osparc.filter.IFilterable],
include: [qx.ui.form.MModelProperty, osparc.filter.MFilterable],
type: "abstract",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
appearance: "pb-study"
});

this.addListener("changeValue", e => this.__itemSelected(e.getData()), this);
this.addListener("tap", this.__itemSelected, this);

this.setPriority(osparc.dashboard.CardBase.CARD_PRIORITY.ITEM);

Expand All @@ -50,6 +50,8 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
"untrashFolderRequested": "qx.event.type.Data",
"deleteFolderRequested": "qx.event.type.Data",
"changeContext": "qx.event.type.Data",
"studyToFolderRequested": "qx.event.type.Data",
"folderToFolderRequested": "qx.event.type.Data",
},

properties: {
Expand Down Expand Up @@ -152,6 +154,87 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
osparc.utils.Utils.setIdToWidget(this, "folderItem_" + folder.getFolderId());

this.__addMenuButton();

this.__attachDragHandlers();
this.__attachDropHandlers();
},

__attachDragHandlers: function() {
this.setDraggable(true);
this.addListener("dragstart", e => {
e.addAction("move");
e.addType("osparc-moveFolder");
e.addData("osparc-moveFolder", {
"folderOrigin": this.getFolder(),
});
});
},

__attachDropHandlers: function() {
this.setDroppable(true);

this.addListener("dragover", e => {
let compatible = false;
if (e.supportsType("osparc-moveStudy")) {
const studyData = e.getData("osparc-moveStudy")["studyDataOrigin"];
// Compatibility checks:
// - My workspace
// - None
// - Shared workspace
// - write access on workspace
const workspaceId = studyData["workspaceId"];
if (workspaceId) {
const workspace = osparc.store.Workspaces.getInstance().getWorkspace(workspaceId);
if (workspace) {
compatible = workspace.getMyAccessRights()["write"];
}
} else {
compatible = true;
}
} else if (e.supportsType("osparc-moveFolder")) {
// Compatibility checks:
// - It's not the same folder
// - My workspace
// - None
// - Shared workspace
// - write access on workspace
const folder = e.getData("osparc-moveFolder")["folderOrigin"];
compatible = this.getFolder() !== folder;
const workspaceId = folder.getWorkspaceId();
if (compatible) {
if (workspaceId) {
const workspace = osparc.store.Workspaces.getInstance().getWorkspace(workspaceId);
if (workspace) {
compatible = workspace.getMyAccessRights()["write"];
}
} else {
compatible = true;
}
}
}
if (!compatible) {
// do not allow
e.preventDefault();
}
});

this.addListener("drop", e => {
if (e.supportsType("osparc-moveStudy")) {
const studyData = e.getData("osparc-moveStudy")["studyDataOrigin"];
const studyToFolderData = {
studyData,
destFolderId: this.getFolderId(),
};
this.fireDataEvent("studyToFolderRequested", studyToFolderData);
} else if (e.supportsType("osparc-moveFolder")) {
const folder = e.getData("osparc-moveFolder")["folderOrigin"];
const folderToFolderData = {
folderId: folder.getFolderId(),
destFolderId: this.getFolderId(),
};
this.fireDataEvent("folderToFolderRequested", folderToFolderData);
}
});
},

__applyWorkspaceId: function(workspaceId) {
Expand Down Expand Up @@ -188,9 +271,9 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
const menuButton = this.getChildControl("menu-button");
menuButton.setVisibility("visible");

const menu = new qx.ui.menu.Menu().set({
position: "bottom-right"
});
const menu = new qx.ui.menu.Menu();
menu.setPosition("bottom-right");
osparc.utils.Utils.prettifyMenu(menu);

const studyBrowserContext = osparc.store.Store.getInstance().getStudyBrowserContext();
if (
Expand Down Expand Up @@ -240,13 +323,12 @@ qx.Class.define("osparc.dashboard.FolderButtonItem", {
menuButton.setMenu(menu);
},

__itemSelected: function(newVal) {
__itemSelected: function() {
const studyBrowserContext = osparc.store.Store.getInstance().getStudyBrowserContext();
// do not allow selecting workspace
if (studyBrowserContext !== "trash" && newVal) {
if (studyBrowserContext !== "trash") {
this.fireDataEvent("folderSelected", this.getFolderId());
}
this.setValue(false);
},

__editFolder: function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ qx.Class.define("osparc.dashboard.FolderButtonNew", {
appearance: "pb-new"
});

this.addListener("changeValue", e => this.__itemSelected(e.getData()), this);
this.addListener("tap", this.__itemSelected, this);

this.setPriority(osparc.dashboard.CardBase.CARD_PRIORITY.NEW);

Expand Down Expand Up @@ -77,22 +77,19 @@ qx.Class.define("osparc.dashboard.FolderButtonNew", {
this.getChildControl("title");
},

__itemSelected: function(newVal) {
if (newVal) {
const newFolder = true;
const folderEditor = new osparc.editor.FolderEditor(newFolder);
const title = this.tr("New Folder");
const win = osparc.ui.window.Window.popUpInWindow(folderEditor, title, 300, 120);
folderEditor.addListener("createFolder", () => {
const name = folderEditor.getLabel();
this.fireDataEvent("createFolder", {
name,
});
win.close();
__itemSelected: function() {
const newFolder = true;
const folderEditor = new osparc.editor.FolderEditor(newFolder);
const title = this.tr("New Folder");
const win = osparc.ui.window.Window.popUpInWindow(folderEditor, title, 300, 120);
folderEditor.addListener("createFolder", () => {
const name = folderEditor.getLabel();
this.fireDataEvent("createFolder", {
name,
});
folderEditor.addListener("cancel", () => win.close());
}
this.setValue(false);
win.close();
});
folderEditor.addListener("cancel", () => win.close());
}
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
construct: function() {
this.base(arguments);

this._setLayout(new qx.ui.layout.Canvas());

this.set({
width: this.self().ITEM_WIDTH,
height: this.self().ITEM_HEIGHT,
padding: 0,
allowGrowX: false
});

this._setLayout(new qx.ui.layout.Canvas());

this.getChildControl("main-layout");
},

Expand Down Expand Up @@ -107,7 +107,6 @@ qx.Class.define("osparc.dashboard.GridButtonBase", {
},

members: {

// overridden
_createChildControlImpl: function(id) {
let layout;
Expand Down
Loading
Loading