From cda0c21a0b61c8e8189f9c1eda32738f270f509b Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Sun, 23 Oct 2016 16:12:07 -0400 Subject: [PATCH] make it responsive (#820) --- app/assets/images/metadata.png | Bin 0 -> 1540 bytes app/assets/stylesheets/mapcard.scss.erb | 31 ++++-- app/assets/stylesheets/mobile.scss.erb | 113 +++++++++++++++------ frontend/src/components/Maps/MapCard.js | 126 ++++++++++++++---------- frontend/src/components/Maps/index.js | 9 +- 5 files changed, 190 insertions(+), 89 deletions(-) create mode 100644 app/assets/images/metadata.png diff --git a/app/assets/images/metadata.png b/app/assets/images/metadata.png new file mode 100644 index 0000000000000000000000000000000000000000..5388c90a5bec7875bbb6a10a697b7ee082a76605 GIT binary patch literal 1540 zcmV+f2K)JmP)2U2`p(xD2>XnY8o*~5C_P8n7)b*B1p~A^ zWdCYiRNi+OK)lNfZwI8oas%80gn)OIOin>{N}ipN<-k2n57RHn<3-$3830fK_i{Ki zL_sDAf^n6Q&SUy4dnfyOtX(=(3c4^<3^VwWhPZIi``|^ntnso5_uyT~Nl7({tP&}} zT#j>F1_VTn{d=`bpxV>%MnLNN>nHWTQkoz`yB~l>^Jd3ddBY}2@|ctddUYI>5K+Q& z1V^wk0oqm+fRhd6p;xe|0EMy5%dM(c;P)UD2FWo&lW|BuGPIo!AkLX*0NXEcZ*p2g{nCvlX=ow6FN%@p@GX#e4+WkSI1Gw|4P(s0|GvZiH&t&sZM1))gq)svv ztA}$~LI)_7x0ok7urwsTY$8;{(IymFV*vZ8vMr{TGz)PLY15(n@FP z;1N)oD!8q~?Is;xsWHG{JFU1lFF23F%;U_fOrfrF;C<@l%>W&hnLQhzSa>!DVYFi>iU!0-8i{Hc{~qebG+X>Q8XSWgrPZJ^B10}BEfRMxPS z&mM+w^gb*;g}noW;a#2+hLsQGlOSHa-%EJtq;nWi89aCR_dFWY-5xhhd;`69b&@>s z!wh=!_679XXOo8?(Ls|>6sVN<m3(f{sRWcpdo0$Hn__98nvtFM>nj(@ud6fY@~sA*xqAu!wlM+ADYF z(A3>I{3m}Fu2*N#)be@s>Xp++9`|X0+|wQdls7&Dpu5mBZymTFV7@kw|4I!&ui>*V z=sjDxIt`8{N7l+G?Jw)zpto1tzVFKqaW$GHQF{UZvpR#9Dc|f~lhtcy(Lt5WWKJ+{ zi$Rg}%y7c0<8Pw!&OeOw`v3ltb^7gn4_ui%^wN5O{{CqmZ+>-_y!iDwa-1Sy6F&QV zk{myFtgaRk=450K@>;1t5fsj}^k6&1x#_wJ~ zbKv13RJqOsdCiZvxnJ(wa>BrfIQ)Ig135?EydT$RhoSix?6PQP%-;UMgm3Q;?L1Ou z;WTc4S;9}6%7Aw`^j!_9^8U~dV

QF^8{79}lqSVZ{D*+!YeN?^NUMkWd>>l}UDn zREX&24%+kcgqI{z8}#IPe@B(?+t^6TqdudPKE_|c`;pK8nc}j;liB#pF!R12#U<}Y qyYl1*KmNXJkG*(3?Nw4qO8OT%hhdrnfF&gW0000"); background-repeat: no-repeat; - background-position: 0 0; + background-position: 0 0; position: absolute; left: 50%; margin-left: -36px; @@ -96,7 +96,7 @@ .mapperList { display: none; - padding: 8px; + padding: 8px; list-style-type: none; li { @@ -117,7 +117,7 @@ padding-left: 10px; font-size: 14px; } - } + } } } .mapHasMapper { @@ -149,7 +149,7 @@ &:hover .circle { background-color: #222; } - } + } .menuItems { position: absolute; @@ -167,8 +167,8 @@ &:hover { background-color: #DDD; } - } - } + } + } } .mapScreenshot { @@ -253,6 +253,25 @@ float: left; font-family: 'din-medium', sans-serif; text-align: center; + + div { + background: url('<%= asset_path('metadata.png') %>') no-repeat; + width: 32px; + height: 32px; + margin: 0 auto; + } + .numTopicsIcon { + background-position: 0 -32px; + } + .numStarsIcon { + background-position: 0 0; + } + .numSynapsesIcon { + background-position: -32px -32px; + } + .numContributorsIcon { + background-position: -32px 0; + } } } diff --git a/app/assets/stylesheets/mobile.scss.erb b/app/assets/stylesheets/mobile.scss.erb index a646fea4..9ced854c 100644 --- a/app/assets/stylesheets/mobile.scss.erb +++ b/app/assets/stylesheets/mobile.scss.erb @@ -2,16 +2,33 @@ display: none; } -/* Smartphones (portrait and landscape) ----------- */ -@media only screen and (max-device-width : 480px) { - .upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .uv-icon, .chat-box, #exploreMapsHeader { +@media only screen and (max-device-width : 720px) and (min-device-width : 504px) { + .sidebarSearch .tt-hint, .sidebarSearch .sidebarSearchField { + width: 160px !important; + } +} + +@media only screen and (max-device-width : 390px) { + .map .mapCard .mobileMetadata { + width: 190px; + } +} +@media only screen and (min-device-width : 390px) { + .map .mapCard .mobileMetadata { + width: 390px; + } +} + +/* Smartphones (portrait and landscape) ----------- the minimum space that two map cards can fit side by side */ +@media only screen and (max-device-width : 504px) { + .upperLeftUI, .upperRightUI, .openCheatsheet, .mapInfoIcon, .feedback-icon, .chat-box, #exploreMapsHeader { display: none !important; } - + #mobile_header { display: block; } - + .homeWrapper { width: 96%; padding: 0 2%; @@ -38,11 +55,11 @@ .learnMoreCTA { display: none !important; } - + #yield { height: 100%; } - + .new_session, .new_user, .edit_user, .login, .forgotPassword { position: relative; top: auto; @@ -51,11 +68,11 @@ padding: 16px 10%; margin: 50px auto 0 auto; } - + .centerGreyForm input[type="text"], .centerGreyForm input[type="email"], .centerGreyForm input[type="password"] { width: 100%; } - + .wrapper .mapInfoBox { position: fixed; top: 50px; @@ -64,12 +81,12 @@ width: 100%; max-width: 360px; } - + #wrapper .requestInvite { width: 100%; padding: 0; } - + #exploreMaps > div { margin-top: 70px; } @@ -94,35 +111,73 @@ span { vertical-align: middle; padding: 16px; - display: inline-block; + display: inline-block; } } .map.newMap:hover .newMapImage { background-position: 0 -40px; } -} - -/* Smartphones (portrait) ----------- */ -@media only screen and (max-width : 400px) { .map { width: 100%; margin: 0 0 30px 0; height: auto; - } - - .mapCard { - height: auto; - } - - .mapCard .title { - text-align: left; - } - - .mapCard .mapScreenshot { - display: none; - } + .mapCard { + height: auto; + padding: 0; + + &:hover { + .mainContent { + filter: none; + } + } + .mobileHasMapper, .mobileHasConversation { + .mapperList { + padding: 8px 16px; + list-style-type: none; + + li { + &.live { + height: 32px; + padding-left: 32px; + font-size: 16px; + } + + img { + width: 24px; + height: 24px; + border-radius: 12px; + display: inline-block; + vertical-align: middle; + } + span { + padding-left: 10px; + font-size: 14px; + } + } + } + } + .mobileHasMapper { + background: url('<%= asset_path('junto.png') %>') no-repeat 12px 0; + } + .mobileHasConversation { + background: url('<%= asset_path('junto.gif') %>') no-repeat 12px 0; + } + .mobileMetadata { + margin: 0 auto; + } + .title { + text-align: left; + display: block; + height: auto; + padding: 16px; + } + .desc { + padding: 0 16px; + } + } + } } #mobile_header { diff --git a/frontend/src/components/Maps/MapCard.js b/frontend/src/components/Maps/MapCard.js index efa3d59f..085784d7 100644 --- a/frontend/src/components/Maps/MapCard.js +++ b/frontend/src/components/Maps/MapCard.js @@ -24,17 +24,17 @@ class Menu extends Component { render = () => { const { currentUser, map, onStar, onRequest } = this.props - const style = { display: this.state.open ? 'block' : 'none' } + const style = { display: this.state.open ? 'block' : 'none' } return

-
+
    -
  • { this.toggle() && onStar(map) }}>Star Map
  • - { !map.authorizeToEdit(currentUser) &&
  • { this.toggle() && onRequest(map) }}>Request Access
  • } +
  • { this.toggle() && onStar(map) }}>Star Map
  • + { !map.authorizeToEdit(currentUser) &&
  • { this.toggle() && onRequest(map) }}>Request Access
  • }
} @@ -43,16 +43,47 @@ Menu.propTypes = { currentUser: PropTypes.object.isRequired, map: PropTypes.object.isRequired, onStar: PropTypes.func.isRequired, - onRequest: PropTypes.func.isRequired + onRequest: PropTypes.func.isRequired } +const Metadata = (props) => { + const { map } = props + return (
+
+
+ { map.get('topic_count') }
+ { map.get('topic_count') === 1 ? 'topic' : 'topics' } +
+
+
+ { map.get('star_count') }
+ { map.get('star_count') === 1 ? 'star' : 'stars' } +
+
+
+ { map.get('synapse_count') }
+ { map.get('synapse_count') === 1 ? 'synapse' : 'synapses' } +
+
+
+ { map.get('contributor_count') }
+ { map.get('contributor_count') === 1 ? 'contributor' : 'contributors' } +
+
+
) +} + +const checkAndWrapInA = (shouldWrap, classString, mapId, element) => { + if (shouldWrap) return { element } + else return element +} class MapCard extends Component { render = () => { - const { map, juntoState, currentUser, onRequest, onStar } = this.props + const { map, mobile, juntoState, currentUser, onRequest, onStar } = this.props const hasMap = juntoState.liveMaps[map.id] - const hasConversation = hasMap && find(values(hasMap), v => v === IN_CONVERSATION) + const hasConversation = hasMap && find(values(hasMap), v => v === IN_CONVERSATION) const hasMapper = hasMap && !hasConversation const mapperList = hasMap && Object.keys(hasMap).map(id => juntoState.connectedPeople[id]) @@ -71,51 +102,41 @@ class MapCard extends Component { return (
- + { checkAndWrapInA(mobile, '', map.id, +
+
+
+ { !mobile &&
+ +
} +
+
{ truncatedName }
+
+ { mobile && hasMapper &&
} + { mobile && hasConversation &&
} + { mobile && d &&
{ d }
} + { mobile &&
} +
+ + { map.get('user_name') } + { !map.authorizeToEdit(currentUser) &&
View Only
} +
+
+ { !mobile && checkAndWrapInA(true, 'mapMetadata', map.id, +
+ +
+
+ { truncatedDesc } +
+
+
+
) } + { !mobile && hasMapper &&
} + { !mobile && hasConversation &&
} + { !mobile && currentUser && } +
+
) }
) } @@ -123,6 +144,7 @@ class MapCard extends Component { MapCard.propTypes = { map: PropTypes.object.isRequired, + mobile: PropTypes.bool.isRequired, juntoState: PropTypes.object, currentUser: PropTypes.object, onStar: PropTypes.func.isRequired, diff --git a/frontend/src/components/Maps/index.js b/frontend/src/components/Maps/index.js index fee6c332..421cf056 100644 --- a/frontend/src/components/Maps/index.js +++ b/frontend/src/components/Maps/index.js @@ -5,6 +5,8 @@ import MapperCard from './MapperCard' import MapCard from './MapCard' const MAP_WIDTH = 252 +const MOBILE_VIEW_BREAKPOINT = 504 +const MOBILE_VIEW_PADDING = 20 const MAX_COLUMNS = 4 class Maps extends Component { @@ -28,7 +30,9 @@ class Maps extends Component { const { maps, user, currentUser } = this.props const numCards = maps.length + (user || currentUser ? 1 : 0) const mapSpaces = Math.floor(document.body.clientWidth / MAP_WIDTH) - const mapsWidth = Math.min(MAX_COLUMNS, Math.min(numCards, mapSpaces)) * MAP_WIDTH + const mapsWidth = document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT ? + document.body.clientWidth - MOBILE_VIEW_PADDING : + Math.min(MAX_COLUMNS, Math.min(numCards, mapSpaces)) * MAP_WIDTH this.setState({ mapsWidth }) } @@ -43,6 +47,7 @@ class Maps extends Component { render = () => { const { maps, currentUser, juntoState, pending, section, user, moreToLoad, loadMore, onStar, onRequest } = this.props const style = { width: this.state.mapsWidth + 'px' } + const mobile = document && document.body.clientWidth <= MOBILE_VIEW_BREAKPOINT return (
@@ -50,7 +55,7 @@ class Maps extends Component {
{ user ? : null } { currentUser && !user && !(pending && maps.length === 0) ? : null } - { maps.models.map(map => ) } + { maps.models.map(map => ) }