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-7100: add a new TrustCenterView, and rely on a new SRC component … #5537

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -250,6 +250,9 @@ protected void configure() {
bind(HelpView.class).to(HelpViewImpl.class).in(Singleton.class);
// SearchView
bind(SearchView.class).to(SearchViewImpl.class).in(Singleton.class);
bind(TrustCenterView.class)
.to(TrustCenterViewImpl.class)
.in(Singleton.class);

// Down
bind(DownView.class).to(DownViewImpl.class).in(Singleton.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sagebionetworks.web.client.jsinterop;

import jsinterop.annotations.JsNullable;
import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;

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

@JsNullable
public String repoOwner;

@JsNullable
public String repoName;

@JsNullable
public String filePath;

@JsOverlay
public static MarkdownGithubProps create(
String repoOwner,
String repoName,
String filePath
) {
MarkdownGithubProps props = new MarkdownGithubProps();
props.repoOwner = repoOwner;
props.repoName = repoName;
props.filePath = filePath;
return props;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public static class SynapseComponents {
public static ReactComponentType<
RejectProfileValidationRequestModalProps
> RejectProfileValidationRequestModal;
public static ReactComponentType<MarkdownGithubProps> MarkdownGithub;

/**
* Pushes a global toast message. In SWC, you should use {@link DisplayUtils#notify}, rather than calling this method directly.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,49 @@

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import org.sagebionetworks.web.client.RequestBuilderWrapper;
import org.sagebionetworks.web.client.PopupUtilsView;
import org.sagebionetworks.web.client.place.TrustCenterPlace;
import org.sagebionetworks.web.client.view.MapView;
import org.sagebionetworks.web.client.view.SynapseStandaloneWikiView;
import org.sagebionetworks.web.client.widget.entity.controller.SynapseAlert;
import org.sagebionetworks.web.shared.WebConstants;
import org.sagebionetworks.web.client.view.TrustCenterView;

public class TrustCenterPresenter
extends AbstractActivity
implements
Presenter<org.sagebionetworks.web.client.place.TrustCenterPlace>,
MapView.Presenter {

SynapseStandaloneWikiView view;
RequestBuilderWrapper requestBuilder;
SynapseAlert synAlert;
TrustCenterView view;
PopupUtilsView popupUtils;

private static Map<String, String> documentKeyToGithubUrl = new HashMap<>();
private static Map<String, String> documentKeyToGithubFilename =
new HashMap<>();
public static String REPO_OWNER = "Sage-Bionetworks";
public static String REPO_NAME = "Sage-Governance-Documents";

static {
documentKeyToGithubUrl.put(
documentKeyToGithubFilename.put(
TrustCenterPlace.TERMS_OF_SERVICE_KEY,
"https://raw.githubusercontent.com/Sage-Bionetworks/Sage-Governance-Documents/main/Terms.md"
"Terms.md"
);
documentKeyToGithubUrl.put(
documentKeyToGithubFilename.put(
TrustCenterPlace.PRIVACY_POLICY_KEY,
"https://raw.githubusercontent.com/Sage-Bionetworks/Sage-Governance-Documents/main/privacy.md"
"privacy.md"
);
documentKeyToGithubUrl.put(
TrustCenterPlace.COOKIES_KEY,
"https://raw.githubusercontent.com/Sage-Bionetworks/Sage-Governance-Documents/main/cookies.md"
);
documentKeyToGithubUrl.put(
documentKeyToGithubFilename.put(TrustCenterPlace.COOKIES_KEY, "cookies.md");
documentKeyToGithubFilename.put(
TrustCenterPlace.SUBPROCESSORS_KEY,
"https://raw.githubusercontent.com/Sage-Bionetworks/Sage-Governance-Documents/main/subprocessors.md"
"subprocessors.md"
);
}

@Inject
public TrustCenterPresenter(
SynapseStandaloneWikiView view,
RequestBuilderWrapper requestBuilder,
SynapseAlert synAlert
) {
public TrustCenterPresenter(TrustCenterView view, PopupUtilsView popupUtils) {
this.view = view;
this.requestBuilder = requestBuilder;
this.synAlert = synAlert;
view.setSynAlert(synAlert);
this.popupUtils = popupUtils;
}

@Override
Expand All @@ -69,53 +56,12 @@ public void start(AcceptsOneWidget panel, EventBus eventBus) {
public void setPlace(
org.sagebionetworks.web.client.place.TrustCenterPlace place
) {
synAlert.clear();
String documentKey = place.getDocumentKey();
String documentUrl = documentKeyToGithubUrl.get(documentKey);
if (documentUrl == null) {
synAlert.showError("Unrecognized document key: " + documentKey);
String fileName = documentKeyToGithubFilename.get(documentKey);
if (fileName == null) {
popupUtils.showErrorMessage("Unrecognized document key: " + documentKey);
} else {
showFileContent(documentUrl);
}
}

public void showFileContent(String url) {
requestBuilder.configure(RequestBuilder.GET, url);
requestBuilder.setHeader(
WebConstants.CONTENT_TYPE,
WebConstants.TEXT_PLAIN_CHARSET_UTF8
);
try {
requestBuilder.sendRequest(
null,
new RequestCallback() {
@Override
public void onResponseReceived(Request request, Response response) {
int statusCode = response.getStatusCode();
if (statusCode == Response.SC_OK) {
String md = response.getText();
view.configure(md);
} else {
onError(
null,
new IllegalArgumentException(
"Unable to retrieve file content " +
url +
". Reason: " +
response.getStatusText()
)
);
}
}

@Override
public void onError(Request request, Throwable exception) {
synAlert.handleException(exception);
}
}
);
} catch (final Exception e) {
synAlert.handleException(e);
view.render(REPO_OWNER, REPO_NAME, fileName);
}
}

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

import com.google.gwt.user.client.ui.IsWidget;

public interface TrustCenterView extends IsWidget {
void render(String repoOwner, String repoName, String filePath);

void refresh();

void scrollToTop();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.sagebionetworks.web.client.view;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.inject.Inject;
import org.sagebionetworks.web.client.context.SynapseReactClientFullContextPropsProvider;
import org.sagebionetworks.web.client.jsinterop.MarkdownGithubProps;
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.widget.ReactComponent;
import org.sagebionetworks.web.client.widget.header.Header;

public class TrustCenterViewImpl extends Composite implements TrustCenterView {

ReactComponent container = new ReactComponent();

private Header headerWidget;
private SynapseReactClientFullContextPropsProvider propsProvider;

@Inject
public TrustCenterViewImpl(
Header headerWidget,
final SynapseReactClientFullContextPropsProvider propsProvider
) {
initWidget(container);

this.headerWidget = headerWidget;
this.propsProvider = propsProvider;
headerWidget.configure();
}

@Override
public void render(String repoOwner, String repoName, String filePath) {
scrollToTop();
ReactElement component;

MarkdownGithubProps props = MarkdownGithubProps.create(
repoOwner,
repoName,
filePath
);
component =
React.createElementWithSynapseContext(
SRC.SynapseComponents.MarkdownGithub,
props,
propsProvider.getJsInteropContextProps()
);

container.render(component);
}

@Override
public void refresh() {
headerWidget.configure();
headerWidget.refresh();
}

@Override
public void scrollToTop() {
Window.scrollTo(0, 0);
}
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,27 @@
package org.sagebionetworks.web.unitclient.presenter;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.sagebionetworks.web.client.RequestBuilderWrapper;
import org.sagebionetworks.web.client.PopupUtilsView;
import org.sagebionetworks.web.client.place.TrustCenterPlace;
import org.sagebionetworks.web.client.presenter.TrustCenterPresenter;
import org.sagebionetworks.web.client.view.SynapseStandaloneWikiView;
import org.sagebionetworks.web.client.widget.entity.controller.SynapseAlert;
import org.sagebionetworks.web.shared.WebConstants;
import org.sagebionetworks.web.test.helper.RequestBuilderMockStubber;
import org.sagebionetworks.web.client.view.TrustCenterView;

public class TrustCenterPresenterTest {

@Mock
SynapseStandaloneWikiView mockView;
TrustCenterView mockView;

@Mock
RequestBuilderWrapper mockRequestBuilder;

@Mock
Response mockResponse;

@Mock
SynapseAlert mockSynAlert;
PopupUtilsView mockPopupUtils;

@Mock
TrustCenterPlace mockPlace;
Expand All @@ -45,62 +31,31 @@ public class TrustCenterPresenterTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
presenter =
new TrustCenterPresenter(mockView, mockRequestBuilder, mockSynAlert);
presenter = new TrustCenterPresenter(mockView, mockPopupUtils);
}

@Test
public void testValidDocumentKey() throws RequestException {
when(mockResponse.getStatusCode()).thenReturn(Response.SC_OK);
String markdown = "Privacy Policy **markdown**";
when(mockResponse.getText()).thenReturn(markdown);
RequestBuilderMockStubber
.callOnResponseReceived(null, mockResponse)
.when(mockRequestBuilder)
.sendRequest(any(), any());
when(mockPlace.getDocumentKey())
.thenReturn(TrustCenterPlace.PRIVACY_POLICY_KEY);

presenter.setPlace(mockPlace);

verify(mockSynAlert, atLeastOnce()).clear();
verify(mockRequestBuilder).configure(eq(RequestBuilder.GET), anyString());
verify(mockRequestBuilder)
.setHeader(
WebConstants.CONTENT_TYPE,
WebConstants.TEXT_PLAIN_CHARSET_UTF8
verify(mockPopupUtils, never()).showErrorMessage(anyString());
verify(mockView)
.render(
TrustCenterPresenter.REPO_OWNER,
TrustCenterPresenter.REPO_NAME,
"privacy.md"
);
verify(mockSynAlert, never()).handleException(any(Throwable.class));
verify(mockView).configure(markdown);
}

@Test
public void testInvalidDocumentKey() throws RequestException {
when(mockResponse.getStatusCode()).thenReturn(Response.SC_OK);
when(mockPlace.getDocumentKey()).thenReturn("Invalid Key");

presenter.setPlace(mockPlace);

verify(mockSynAlert, atLeastOnce()).clear();
verify(mockSynAlert).showError(any());
verify(mockRequestBuilder, never())
.configure(eq(RequestBuilder.GET), any());
}

@Test
public void testUnableToGetMarkdown() throws RequestException {
when(mockResponse.getStatusCode()).thenReturn(Response.SC_OK);
when(mockPlace.getDocumentKey())
.thenReturn(TrustCenterPlace.PRIVACY_POLICY_KEY);
RequestBuilderMockStubber
.callOnError(null, new Exception())
.when(mockRequestBuilder)
.sendRequest(any(), any());

presenter.setPlace(mockPlace);

verify(mockRequestBuilder).configure(eq(RequestBuilder.GET), any());
verify(mockSynAlert, atLeastOnce()).clear();
verify(mockSynAlert).handleException(any());
verify(mockPopupUtils).showErrorMessage(anyString());
}
}