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

SWC-7185 #5590

Merged
merged 2 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -43,6 +43,9 @@ public enum FeatureFlagKey {
// If enabled, uses the v2 uploader (react implementation) for file entity uploads.
UPLOADER_V2("UPLOADER_V2"),

// If enabled, uses the file browser react implementation
REACT_FILE_BROWSER("REACT_FILE_BROWSER"),

// Last flag is used only for tests
TEST_FLAG_ONLY("TEST_FLAG_ONLY");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.sagebionetworks.web.client.jsinterop;

import jsinterop.annotations.JsFunction;
import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;
import org.sagebionetworks.web.client.jsni.ReferenceJSNIObject;

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
public class EntityFileBrowserProps extends ReactComponentProps {

@FunctionalInterface
@JsFunction
public interface OnSelectCallback {
void run(ReferenceJSNIObject selected);
}

OnSelectCallback onSelect;
String parentContainerId;

@JsOverlay
public static EntityFileBrowserProps create(
String parentContainerId,
OnSelectCallback onSelect
) {
EntityFileBrowserProps props = new EntityFileBrowserProps();
props.parentContainerId = parentContainerId;
props.onSelect = onSelect;
return props;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static class SynapseComponents {
public static ReactComponentType<EntityBadgeIconsProps> EntityBadgeIcons;
public static ReactComponentType<DatasetEditorProps> DatasetItemsEditor;
public static ReactComponentType<EntityFinderProps> EntityFinder;
public static ReactComponentType<EntityFileBrowserProps> EntityFileBrowser;
public static ReactComponentType<EvaluationCardProps> EvaluationCard;
public static ReactComponentType<
EvaluationEditorPageProps
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package org.sagebionetworks.web.client.widget.entity.browse;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import org.gwtbootstrap3.client.ui.AnchorListItem;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.Heading;
import org.gwtbootstrap3.client.ui.Tooltip;
import org.gwtbootstrap3.client.ui.html.Div;
import org.gwtbootstrap3.client.ui.html.Span;
import org.sagebionetworks.web.client.DisplayUtils;
import org.sagebionetworks.web.client.security.AuthenticationController;
import org.sagebionetworks.web.client.FeatureFlagConfig;
import org.sagebionetworks.web.client.FeatureFlagKey;
import org.sagebionetworks.web.client.context.SynapseReactClientFullContextPropsProvider;
import org.sagebionetworks.web.client.jsinterop.EntityFileBrowserProps;
import org.sagebionetworks.web.client.jsinterop.React;
import org.sagebionetworks.web.client.jsinterop.ReactElement;
import org.sagebionetworks.web.client.jsinterop.SRC;
import org.sagebionetworks.web.client.utils.CallbackP;
import org.sagebionetworks.web.client.widget.HelpWidget;
import org.sagebionetworks.web.client.widget.ReactComponent;

public class FilesBrowserViewImpl implements FilesBrowserView {

Expand All @@ -23,6 +26,8 @@ public interface FilesBrowserViewImplUiBinder

private EntityTreeBrowser entityTreeBrowser;
private Widget widget;
SynapseReactClientFullContextPropsProvider propsProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consistency nit

Suggested change
SynapseReactClientFullContextPropsProvider propsProvider;
private SynapseReactClientFullContextPropsProvider propsProvider;

private FeatureFlagConfig featureFlagConfig;

@UiField
Div files;
Expand All @@ -39,12 +44,21 @@ public interface FilesBrowserViewImplUiBinder
@UiField
Heading title;

@UiField
Div reactFileBrowserContainer;

CallbackP<String> entityClickedCallback;

@Inject
public FilesBrowserViewImpl(
FilesBrowserViewImplUiBinder binder,
EntityTreeBrowser entityTreeBrowser
EntityTreeBrowser entityTreeBrowser,
SynapseReactClientFullContextPropsProvider propsProvider,
FeatureFlagConfig featureFlagConfig
) {
widget = binder.createAndBindUi(this);
this.featureFlagConfig = featureFlagConfig;
this.propsProvider = propsProvider;
this.entityTreeBrowser = entityTreeBrowser;
Widget etbW = entityTreeBrowser.asWidget();
etbW.addStyleName("margin-top-10");
Expand All @@ -53,15 +67,46 @@ public FilesBrowserViewImpl(

@Override
public void configure(String entityId) {
boolean isReactFileBrowser = featureFlagConfig.isFeatureEnabled(
FeatureFlagKey.REACT_FILE_BROWSER
);
title.setVisible(false);
entityTreeBrowser.configure(entityId);
reactFileBrowserContainer.setVisible(isReactFileBrowser);
files.setVisible(!isReactFileBrowser);
if (isReactFileBrowser) {
rerenderFileBrowser(entityId);
} else {
entityTreeBrowser.configure(entityId);
}
}

public void rerenderFileBrowser(String parentContainerId) {
// TODO: Should not need to remount, but currently the parentContainer is not shown if the existing react component is updated
// TODO: Bug: The tree is not always auto-expanding (to the path to the parent container Id)
reactFileBrowserContainer.clear();
ReactComponent componentContainer = new ReactComponent();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to create a new ReactComponent instance, you should just be able to create one instance and call render on it with the new ReactElement. But it's possible you tried that and it resulted in another bug.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, tried. Noted a couple of bugs in TODO comments that would need to be addressed if we're moving forward with this solution

EntityFileBrowserProps props = EntityFileBrowserProps.create(
parentContainerId,
ref -> {
String entityId = ref.getTargetId();
entityClickedCallback.invoke(entityId);
}
);
ReactElement component = React.createElementWithSynapseContext(
SRC.SynapseComponents.EntityFileBrowser,
props,
propsProvider.getJsInteropContextProps()
);
reactFileBrowserContainer.add(componentContainer);
componentContainer.render(component);
}

@Override
public void setEntityClickedHandler(CallbackP<String> callback) {
this.entityClickedCallback = callback;
entityTreeBrowser.setEntityClickedHandler(entityId -> {
entityTreeBrowser.setLoadingVisible(true);
callback.invoke(entityId);
entityClickedCallback.invoke(entityId);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
/>
</bh:Div>
<bh:Div ui:field="addToDownloadListContainer" />
<bh:Div ui:field="reactFileBrowserContainer" />
<bh:Div
ui:field="files"
styleName="highlight-box padding-top-0-imp overflow-auto"
Expand Down