From be8efa6025fde504f96c0f3f455146b4e41f3ed0 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Fri, 21 Oct 2016 17:42:21 -0400 Subject: [PATCH] add card features (#793) --- app/assets/stylesheets/mapcard.scss.erb | 119 ++++++++++++++++-- frontend/src/Metamaps/Views/ExploreMaps.js | 17 ++- frontend/src/components/Maps/MapCard.js | 139 ++++++++++++++------- frontend/src/components/Maps/index.js | 8 +- 4 files changed, 219 insertions(+), 64 deletions(-) diff --git a/app/assets/stylesheets/mapcard.scss.erb b/app/assets/stylesheets/mapcard.scss.erb index 69e3b71d..9dd38621 100644 --- a/app/assets/stylesheets/mapcard.scss.erb +++ b/app/assets/stylesheets/mapcard.scss.erb @@ -61,18 +61,113 @@ padding: 0 0 16px 0; color: #424242; + &:hover { + .dropdownMenu .menuToggle .circle { + background-color: #FFF; + } + .dropdownMenu .menuToggle:hover .circle { + background-color: #DDD; + } + + .mainContent { + filter: blur(2px); + } + + .mapMetadata { + display: block; + } + } + .mapHasMapper, .mapHasConversation { position: absolute; - top: 5px; - left: 5px; - width: 32px; - height: 32px; + top: 8px; + left: 8px; + min-width: 32px; + min-height: 32px; + + &:hover { + background-color: #FFF; + border-radius: 2px; + + .mapperList { + display: block; + } + } + + .mapperList { + display: none; + padding: 8px; + list-style-type: none; + + li { + &.live { + height: 32px; + padding-left: 32px; + font-size: 16px; + } + + img { + width: 24px; + height: 24px; + display: inline-block; + vertical-align: middle; + } + span { + padding-left: 10px; + font-size: 14px; + } + } + } } .mapHasMapper { - background: url('<%= asset_path('junto.png') %>'); + background: url('<%= asset_path('junto.png') %>') no-repeat 4px 0; } .mapHasConversation { - background: url('<%= asset_path('junto.gif') %>'); + background: url('<%= asset_path('junto.gif') %>') no-repeat 4px 0; + } + + .dropdownMenu { + position: absolute; + top: 8px; + right: 8px; + cursor: pointer; + + .menuToggle { + width: 30px; + height: 10px; + + .circle { + display: inline-block; + background-color: #454545; + width: 6px; + height: 6px; + border-radius: 3px; + margin: 2px; + } + + &:hover .circle { + background-color: #222; + } + } + + .menuItems { + position: absolute; + top: 18px; + right: 0px; + background: #FFF; + border-radius: 2px; + list-style-type: none; + color: #454545; + + li { + white-space: nowrap; + padding: 6px; + + &:hover { + background-color: #DDD; + } + } + } } .mapScreenshot { @@ -117,6 +212,12 @@ margin-left: 8px; } + .cardViewOnly { + float: right; + line-height: 32px; + padding-right: 10px; + color: #454545; + } .scroll { display:block; @@ -127,13 +228,7 @@ margin-top: 16px; } - &:hover .mainContent { - filter: blur(2px); - } - &:hover .mapMetadata { - display: block; - } .mapMetadata { display: none; diff --git a/frontend/src/Metamaps/Views/ExploreMaps.js b/frontend/src/Metamaps/Views/ExploreMaps.js index 421b3c22..c04346cc 100644 --- a/frontend/src/Metamaps/Views/ExploreMaps.js +++ b/frontend/src/Metamaps/Views/ExploreMaps.js @@ -4,6 +4,7 @@ import React from 'react' import ReactDOM from 'react-dom' // TODO ensure this isn't a double import import Active from '../Active' +import GlobalUI from '../GlobalUI' import Realtime from '../Realtime' import Maps from '../../components/Maps' @@ -42,7 +43,21 @@ const ExploreMaps = { juntoState: Realtime.juntoState, moreToLoad: self.collection.page != 'loadedAll', user: mapperObj, - loadMore: self.loadMore + loadMore: self.loadMore, + onStar: function (map) { + $.post('/maps/' + map.id + '/star') + map.set('star_count', map.get('star_count') + 1) + if (Metamaps.Stars) Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: map.id }) + Metamaps.Maps.Starred.add(map) + GlobalUI.notifyUser('Map is now starred') + self.render() + }, + onRequest: function (map) { + $.post({ + url: `/maps/${map.id}/access_request` + }) + GlobalUI.notifyUser('You will be notified by email if request accepted') + } } ReactDOM.render( React.createElement(Maps, exploreObj), diff --git a/frontend/src/components/Maps/MapCard.js b/frontend/src/components/Maps/MapCard.js index 1cb99530..efa3d59f 100644 --- a/frontend/src/components/Maps/MapCard.js +++ b/frontend/src/components/Maps/MapCard.js @@ -4,16 +4,57 @@ import { find, values } from 'lodash' const IN_CONVERSATION = 1 // shared with /realtime/reducer.js const MapperList = (props) => { - + return } +class Menu extends Component { + + constructor(props) { + super(props) + this.state = { open: false } + } + + toggle = () => { + this.setState({ open: !this.state.open }) + return true + } + + render = () => { + const { currentUser, map, onStar, onRequest } = this.props + const style = { display: this.state.open ? 'block' : 'none' } + + return
+
+
+
+
+
+ +
+ } +} +Menu.propTypes = { + currentUser: PropTypes.object.isRequired, + map: PropTypes.object.isRequired, + onStar: PropTypes.func.isRequired, + onRequest: PropTypes.func.isRequired +} + + class MapCard extends Component { render = () => { - const { map, juntoState, currentUser } = this.props + const { map, juntoState, currentUser, onRequest, onStar } = this.props const hasMap = juntoState.liveMaps[map.id] 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]) function capitalize (string) { return string.charAt(0).toUpperCase() + string.slice(1) @@ -30,51 +71,51 @@ class MapCard extends Component { return (
- -
-
-
-
- -
-
-
{ truncatedName }
-
-
- - { map.get('user_name') } -
-
-
-
- { map.get('contributor_count') }
- { map.get('contributor_count') === 1 ? 'contributor' : 'contributors' } -
-
- { 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' } -
-
-
-
- { truncatedDesc } -
-
-
-
- { hasMapper &&
} - { hasConversation &&
} -
-
-
+
+
+
+
+ +
+
+
{ truncatedName }
+
+
+ + { map.get('user_name') } + { !map.authorizeToEdit(currentUser) &&
View Only
} +
+
+ +
+ { map.get('contributor_count') }
+ { map.get('contributor_count') === 1 ? 'contributor' : 'contributors' } +
+
+ { 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' } +
+
+
+
+ { truncatedDesc } +
+
+
+
+ { hasMapper &&
} + { hasConversation &&
} + { currentUser && } +
+
) } @@ -83,7 +124,9 @@ class MapCard extends Component { MapCard.propTypes = { map: PropTypes.object.isRequired, juntoState: PropTypes.object, - currentUser: PropTypes.object + currentUser: PropTypes.object, + onStar: PropTypes.func.isRequired, + onRequest: PropTypes.func.isRequired } export default MapCard diff --git a/frontend/src/components/Maps/index.js b/frontend/src/components/Maps/index.js index a714e4ca..51bd1acc 100644 --- a/frontend/src/components/Maps/index.js +++ b/frontend/src/components/Maps/index.js @@ -41,7 +41,7 @@ class Maps extends Component { } render = () => { - const { maps, currentUser, juntoState, section, user, moreToLoad, loadMore } = this.props + const { maps, currentUser, juntoState, section, user, moreToLoad, loadMore, onStar, onRequest } = this.props const style = { width: this.state.mapsWidth + 'px' } return ( @@ -50,7 +50,7 @@ class Maps extends Component {
{ user ? : null } { currentUser && !user ?
Create new map...
: null } - { maps.models.map(map => ) } + { maps.models.map(map => ) }
{!moreToLoad ? null : [ , @@ -74,7 +74,9 @@ Maps.propTypes = { moreToLoad: PropTypes.bool.isRequired, user: PropTypes.object, currentUser: PropTypes.object, - loadMore: PropTypes.func + loadMore: PropTypes.func, + onStar: PropTypes.func.isRequired, + onRequest: PropTypes.func.isRequired } export default Maps