From 8b9dd90ae38fcd029d83b7ed3d8cbd0bc216f235 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Thu, 6 Aug 2020 15:59:22 -0300 Subject: [PATCH 01/27] :construction: make component --- client/components/Dropdown.jsx | 2 +- client/components/Sidebar.jsx | 43 ++++++++++++++++++++++ client/components/useAsModal.jsx | 1 + client/modules/IDE/pages/MobileIDEView.jsx | 30 +++++++++++---- 4 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 client/components/Sidebar.jsx diff --git a/client/components/Dropdown.jsx b/client/components/Dropdown.jsx index bd2169b8..48bed0cb 100644 --- a/client/components/Dropdown.jsx +++ b/client/components/Dropdown.jsx @@ -25,7 +25,7 @@ const DropdownWrapper = styled.ul` display: flex; flex-direction: column; height: auto; - z-index: 9999; + z-index: 2; border-radius: ${remSize(6)}; & li:first-child { border-radius: ${remSize(5)} ${remSize(5)} 0 0; } diff --git a/client/components/Sidebar.jsx b/client/components/Sidebar.jsx new file mode 100644 index 00000000..93bba04d --- /dev/null +++ b/client/components/Sidebar.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link } from 'react-router'; +import styled from 'styled-components'; +import { remSize, prop, common } from '../theme'; +import Header from './mobile/Header'; +import IconButton from './mobile/IconButton'; +import { ExitIcon } from '../common/icons'; + + +const SidebarWrapper = styled.div` + height: 100%; + width: ${remSize(180)}; + + position: absolute; + z-index: 2; + left: 0; + + background: white; + box-shadow: 0 6px 6px 0 rgba(0,0,0,0.10); +`; + +const Sidebar = ({ title, onPressClose }) => ( + + {title && +
+ +
} +
+); + +Sidebar.propTypes = { + title: PropTypes.string, + onPressClose: PropTypes.func.isRequired, +}; + +Sidebar.defaultProps = { + title: null, + // onPressClose: PropTypes.func.isRequired, +}; + + +export default Sidebar; diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 1afa0d30..5dbeb82a 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { useModalBehavior } from '../utils/custom-hooks'; + export default (component) => { const [visible, trigger, setRef] = useModalBehavior(); diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index c33c6cda..3d48f7f9 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -34,6 +34,7 @@ import ActionStrip from '../../../components/mobile/ActionStrip'; import useAsModal from '../../../components/useAsModal'; import { PreferencesIcon } from '../../../common/icons'; import Dropdown from '../../../components/Dropdown'; +import Sidebar from '../../../components/Sidebar'; const isUserOwner = ({ project, user }) => project.owner && project.owner.id === user.id; @@ -67,18 +68,13 @@ const MobileIDEView = (props) => { selectedFile, updateFileContent, files, user, params, closeEditorOptions, showEditorOptions, startRefreshSketch, stopSketch, expandSidebar, collapseSidebar, clearConsole, console, - showRuntimeErrorWarning, hideRuntimeErrorWarning, startSketch, getProject, clearPersistedState + showRuntimeErrorWarning, hideRuntimeErrorWarning, startSketch, getProject, clearPersistedState, setUnsavedChanges } = props; const [tmController, setTmController] = useState(null); // eslint-disable-line const { username } = user; - const [triggerNavDropdown, NavDropDown] = useAsModal(); - // Force state reset useEffect(clearPersistedState, []); useEffect(stopSketch, []); @@ -95,16 +91,34 @@ const MobileIDEView = (props) => { setCurrentProjectID(params.project_id); }, [params, project, username]); + const [toggleNavDropdown, NavDropDown] = useAsModal(); + + const [toggleExplorer, Explorer] = useAsModal( {}} + />); + + // toggle sidebar starting opened + useEffect(toggleExplorer, []); return ( +
+ @@ -147,6 +161,7 @@ const MobileIDEView = (props) => { hideRuntimeErrorWarning={hideRuntimeErrorWarning} runtimeErrorWarningVisible={ide.runtimeErrorWarningVisible} provideController={setTmController} + setUnsavedChanges={setUnsavedChanges} /> @@ -267,6 +282,7 @@ MobileIDEView.propTypes = { username: PropTypes.string, }).isRequired, + setUnsavedChanges: PropTypes.func.isRequired, getProject: PropTypes.func.isRequired, clearPersistedState: PropTypes.func.isRequired, params: PropTypes.shape({ From 1680c0cd52e177516dd6d6acc0dd76aba2be7afe Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Thu, 6 Aug 2020 16:05:28 -0300 Subject: [PATCH 02/27] :construction: add background overlay to modals --- client/components/useAsModal.jsx | 21 +++++++++++++++++---- client/modules/IDE/pages/MobileIDEView.jsx | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 5dbeb82a..4e124435 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -1,11 +1,24 @@ import React from 'react'; +import styled from 'styled-components'; import { useModalBehavior } from '../utils/custom-hooks'; +const BackgroundOverlay = styled.div` + position: absolute; + z-index: 2; + width: 100% !important; + height: 100% !important; + + background: black; + opacity: 0.3; +`; -export default (component) => { - const [visible, trigger, setRef] = useModalBehavior(); +export default (component, hasOverlay = false) => { + const [visible, toggle, setRef] = useModalBehavior(); - const wrapper = () =>
{visible && component}
; // eslint-disable-line + const wrapper = () => (
+ {hasOverlay && visible && } +
{visible && component}
+
); // eslint-disable-line - return [trigger, wrapper]; + return [toggle, wrapper]; }; diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index 3d48f7f9..a008c079 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -99,7 +99,7 @@ const MobileIDEView = (props) => { const [toggleExplorer, Explorer] = useAsModal( {}} - />); + />, true); // toggle sidebar starting opened useEffect(toggleExplorer, []); From 6d121491aaa0f434e99e1b44487c73195d30beed Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Thu, 6 Aug 2020 16:24:47 -0300 Subject: [PATCH 03/27] :construction: improve useAsModal rendering --- client/components/Sidebar.jsx | 2 +- client/components/mobile/Header.jsx | 10 ++++++---- client/components/useAsModal.jsx | 13 ++++++++----- client/modules/IDE/pages/MobileIDEView.jsx | 3 +-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/client/components/Sidebar.jsx b/client/components/Sidebar.jsx index 93bba04d..962cff36 100644 --- a/client/components/Sidebar.jsx +++ b/client/components/Sidebar.jsx @@ -23,7 +23,7 @@ const SidebarWrapper = styled.div` const Sidebar = ({ title, onPressClose }) => ( {title && -
+
} diff --git a/client/components/mobile/Header.jsx b/client/components/mobile/Header.jsx index cb6702ed..7b3fbae1 100644 --- a/client/components/mobile/Header.jsx +++ b/client/components/mobile/Header.jsx @@ -14,7 +14,7 @@ const textColor = ({ transparent, inverted }) => prop((transparent === false && const HeaderDiv = styled.div` - position: fixed; + ${props => props.fixed && 'position: fixed;'} width: 100%; background: ${props => background(props)}; color: ${textColor}; @@ -57,9 +57,9 @@ const TitleContainer = styled.div` const Header = ({ title, subtitle, leftButton, children, - transparent, inverted, slim + transparent, inverted, slim, fixed }) => ( - + {leftButton} {title &&

{title}

} @@ -79,6 +79,7 @@ Header.propTypes = { transparent: PropTypes.bool, inverted: PropTypes.bool, slim: PropTypes.bool, + fixed: PropTypes.bool, }; Header.defaultProps = { @@ -88,7 +89,8 @@ Header.defaultProps = { children: [], transparent: false, inverted: false, - slim: false + slim: false, + fixed: true }; export default Header; diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 4e124435..52d2fc00 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -12,13 +12,16 @@ const BackgroundOverlay = styled.div` opacity: 0.3; `; -export default (component, hasOverlay = false) => { +export default (Element, hasOverlay = false) => { const [visible, toggle, setRef] = useModalBehavior(); - const wrapper = () => (
- {hasOverlay && visible && } -
{visible && component}
-
); // eslint-disable-line + // const Comp = styled(() => Element).attrs({ onPressClose: toggle }); + + const wrapper = () => (visible && +
+ {hasOverlay && } +
{Element}
+
); // eslint-disable-line} return [toggle, wrapper]; }; diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index a008c079..780edba0 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -97,8 +97,7 @@ const MobileIDEView = (props) => { />); const [toggleExplorer, Explorer] = useAsModal( {}} + title="Files" />, true); // toggle sidebar starting opened From d1b4d8d4e38da4fa3e83877f2c8228e4112bcf9f Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 11:24:25 -0300 Subject: [PATCH 04/27] :broom: remove eslint-disable-line --- client/components/useAsModal.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 52d2fc00..a8f4d7d1 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -21,7 +21,7 @@ export default (Element, hasOverlay = false) => {
{hasOverlay && }
{Element}
-
); // eslint-disable-line} + ); return [toggle, wrapper]; }; From dfedc81f66dda165fdd633e87185e83cdc1516b0 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 14:09:17 -0300 Subject: [PATCH 05/27] :sparkles: add files tab --- client/components/mobile/Explorer.jsx | 22 ++++++++++++++++++ client/components/{ => mobile}/Sidebar.jsx | 17 ++++++++------ client/modules/IDE/pages/MobileIDEView.jsx | 26 ++++++++++++++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 client/components/mobile/Explorer.jsx rename client/components/{ => mobile}/Sidebar.jsx (62%) diff --git a/client/components/mobile/Explorer.jsx b/client/components/mobile/Explorer.jsx new file mode 100644 index 00000000..6d4965b3 --- /dev/null +++ b/client/components/mobile/Explorer.jsx @@ -0,0 +1,22 @@ +import React from 'react'; +import styled from 'styled-components'; +import PropTypes from 'prop-types'; +import Sidebar from './Sidebar'; +import ConnectedFileNode from '../../modules/IDE/components/FileNode'; + + +const Explorer = ({ id, canEdit }) => ( + + + +); + +Explorer.propTypes = { + id: PropTypes.number.isRequired, + canEdit: PropTypes.bool +}; +Explorer.defaultProps = { + canEdit: false +}; + +export default Explorer; diff --git a/client/components/Sidebar.jsx b/client/components/mobile/Sidebar.jsx similarity index 62% rename from client/components/Sidebar.jsx rename to client/components/mobile/Sidebar.jsx index 962cff36..4e2cfda9 100644 --- a/client/components/Sidebar.jsx +++ b/client/components/mobile/Sidebar.jsx @@ -2,10 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Link } from 'react-router'; import styled from 'styled-components'; -import { remSize, prop, common } from '../theme'; -import Header from './mobile/Header'; -import IconButton from './mobile/IconButton'; -import { ExitIcon } from '../common/icons'; +import { remSize, prop, common } from '../../theme'; +import Header from './Header'; +import IconButton from './IconButton'; +import { ExitIcon } from '../../common/icons'; const SidebarWrapper = styled.div` @@ -20,23 +20,26 @@ const SidebarWrapper = styled.div` box-shadow: 0 6px 6px 0 rgba(0,0,0,0.10); `; -const Sidebar = ({ title, onPressClose }) => ( +const Sidebar = ({ title, onPressClose, children }) => ( {title &&
} + {children}
); Sidebar.propTypes = { title: PropTypes.string, - onPressClose: PropTypes.func.isRequired, + onPressClose: PropTypes.func, + children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]), }; Sidebar.defaultProps = { title: null, - // onPressClose: PropTypes.func.isRequired, + children: [], + onPressClose: () => {} }; diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index 780edba0..9bad5903 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -27,6 +27,7 @@ import Header from '../../../components/mobile/Header'; import Screen from '../../../components/mobile/MobileScreen'; import Footer from '../../../components/mobile/Footer'; import IDEWrapper from '../../../components/mobile/IDEWrapper'; +import MobileExplorer from '../../../components/mobile/Explorer'; import Console from '../components/Console'; import { remSize } from '../../../theme'; // import OverlayManager from '../../../components/OverlayManager'; @@ -34,11 +35,28 @@ import ActionStrip from '../../../components/mobile/ActionStrip'; import useAsModal from '../../../components/useAsModal'; import { PreferencesIcon } from '../../../common/icons'; import Dropdown from '../../../components/Dropdown'; -import Sidebar from '../../../components/Sidebar'; +import Sidebar from '../../../components/mobile/Sidebar'; + + +const getRootFile = files => files && files.filter(file => file.name === 'root')[0]; +const getRootFileID = files => (root => root && root.id)(getRootFile(files)); const isUserOwner = ({ project, user }) => project.owner && project.owner.id === user.id; + +// const userCanEditProject = (props) => { +// let canEdit; +// if (!props.owner) { +// canEdit = true; +// } else if (props.user.authenticated && props.owner.id === props.user.id) { +// canEdit = true; +// } else { +// canEdit = false; +// } +// return canEdit; +// }; + const Expander = styled.div` height: ${props => (props.expanded ? remSize(160) : remSize(27))}; `; @@ -75,6 +93,7 @@ const MobileIDEView = (props) => { const { username } = user; + // Force state reset useEffect(clearPersistedState, []); useEffect(stopSketch, []); @@ -91,14 +110,13 @@ const MobileIDEView = (props) => { setCurrentProjectID(params.project_id); }, [params, project, username]); + // Screen Modals const [toggleNavDropdown, NavDropDown] = useAsModal(); - const [toggleExplorer, Explorer] = useAsModal(, true); + const [toggleExplorer, Explorer] = useAsModal(, true); // toggle sidebar starting opened useEffect(toggleExplorer, []); From 34be0e700de8c47c2efe6f6e7df30ad5055dcbff Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 14:17:26 -0300 Subject: [PATCH 06/27] :sparkles: add visibility padding to the bottom of the editor wrapper --- client/components/mobile/IDEWrapper.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/components/mobile/IDEWrapper.jsx b/client/components/mobile/IDEWrapper.jsx index 0982cf81..5e66ee01 100644 --- a/client/components/mobile/IDEWrapper.jsx +++ b/client/components/mobile/IDEWrapper.jsx @@ -2,7 +2,10 @@ import React from 'react'; import styled from 'styled-components'; import { remSize } from '../../theme'; +// Applies padding to top and bottom so editor content is always visible + export default styled.div` z-index: 0; margin-top: ${remSize(16)}; + .CodeMirror-sizer > * { padding-bottom: ${remSize(320)}; }; `; From 81ad78ba79c45331de154310d1d1ae1eec4f7039 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 15:03:18 -0300 Subject: [PATCH 07/27] :sparkles: add floating button to open files tab --- client/common/icons.jsx | 8 +++++ client/components/mobile/FloatingNav.jsx | 40 ++++++++++++++++++++++ client/images/circle-folder.svg | 5 +++ client/images/circle-info.svg | 4 +++ client/images/circle-terminal.svg | 6 ++++ client/modules/App/App.jsx | 4 ++- client/modules/IDE/pages/MobileIDEView.jsx | 22 ++++++------ 7 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 client/components/mobile/FloatingNav.jsx create mode 100644 client/images/circle-folder.svg create mode 100644 client/images/circle-info.svg create mode 100644 client/images/circle-terminal.svg diff --git a/client/common/icons.jsx b/client/common/icons.jsx index 215083a6..b03c3c0f 100644 --- a/client/common/icons.jsx +++ b/client/common/icons.jsx @@ -16,6 +16,10 @@ import More from '../images/more.svg'; import Code from '../images/code.svg'; import Terminal from '../images/terminal.svg'; +import CircleTerminal from '../images/circle-terminal.svg'; +import CircleFolder from '../images/circle-folder.svg'; +import CircleInfo from '../images/circle-info.svg'; + // HOC that adds the right web accessibility props // https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html @@ -81,3 +85,7 @@ export const PlayIcon = withLabel(Play); export const MoreIcon = withLabel(More); export const TerminalIcon = withLabel(Terminal); export const CodeIcon = withLabel(Code); + +export const CircleTerminalIcon = withLabel(CircleTerminal); +export const CircleFolderIcon = withLabel(CircleFolder); +export const CircleInfoIcon = withLabel(CircleInfo); diff --git a/client/components/mobile/FloatingNav.jsx b/client/components/mobile/FloatingNav.jsx new file mode 100644 index 00000000..ca8220f7 --- /dev/null +++ b/client/components/mobile/FloatingNav.jsx @@ -0,0 +1,40 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; +import { remSize } from '../../theme'; +import Button from '../../common/Button'; +import IconButton from './IconButton'; + +const FloatingContainer = styled.div` + position: absolute; + right: ${remSize(16)}; + top: ${remSize(80)}; + + text-align: right; + z-index: 3; +`; + +const FloatingNav = ({ items }) => ( + + { items.map(({ icon, onPress }) => + ( + + ))} + +); + +FloatingNav.propTypes = { + items: PropTypes.arrayOf(PropTypes.shape({ + icon: PropTypes.element, + onPress: PropTypes.func + })) +}; + +FloatingNav.defaultProps = { + items: [] +}; + +export default FloatingNav; diff --git a/client/images/circle-folder.svg b/client/images/circle-folder.svg new file mode 100644 index 00000000..ab2076b9 --- /dev/null +++ b/client/images/circle-folder.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/client/images/circle-info.svg b/client/images/circle-info.svg new file mode 100644 index 00000000..ed75766b --- /dev/null +++ b/client/images/circle-info.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/images/circle-terminal.svg b/client/images/circle-terminal.svg new file mode 100644 index 00000000..168efd85 --- /dev/null +++ b/client/images/circle-terminal.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/client/modules/App/App.jsx b/client/modules/App/App.jsx index af441a9d..96013836 100644 --- a/client/modules/App/App.jsx +++ b/client/modules/App/App.jsx @@ -34,7 +34,9 @@ class App extends React.Component { render() { return (
- {this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && } +
+ {this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && } +
{this.props.children}
); diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index 9bad5903..2d6fb526 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -20,7 +20,7 @@ import { getHTMLFile } from '../reducers/files'; // Local Imports import Editor from '../components/Editor'; -import { PlayIcon, MoreIcon } from '../../../common/icons'; +import { PlayIcon, MoreIcon, CircleFolderIcon } from '../../../common/icons'; import IconButton from '../../../components/mobile/IconButton'; import Header from '../../../components/mobile/Header'; @@ -30,12 +30,12 @@ import IDEWrapper from '../../../components/mobile/IDEWrapper'; import MobileExplorer from '../../../components/mobile/Explorer'; import Console from '../components/Console'; import { remSize } from '../../../theme'; -// import OverlayManager from '../../../components/OverlayManager'; + import ActionStrip from '../../../components/mobile/ActionStrip'; import useAsModal from '../../../components/useAsModal'; import { PreferencesIcon } from '../../../common/icons'; import Dropdown from '../../../components/Dropdown'; -import Sidebar from '../../../components/mobile/Sidebar'; +import FloatingNav from '../../../components/mobile/FloatingNav'; const getRootFile = files => files && files.filter(file => file.name === 'root')[0]; @@ -65,7 +65,7 @@ const NavItem = styled.li` position: relative; `; -const getNatOptions = (username = undefined) => +const getNavOptions = (username = undefined) => (username ? [ { icon: PreferencesIcon, title: 'Preferences', href: '/mobile/preferences', }, @@ -112,14 +112,18 @@ const MobileIDEView = (props) => { // Screen Modals const [toggleNavDropdown, NavDropDown] = useAsModal(); + const [toggleExplorer, Explorer] = useAsModal(, true); // toggle sidebar starting opened - useEffect(toggleExplorer, []); + // useEffect(toggleExplorer, []); + + const floatingNavOptions = + [{ icon: CircleFolderIcon, onPress: toggleExplorer }]; return ( @@ -129,11 +133,6 @@ const MobileIDEView = (props) => { subtitle={selectedFile.name} > - { provideController={setTmController} setUnsavedChanges={setUnsavedChanges} /> +
From 6fa1b2361348c7e1008ac02534d56e424bf775d0 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 15:25:41 -0300 Subject: [PATCH 08/27] :lipstick: update floating nav button color --- client/components/mobile/FloatingNav.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/components/mobile/FloatingNav.jsx b/client/components/mobile/FloatingNav.jsx index ca8220f7..094a481e 100644 --- a/client/components/mobile/FloatingNav.jsx +++ b/client/components/mobile/FloatingNav.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; -import { remSize } from '../../theme'; +import { remSize, prop } from '../../theme'; import Button from '../../common/Button'; import IconButton from './IconButton'; @@ -12,6 +12,9 @@ const FloatingContainer = styled.div` text-align: right; z-index: 3; + + svg { width: ${remSize(32)}; }; + svg > path { fill: ${prop('Button.default.background')} !important }; `; const FloatingNav = ({ items }) => ( From faaa6d2edbcd88e26c6c7d3d6dd0835ffaa7671b Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 18:32:50 -0300 Subject: [PATCH 09/27] :sparkles: make sidebar close via hook toggle --- client/components/mobile/Explorer.jsx | 10 ++++++---- client/components/mobile/Sidebar.jsx | 4 +++- client/components/useAsModal.jsx | 6 +++++- client/modules/IDE/pages/MobileIDEView.jsx | 8 ++++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/client/components/mobile/Explorer.jsx b/client/components/mobile/Explorer.jsx index 6d4965b3..4e1e902f 100644 --- a/client/components/mobile/Explorer.jsx +++ b/client/components/mobile/Explorer.jsx @@ -5,18 +5,20 @@ import Sidebar from './Sidebar'; import ConnectedFileNode from '../../modules/IDE/components/FileNode'; -const Explorer = ({ id, canEdit }) => ( - - +const Explorer = ({ id, canEdit, onPressClose }) => ( + + ); Explorer.propTypes = { id: PropTypes.number.isRequired, + onPressClose: PropTypes.func, canEdit: PropTypes.bool }; Explorer.defaultProps = { - canEdit: false + canEdit: false, + onPressClose: () => {} }; export default Explorer; diff --git a/client/components/mobile/Sidebar.jsx b/client/components/mobile/Sidebar.jsx index 4e2cfda9..5e872699 100644 --- a/client/components/mobile/Sidebar.jsx +++ b/client/components/mobile/Sidebar.jsx @@ -20,11 +20,13 @@ const SidebarWrapper = styled.div` box-shadow: 0 6px 6px 0 rgba(0,0,0,0.10); `; +// onClick={() => alert('haha')} + const Sidebar = ({ title, onPressClose, children }) => ( {title &&
- +
} {children}
diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index a8f4d7d1..ca69fc8d 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -20,7 +20,11 @@ export default (Element, hasOverlay = false) => { const wrapper = () => (visible &&
{hasOverlay && } -
{Element}
+
+ { (typeof (Element) === 'function') + ? Element(toggle) + : Element} +
); return [toggle, wrapper]; diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index 2d6fb526..c398f6b0 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -116,8 +116,12 @@ const MobileIDEView = (props) => { align="right" />); - - const [toggleExplorer, Explorer] = useAsModal(, true); + const [toggleExplorer, Explorer] = useAsModal(toggle => + (), true); // toggle sidebar starting opened // useEffect(toggleExplorer, []); From df5ac3fb4cbfe20a08c4e2c987eb7c3bd93ea675 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Fri, 7 Aug 2020 18:48:39 -0300 Subject: [PATCH 10/27] :sparkles: make sidebar close on file click --- client/components/mobile/Explorer.jsx | 2 +- client/components/mobile/Sidebar.jsx | 2 -- client/components/useAsModal.jsx | 2 -- client/modules/IDE/components/FileNode.jsx | 15 +++++++++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/client/components/mobile/Explorer.jsx b/client/components/mobile/Explorer.jsx index 4e1e902f..40455e24 100644 --- a/client/components/mobile/Explorer.jsx +++ b/client/components/mobile/Explorer.jsx @@ -7,7 +7,7 @@ import ConnectedFileNode from '../../modules/IDE/components/FileNode'; const Explorer = ({ id, canEdit, onPressClose }) => ( - + onPressClose()} /> ); diff --git a/client/components/mobile/Sidebar.jsx b/client/components/mobile/Sidebar.jsx index 5e872699..cefd46bd 100644 --- a/client/components/mobile/Sidebar.jsx +++ b/client/components/mobile/Sidebar.jsx @@ -20,8 +20,6 @@ const SidebarWrapper = styled.div` box-shadow: 0 6px 6px 0 rgba(0,0,0,0.10); `; -// onClick={() => alert('haha')} - const Sidebar = ({ title, onPressClose, children }) => ( {title && diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index ca69fc8d..092550e4 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -15,8 +15,6 @@ const BackgroundOverlay = styled.div` export default (Element, hasOverlay = false) => { const [visible, toggle, setRef] = useModalBehavior(); - // const Comp = styled(() => Element).attrs({ onPressClose: toggle }); - const wrapper = () => (visible &&
{hasOverlay && } diff --git a/client/modules/IDE/components/FileNode.jsx b/client/modules/IDE/components/FileNode.jsx index e7869f26..d0a10ef8 100644 --- a/client/modules/IDE/components/FileNode.jsx +++ b/client/modules/IDE/components/FileNode.jsx @@ -108,10 +108,15 @@ export class FileNode extends React.Component { handleFileClick = (event) => { event.stopPropagation(); const { isDeleting } = this.state; - const { id, setSelectedFile, name } = this.props; + const { + id, setSelectedFile, name, onClickFile + } = this.props; if (name !== 'root' && !isDeleting) { setSelectedFile(id); } + + // debugger; // eslint-disable-line + if (onClickFile) { onClickFile(); } } handleFileNameChange = (event) => { @@ -214,7 +219,7 @@ export class FileNode extends React.Component { renderChild = childId => (
  • - +
  • ) @@ -233,7 +238,7 @@ export class FileNode extends React.Component { const isRoot = this.props.name === 'root'; return ( -
    +
    { !isRoot &&
    @@ -382,10 +387,12 @@ FileNode.propTypes = { hideFolderChildren: PropTypes.func.isRequired, canEdit: PropTypes.bool.isRequired, openUploadFileModal: PropTypes.func.isRequired, - authenticated: PropTypes.bool.isRequired + authenticated: PropTypes.bool.isRequired, + onClickFile: PropTypes.func }; FileNode.defaultProps = { + onClickFile: null, parentId: '0', isSelectedFile: false, isFolderClosed: false, From 778aa4df222879e682a6fa086f54761b2d6937ee Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Tue, 11 Aug 2020 13:00:36 -0300 Subject: [PATCH 11/27] :lipstick: update some styles to position: fixed --- client/components/mobile/FloatingNav.jsx | 2 +- client/components/mobile/Sidebar.jsx | 2 +- client/components/useAsModal.jsx | 2 +- client/utils/custom-hooks.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/components/mobile/FloatingNav.jsx b/client/components/mobile/FloatingNav.jsx index 094a481e..de19c4ff 100644 --- a/client/components/mobile/FloatingNav.jsx +++ b/client/components/mobile/FloatingNav.jsx @@ -6,7 +6,7 @@ import Button from '../../common/Button'; import IconButton from './IconButton'; const FloatingContainer = styled.div` - position: absolute; + position: fixed; right: ${remSize(16)}; top: ${remSize(80)}; diff --git a/client/components/mobile/Sidebar.jsx b/client/components/mobile/Sidebar.jsx index cefd46bd..bc6c13ab 100644 --- a/client/components/mobile/Sidebar.jsx +++ b/client/components/mobile/Sidebar.jsx @@ -12,7 +12,7 @@ const SidebarWrapper = styled.div` height: 100%; width: ${remSize(180)}; - position: absolute; + position: fixed; z-index: 2; left: 0; diff --git a/client/components/useAsModal.jsx b/client/components/useAsModal.jsx index 092550e4..350d1de2 100644 --- a/client/components/useAsModal.jsx +++ b/client/components/useAsModal.jsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import { useModalBehavior } from '../utils/custom-hooks'; const BackgroundOverlay = styled.div` - position: absolute; + position: fixed; z-index: 2; width: 100% !important; height: 100% !important; diff --git a/client/utils/custom-hooks.js b/client/utils/custom-hooks.js index e289147f..a58bda41 100644 --- a/client/utils/custom-hooks.js +++ b/client/utils/custom-hooks.js @@ -28,7 +28,7 @@ export const useModalBehavior = (hideOverlay) => { const handleClickOutside = ({ target }) => { - if (ref && ref.current && !ref.current.contains(target)) { + if (ref && ref.current && !(ref.current.contains && ref.current.contains(target))) { hide(); } }; From d667b4b0c891a3a9fd2d2c5a79ae3e15a6889369 Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Tue, 11 Aug 2020 18:03:09 -0300 Subject: [PATCH 12/27] :ok_hand: move files button to bottom bar --- client/common/icons.jsx | 4 ++ client/components/mobile/ActionStrip.jsx | 57 +++++++++++++++++----- client/images/folder-padded.svg | 4 ++ client/modules/IDE/pages/MobileIDEView.jsx | 11 +---- 4 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 client/images/folder-padded.svg diff --git a/client/common/icons.jsx b/client/common/icons.jsx index b03c3c0f..c92fa2e7 100644 --- a/client/common/icons.jsx +++ b/client/common/icons.jsx @@ -16,6 +16,8 @@ import More from '../images/more.svg'; import Code from '../images/code.svg'; import Terminal from '../images/terminal.svg'; +import Folder from '../images/folder-padded.svg'; + import CircleTerminal from '../images/circle-terminal.svg'; import CircleFolder from '../images/circle-folder.svg'; import CircleInfo from '../images/circle-info.svg'; @@ -86,6 +88,8 @@ export const MoreIcon = withLabel(More); export const TerminalIcon = withLabel(Terminal); export const CodeIcon = withLabel(Code); +export const FolderIcon = withLabel(Folder); + export const CircleTerminalIcon = withLabel(CircleTerminal); export const CircleFolderIcon = withLabel(CircleFolder); export const CircleInfoIcon = withLabel(CircleInfo); diff --git a/client/components/mobile/ActionStrip.jsx b/client/components/mobile/ActionStrip.jsx index 0d75a579..6f72b34b 100644 --- a/client/components/mobile/ActionStrip.jsx +++ b/client/components/mobile/ActionStrip.jsx @@ -1,35 +1,66 @@ import React from 'react'; import styled from 'styled-components'; +import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { useDispatch, useSelector } from 'react-redux'; -import { remSize } from '../../theme'; +import { remSize, prop } from '../../theme'; import IconButton from './IconButton'; -import { TerminalIcon } from '../../common/icons'; +import { TerminalIcon, FolderIcon } from '../../common/icons'; import * as IDEActions from '../../modules/IDE/actions/ide'; -const BottomBarContent = styled.h2` +const BottomBarContent = styled.div` padding: ${remSize(8)}; - + display: flex; + svg { max-height: ${remSize(32)}; + + } + + path { fill: ${prop('primaryTextColor')} !important } + + .inverted { + path { fill: ${prop('backgroundColor')} !important } + rect { fill: ${prop('primaryTextColor')} !important } } `; -export default () => { +// Maybe this component shouldn't be connected, and instead just receive the `actions` prop +const ActionStrip = ({ toggleExplorer }) => { const { expandConsole, collapseConsole } = bindActionCreators(IDEActions, useDispatch()); const { consoleIsExpanded } = useSelector(state => state.ide); - const actions = [{ icon: TerminalIcon, aria: 'Say Something', action: consoleIsExpanded ? collapseConsole : expandConsole }]; + const actions = [ + { + icon: TerminalIcon, inverted: true, aria: 'Open terminal console', action: consoleIsExpanded ? collapseConsole : expandConsole + }, + { icon: FolderIcon, aria: 'Open files explorer', action: toggleExplorer } + ]; return ( - {actions.map(({ icon, aria, action }) => - ( action()} - />))} + {actions.map(({ + icon, aria, action, inverted + }) => + ( + action()} + />))} ); }; + +ActionStrip.propTypes = { + toggleExplorer: PropTypes.func +}; + +ActionStrip.defaultProps = { + toggleExplorer: () => {} +}; + +export default ActionStrip; diff --git a/client/images/folder-padded.svg b/client/images/folder-padded.svg new file mode 100644 index 00000000..67980f0a --- /dev/null +++ b/client/images/folder-padded.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/modules/IDE/pages/MobileIDEView.jsx b/client/modules/IDE/pages/MobileIDEView.jsx index c398f6b0..a1ab0ea7 100644 --- a/client/modules/IDE/pages/MobileIDEView.jsx +++ b/client/modules/IDE/pages/MobileIDEView.jsx @@ -35,8 +35,6 @@ import ActionStrip from '../../../components/mobile/ActionStrip'; import useAsModal from '../../../components/useAsModal'; import { PreferencesIcon } from '../../../common/icons'; import Dropdown from '../../../components/Dropdown'; -import FloatingNav from '../../../components/mobile/FloatingNav'; - const getRootFile = files => files && files.filter(file => file.name === 'root')[0]; const getRootFileID = files => (root => root && root.id)(getRootFile(files)); @@ -123,12 +121,6 @@ const MobileIDEView = (props) => { onPressClose={toggle} />), true); - // toggle sidebar starting opened - // useEffect(toggleExplorer, []); - - const floatingNavOptions = - [{ icon: CircleFolderIcon, onPress: toggleExplorer }]; - return ( @@ -183,7 +175,6 @@ const MobileIDEView = (props) => { provideController={setTmController} setUnsavedChanges={setUnsavedChanges} /> -
    @@ -192,7 +183,7 @@ const MobileIDEView = (props) => { )} - +
    ); From c50ca2a96929503210d174dd3c73a87b4d7f17cb Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Tue, 11 Aug 2020 18:06:14 -0300 Subject: [PATCH 13/27] :ok_hand: restore sidebar --- client/modules/App/App.jsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/modules/App/App.jsx b/client/modules/App/App.jsx index 27de8b67..a4ec3d7a 100644 --- a/client/modules/App/App.jsx +++ b/client/modules/App/App.jsx @@ -36,10 +36,7 @@ class App extends React.Component { render() { return (
    - {false && - this.state.isMounted && - !window.devToolsExtension && - getConfig('NODE_ENV') === 'development' && } + {this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && } {this.props.children}
    ); From 4b12f2f2f6aab4b4782281a9883502e4aac2664a Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Wed, 12 Aug 2020 14:50:31 -0400 Subject: [PATCH 14/27] Add minor styling fixes for MobileDashboardView --- client/modules/Mobile/MobileDashboardView.jsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/client/modules/Mobile/MobileDashboardView.jsx b/client/modules/Mobile/MobileDashboardView.jsx index 7bae38f4..ba51ad02 100644 --- a/client/modules/Mobile/MobileDashboardView.jsx +++ b/client/modules/Mobile/MobileDashboardView.jsx @@ -62,7 +62,6 @@ const ContentWrapper = styled(Content)` tbody { height: ${remSize(48)}; } .sketches-table-container { - padding-bottom: ${remSize(160)}; background: ${prop('SketchList.background')}; } .sketches-table__row { @@ -91,6 +90,19 @@ const ContentWrapper = styled(Content)` .loader-container { position: fixed ; padding-bottom: 32% } + .sketches-table thead th { + background-color: transparent; + } + + .asset-table thead th { + height: initial; + align-self: center; + } + + .asset-table thead tr { + height: ${remSize(32)} + } + `; const Subheader = styled.div` From 9f3e083c1726bc990e15b23534629cc4a4310ccd Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Wed, 12 Aug 2020 17:13:03 -0300 Subject: [PATCH 15/27] :construction: move drop arrow to top of card, unhide CollectionList createdAt --- .../components/CollectionList/CollectionList.jsx | 2 +- .../components/CollectionList/CollectionListRow.jsx | 2 +- client/modules/Mobile/MobileDashboardView.jsx | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/client/modules/IDE/components/CollectionList/CollectionList.jsx b/client/modules/IDE/components/CollectionList/CollectionList.jsx index c161d2bb..4a933f41 100644 --- a/client/modules/IDE/components/CollectionList/CollectionList.jsx +++ b/client/modules/IDE/components/CollectionList/CollectionList.jsx @@ -143,7 +143,7 @@ class CollectionList extends React.Component { {this._renderFieldHeader('name', 'Name')} - {(!mobile) && this._renderFieldHeader('createdAt', 'Date Created')} + {this._renderFieldHeader('createdAt', 'Date Created')} {this._renderFieldHeader('updatedAt', 'Date Updated')} {this._renderFieldHeader('numItems', '# sketches')} diff --git a/client/modules/IDE/components/CollectionList/CollectionListRow.jsx b/client/modules/IDE/components/CollectionList/CollectionListRow.jsx index f3119632..de20cea9 100644 --- a/client/modules/IDE/components/CollectionList/CollectionListRow.jsx +++ b/client/modules/IDE/components/CollectionList/CollectionListRow.jsx @@ -213,7 +213,7 @@ class CollectionListRowBase extends React.Component { {this.renderCollectionName()} - {(!mobile) && {format(new Date(collection.createdAt), 'MMM D, YYYY')}} + {mobile && 'Created: '}{format(new Date(collection.createdAt), 'MMM D, YYYY')} {mobile && 'Updated: '}{formatDateCell(collection.updatedAt)} {mobile && '# sketches: '}{(collection.items || []).length} diff --git a/client/modules/Mobile/MobileDashboardView.jsx b/client/modules/Mobile/MobileDashboardView.jsx index ba51ad02..b33bca42 100644 --- a/client/modules/Mobile/MobileDashboardView.jsx +++ b/client/modules/Mobile/MobileDashboardView.jsx @@ -55,7 +55,12 @@ const ContentWrapper = styled(Content)` tbody td { justify-self: start; text-align: start; padding: 0 } tbody td:nth-child(2) { justify-self: start; text-align: start; padding-left: ${remSize(12)}}; - tbody td:last-child { justify-self: end; text-align: end; }; + tbody td:last-child { + justify-self: end; + text-align: end; + grid-row-start: 1; + grid-column-start: 3; + }; .sketch-list__dropdown-column { width: auto; }; @@ -78,13 +83,13 @@ const ContentWrapper = styled(Content)` }; thead tr { - grid-template-columns: 1fr 1fr 1fr 0fr; + grid-template-columns: repeat(${props => props.fieldcount}, 1fr) 0fr; } tbody tr { padding: ${remSize(8)}; border-radius: ${remSize(4)}; - grid-template-columns: 5fr 5fr 1fr; + grid-template-columns: repeat(${props => props.fieldcount - 1}) 1fr; grid-template-areas: "name name name" "content content content"; } @@ -180,7 +185,7 @@ const MobileDashboard = ({ params, location }) => {
    - + {panel === Tabs[0] && } {panel === Tabs[1] && } From 69acd3af6720c089239340e58fefe74d8719ebcb Mon Sep 17 00:00:00 2001 From: ghalestrilo Date: Wed, 12 Aug 2020 17:42:14 -0300 Subject: [PATCH 16/27] :construction: add gap to dashboard cards --- client/modules/Mobile/MobileDashboardView.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/modules/Mobile/MobileDashboardView.jsx b/client/modules/Mobile/MobileDashboardView.jsx index b33bca42..bce0f454 100644 --- a/client/modules/Mobile/MobileDashboardView.jsx +++ b/client/modules/Mobile/MobileDashboardView.jsx @@ -27,6 +27,7 @@ const EXAMPLE_USERNAME = 'p5'; const ContentWrapper = styled(Content)` table { table-layout: fixed; + margin-bottom: ${remSize(120)} } td ,thead button { @@ -91,6 +92,7 @@ const ContentWrapper = styled(Content)` border-radius: ${remSize(4)}; grid-template-columns: repeat(${props => props.fieldcount - 1}) 1fr; grid-template-areas: "name name name" "content content content"; + grid-row-gap: ${remSize(12)} } .loader-container { position: fixed ; padding-bottom: 32% } From ff40de36ca6711127182959fcfbf06ab0c0a7d5f Mon Sep 17 00:00:00 2001 From: ov Date: Thu, 13 Aug 2020 11:12:02 +0100 Subject: [PATCH 17/27] Spanish Translation: Reset password Form and View (#1545) * Reset Password Form using login view translation keys * reduxFormUtils.js with i18 functionality to translate validations --- .../User/components/ResetPasswordForm.jsx | 15 ++++--- .../modules/User/pages/ResetPasswordView.jsx | 19 ++++---- client/utils/reduxFormUtils.js | 31 ++++++------- translations/locales/en-US/translations.json | 32 ++++++++++++-- translations/locales/es-419/translations.json | 44 ++++++++++++++----- 5 files changed, 96 insertions(+), 45 deletions(-) diff --git a/client/modules/User/components/ResetPasswordForm.jsx b/client/modules/User/components/ResetPasswordForm.jsx index df96bd79..87155f43 100644 --- a/client/modules/User/components/ResetPasswordForm.jsx +++ b/client/modules/User/components/ResetPasswordForm.jsx @@ -1,20 +1,20 @@ import PropTypes from 'prop-types'; import React from 'react'; - +import { withTranslation } from 'react-i18next'; import { domOnlyProps } from '../../../utils/reduxFormUtils'; import Button from '../../../common/Button'; function ResetPasswordForm(props) { const { - fields: { email }, handleSubmit, submitting, invalid, pristine + fields: { email }, handleSubmit, submitting, invalid, pristine, t } = props; return (

    - + Send Password Reset Email + >{t('ResetPasswordForm.Submit')}

    ); @@ -41,7 +41,8 @@ ResetPasswordForm.propTypes = { pristine: PropTypes.bool, user: PropTypes.shape({ resetPasswordInitiate: PropTypes.bool - }).isRequired + }).isRequired, + t: PropTypes.func.isRequired }; ResetPasswordForm.defaultProps = { @@ -50,4 +51,4 @@ ResetPasswordForm.defaultProps = { invalid: false }; -export default ResetPasswordForm; +export default withTranslation()(ResetPasswordForm); diff --git a/client/modules/User/pages/ResetPasswordView.jsx b/client/modules/User/pages/ResetPasswordView.jsx index 8ff7dac1..46d0b517 100644 --- a/client/modules/User/pages/ResetPasswordView.jsx +++ b/client/modules/User/pages/ResetPasswordView.jsx @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { bindActionCreators } from 'redux'; import { reduxForm } from 'redux-form'; import { Helmet } from 'react-helmet'; +import { withTranslation } from 'react-i18next'; import * as UserActions from '../actions'; import ResetPasswordForm from '../components/ResetPasswordForm'; import { validateResetPassword } from '../../../utils/reduxFormUtils'; @@ -23,19 +24,18 @@ function ResetPasswordView(props) {