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
Iframes#978 #984
Iframes#978 #984
Conversation
…n a way that can be used in an iframe
iframe resizer has been added and the ips path for rendering projects in an iframe is implemented. This is ready for merging.
|
I pulled the latest master, and added opensandiego.org to CSP_FRAME_SRC and CSP_FRAME_ANCESTORS in the democracy-lab-dev heroku settings and then deployed it there. It works, and I tested it with the opensandiego.org page to make sure it works. -- but now I have updated the opensandiego page to point to production so it won't show the incorrect info, A better resolution to manually setting the CSP_... env variables would be to ask leader to enter the URL of their web site when they create their groups, and projects, and then automatically add those domains to the CSP variables - but for now the number of sites will be small, and we should get this feature out their and get feedback before making it easier to administer. So I think this is ready to go. |
Dockerfile
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this identical to what's in #982?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It doesn't work for me on windows without this. I think I have gotten a few other people have tried #982 and at least not complained, and had reports of success with the getting started doc too.
@@ -60,7 +60,7 @@ class AboutGroupController extends React.PureComponent<{||}, State> { | |||
|
|||
_renderLoading(): React$Node { | |||
return this.state.statusCode | |||
? this_.renderLoadErrorMessage() | |||
? this._renderLoadErrorMessage() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any change here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It's a bug fix. this_
is undefined and causes an exception when executed. Where as this
is what was intended. I encountered this when testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, keen eye! I looked over this I don't know how many times and didn't notice...
@@ -71,7 +71,7 @@ class ProjectCardsContainer extends React.Component<Props, State> { | |||
</React.Fragment> | |||
) : null} | |||
<div className="row"> | |||
{!_.isEmpty(this.state.projects) && ( | |||
{!_.isEmpty(this.state.projects) && !this.props.supressHeader && ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling, and be sure to add to Props type above
{!_.isEmpty(this.state.projects) && !this.props.supressHeader && ( | |
{!_.isEmpty(this.state.projects) && !this.props.suppressHeader && ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
import type { GroupDetailsAPIData } from "../../utils/GroupAPIUtils.js"; | ||
import ProjectCardsContainer from "../../componentsBySection/FindProjects/ProjectCardsContainer.jsx"; | ||
|
||
class IframeGroupDisplay extends AboutGroupDisplay<Props, State> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this need to inherit from AboutGroupDisplay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function needs to have its own unique name, and would have a lot of code duplicated from AboutGroupDisplay, but the render function is different. Doing it this way eliminates duplicate code.
@@ -108,8 +108,9 @@ class AboutProjectDisplay extends React.PureComponent<Props, State> { | |||
|
|||
render(): React$Node { | |||
const project = this.state.project; | |||
const widthModifier=window.parent !== window ? ' use-parent-width' : ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The window.parent !== window
check is made in a lot of places, it should live in a helper function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isWithinIframe - done.
// iFrameResizer will startup after the page is rendered, so we need to rerener if it does | ||
if(!window.iFrameResizer) window.iFrameResizer={} | ||
if(!window.iFrameResizer.onInParent) window.iFrameResizer.onInParent=[] | ||
window.iFrameResizer.onInParent.push(this.onIframeResizer.bind(this)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should live in a helper function or wrapper component.
Also, don't forget line semicolons!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was an interesting challenge. I created common/components/common/IframeResizerInParent.jsx a wrapper component with static helper functions that cleanly factored this out.
if(!window.iFrameResizer) window.iFrameResizer={} | ||
window.iFrameResizer.inParent=true | ||
let func | ||
while((func=window.iFrameResizer.onInParent?.shift())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this line doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a comment to the code. There could be multiple components needing to be re-rendered after iframe resizer starts, so onInParent is an array of callbacks from those components to run after iframeresizer starts. Components may need to rerender after iframeresizer starts because their style needs to change if rendering in an iframe that resizes v. rendering in an iframe that doesn't resize.
common/components/urls/urls_v2.json
Outdated
@@ -6,6 +6,7 @@ | |||
{"name": "CreateEventProject", "pattern": "events/(?P<event_id>[\\w\\-]+)/projects/create/(?P<project_id>[\\w\\-]*)"}, | |||
{"name": "AboutEventProject", "pattern": "events/(?P<event_id>[\\w\\-]+)/projects/(?P<project_id>[\\w\\-]+)"}, | |||
{"name": "CreateProject", "pattern": "projects/create/(?P<id>[\\w\\-]*)"}, | |||
{"name": "IframeProject", "pattern": "ips/(?P<id>[\\w\\-]+)"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would be for urls of iframe versions of pages to branch off from the main urls.
{"name": "IframeProject", "pattern": "ips/(?P<id>[\\w\\-]+)"}, | |
{"name": "IframeProject", "pattern": "projects/ips/(?P<id>[\\w\\-]+)"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done but its projects/inframe/ and groups/inframe/
iframe-test-resizer.html
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a demonstration file for clients wanting to embed projects/groups? If so, add comments.
Also, these html files should probably live in a separate folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two files are intended for use be developers in unit testing. I couldn't figure out a directory for putting them in. But they should be retained for future testing of this feature. And I will put comments in them explaining that's what the are for.
But how would you feel about a tools
directory at the top level and I would put them in there. It's doesn't feel right to call it a test directory because that kind of implies automated tests. Just leaving them at the root isn't very clean. Or I am open to other ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a tools directory and put them there.
Okay I've made and pushed the changes and this is ready to go. |
{ShowHeadAndFoot && <SponsorFooter key="sponsor_footer" />} | ||
{ShowHeadAndFoot && <SiteFooter key="site_footer" />} | ||
</> | ||
const ShowHeadAndFoot=!(window.location.pathname.includes('/groups/inframe')||window.location.pathname.includes('/projects/inframe')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement is used a couple times, so should live in a helper method. Can also use helper methods to implement the logic.
const ShowHeadAndFoot=!(window.location.pathname.includes('/groups/inframe')||window.location.pathname.includes('/projects/inframe')); | |
const ShowHeadAndFoot=!(urlHelper.atSection(Section.IframeProject)||urlHelper.atSection(Section.IframeGroup)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the change to urlHelper both in this file and in ProjectCard. - but the code is different between the two and a common helper method wasn't possible. Plus both places read well with the urlHelper change. The ProjectCard code looks like this now:
const url: string = (urlHelper.atSection(Section.IframeGroup) && IframeResizerInParent.inParent()) ?
urlHelper.section(Section.IframeProject, {
id: this.props.project.slug || this.props.project.id,
}) :
( this.props.project.cardUrl ||
urlHelper.section(Section.AboutProject, {
id: this.props.project.slug || this.props.project.id,
})
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd rename this file as just iframe.js
so we can have a util file dedicated to iframes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this file? It seems to be just a wrapper around AboutProjectDisplay (which handles the iframe logic internally).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed it and IframeProjectDisplay by the same logic.
I've tested this locally, and pushed it to democracy-lab-dev and am testing it a little more there, but won't finish until tomorrow. |
ok, I'm done with my testing. ready to go. |
Also, please add opensandiego.org to CSP_FRAME_SRC and CSP_FRAME_ANCESTORS in the environment settings after you push to production. |
More specifically in democracy-lab-dev I have:
I remember it didn't work without the https:// in front for CSP_FRAME_ANCESTORS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made some comments on testing issues I've found, mostly on very small or very large devices. It's not exhaustive so please be sure to take a look at the whole layout on any test deployments (e.g. open san diego) on the whole range of small to very large viewports -- I'm sure there's going to be issues I didn't encounter using the test html files provided.
Broadly, dlab's site when displayed natively supports a mobile minimum of 360px device width up to a maximum viewport of 1440px (at which point the content is 1392px width and does not expand further) -- so please use those as your test boundaries for displaying dlab in a frame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have 3 pending comments so I am doing this to submit them.
With this new push, I think this is ready to go.
Approved all the parts of my review. Anything from your review, Marlon, I left alone. |
@marlonkeating I should have thought of this earlier. I create a test server on heroku to use the iframe feature. This will test the feature: https://dlab-iframe-test-0ac0b57c4ba3.herokuapp.com/ |
update to above:
|
let _args: Dictionary<string> = { | ||
prev: sectionArgs.section, | ||
prev: sectionArgs.section!==Section.IframeProject ? sectionArgs.section : Section.AboutProject, // if login from within an iframe, go direct without iframe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to have the same logic for groups?
Also, be sure to add new logInThenReturn
unit tests to
test("logInThenReturn produces correct redirection urls", () => { |
Also - one issue. The path is /igs instead of /igroups as was in the spec. The problem is that I originally tried to do this as a sitemap - using igroups modeled after the groups path. But I learned it's better to do it as just a path. BUT even after deleting all the code around the /igroups path - it still routs to that path. It seems to be cached somethere that I haven't figures out yet. So I can't change the path to /igroups and get it to run my code. Any ideas?
If you build this code and run it locally, then you can brows to the file
./iframe-test.html
and it will load the projects as an iframe:There might also be a better place to put that test file than root - I'm open to where.