user editing in jsx
This commit is contained in:
parent
0220874590
commit
d765487635
19 changed files with 326 additions and 275 deletions
|
@ -4,18 +4,18 @@ function apiProxyMiddleware (req, res, next) {
|
||||||
if (!(req.xhr || req.originalUrl.indexOf('.json') > -1 || req.method !== 'GET')) {
|
if (!(req.xhr || req.originalUrl.indexOf('.json') > -1 || req.method !== 'GET')) {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
console.log('xhr request', req.originalUrl)
|
|
||||||
const method = req.method.toLowerCase()
|
const method = req.method.toLowerCase()
|
||||||
req.pipe(
|
req.pipe(
|
||||||
request[method](process.env.API + req.originalUrl, {
|
request[method](process.env.API + req.originalUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
...req.headers,
|
...req.headers,
|
||||||
host: process.env.API
|
cookie: `_Metamaps_session=${req.cookies._Metamaps_session}`,
|
||||||
|
host: 'localhost:3001'
|
||||||
},
|
},
|
||||||
followRedirect: false
|
followRedirect: false
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.on('error', console.log)
|
.on('error', (err) => console.log(err))
|
||||||
.pipe(res)
|
.pipe(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
package-lock.json
generated
34
package-lock.json
generated
|
@ -67,9 +67,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"action-cable-node": {
|
"action-cable-node": {
|
||||||
"version": "1.2.2",
|
"version": "github:Connoropolous/action-cable-node#346d691343251b4148ccc0607f87728d4d97f2cd"
|
||||||
"resolved": "https://registry.npmjs.org/action-cable-node/-/action-cable-node-1.2.2.tgz",
|
|
||||||
"integrity": "sha1-KwXl/iR+qqRXfwct2lDOCiEYOS0="
|
|
||||||
},
|
},
|
||||||
"after": {
|
"after": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
|
@ -1909,7 +1907,7 @@
|
||||||
"content-type": {
|
"content-type": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
|
"integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"content-type-parser": {
|
"content-type-parser": {
|
||||||
|
@ -1926,14 +1924,21 @@
|
||||||
"cookie": {
|
"cookie": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
||||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
|
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
||||||
"dev": true
|
},
|
||||||
|
"cookie-parser": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz",
|
||||||
|
"integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=",
|
||||||
|
"requires": {
|
||||||
|
"cookie": "0.3.1",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
|
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"copy-descriptor": {
|
"copy-descriptor": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
|
@ -5479,6 +5484,11 @@
|
||||||
"jquery": "3.2.1"
|
"jquery": "3.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"js-cookie": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s="
|
||||||
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||||
|
@ -6297,7 +6307,7 @@
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
||||||
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
|
"integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
|
@ -8276,7 +8286,7 @@
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.16.1",
|
"version": "0.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
|
||||||
"integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==",
|
"integrity": "sha1-pw4coh0TgsEdDZ9iMd6ygQgNerM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
|
@ -8320,7 +8330,7 @@
|
||||||
"serve-static": {
|
"serve-static": {
|
||||||
"version": "1.13.1",
|
"version": "1.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz",
|
||||||
"integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==",
|
"integrity": "sha1-TFfVNASnYdjy58HooYpH2/J4pxk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"encodeurl": "1.0.2",
|
"encodeurl": "1.0.2",
|
||||||
|
@ -8368,7 +8378,7 @@
|
||||||
"setprototypeof": {
|
"setprototypeof": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
||||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
|
"integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"sha.js": {
|
"sha.js": {
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"backbone": "1.3.3",
|
"backbone": "1.3.3",
|
||||||
"clipboard-js": "0.3.5",
|
"clipboard-js": "0.3.5",
|
||||||
"commonmark": "0.28.1",
|
"commonmark": "0.28.1",
|
||||||
|
"cookie-parser": "^1.4.3",
|
||||||
"csv-parse": "1.2.1",
|
"csv-parse": "1.2.1",
|
||||||
"emoji-mart": "1.0.1",
|
"emoji-mart": "1.0.1",
|
||||||
"getscreenmedia": "4.0.1",
|
"getscreenmedia": "4.0.1",
|
||||||
|
|
|
@ -64,8 +64,7 @@
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<!-- TODO: make 'authenticated' class dynamic -->
|
<body class="unauthenticated">
|
||||||
<body class="authenticated">
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<div id="loading"></div>
|
<div id="loading"></div>
|
||||||
|
@ -107,13 +106,6 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
Metamaps.ServerData = Metamaps.ServerData || {}
|
Metamaps.ServerData = Metamaps.ServerData || {}
|
||||||
Metamaps.ServerData.RAILS_ENV = 'development'
|
Metamaps.ServerData.RAILS_ENV = 'development'
|
||||||
Metamaps.ServerData.ActiveMapper = {
|
|
||||||
id: 10,
|
|
||||||
name: 'Connor',
|
|
||||||
email: 'co@co.com',
|
|
||||||
admin: false,
|
|
||||||
image: 'https://metamaps-live.s3.amazonaws.com/users/images/555/629/996/sixtyfour/11835c3.png?1417298429'
|
|
||||||
}
|
|
||||||
Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '/images/junto_spinner_darkgrey.gif'
|
Metamaps.ServerData['junto_spinner_darkgrey.gif'] = '/images/junto_spinner_darkgrey.gif'
|
||||||
Metamaps.ServerData['user.png'] = '/images/user.png'
|
Metamaps.ServerData['user.png'] = '/images/user.png'
|
||||||
Metamaps.ServerData['icons/wildcard.png'] = '/images/icons/wildcard.png'
|
Metamaps.ServerData['icons/wildcard.png'] = '/images/icons/wildcard.png'
|
||||||
|
|
|
@ -1,17 +1,3 @@
|
||||||
@import 'admin';
|
|
||||||
@import 'apps';
|
|
||||||
@import 'base';
|
|
||||||
@import 'clean';
|
|
||||||
@import 'emoji-mart-0.3.5';
|
|
||||||
@import 'feedback';
|
|
||||||
@import 'jquery-ui';
|
|
||||||
@import 'junto';
|
|
||||||
@import 'mapcard';
|
|
||||||
@import 'mobile';
|
|
||||||
@import 'notifications';
|
|
||||||
@import 'request_access';
|
|
||||||
@import 'search';
|
|
||||||
|
|
||||||
/* clear styles */
|
/* clear styles */
|
||||||
|
|
||||||
html,
|
html,
|
||||||
|
@ -243,10 +229,6 @@ button.button.btn-no:hover {
|
||||||
color:#424242;
|
color:#424242;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toHide {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.forgotPassword {
|
.forgotPassword {
|
||||||
height: 134px;
|
height: 134px;
|
||||||
font-family: din-medium;
|
font-family: din-medium;
|
||||||
|
@ -327,7 +309,6 @@ button.button.btn-no:hover {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 88px;
|
top: 88px;
|
||||||
left: -18px;
|
left: -18px;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
.userMenuArrow {
|
.userMenuArrow {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
|
@ -436,7 +417,6 @@ button.button.btn-no:hover {
|
||||||
margin:5px 0px 0px 5px;
|
margin:5px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
.changeName {
|
.changeName {
|
||||||
display: none;
|
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3029,3 +3009,17 @@ script.data-gratipay-username {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@import 'admin';
|
||||||
|
@import 'apps';
|
||||||
|
@import 'base';
|
||||||
|
@import 'clean';
|
||||||
|
@import 'emoji-mart-0.3.5';
|
||||||
|
@import 'feedback';
|
||||||
|
@import 'jquery-ui';
|
||||||
|
@import 'junto';
|
||||||
|
@import 'mapcard';
|
||||||
|
@import 'mobile';
|
||||||
|
@import 'notifications';
|
||||||
|
@import 'request_access';
|
||||||
|
@import 'search';
|
|
@ -1,5 +1,6 @@
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const express = require('express')
|
const express = require('express')
|
||||||
|
const cookieParser = require('cookie-parser')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
const socketio = require('socket.io')
|
const socketio = require('socket.io')
|
||||||
const { createServer } = require('http')
|
const { createServer } = require('http')
|
||||||
|
@ -13,6 +14,8 @@ const server = createServer(app)
|
||||||
const io = socketio(server)
|
const io = socketio(server)
|
||||||
realtime(io) // sets up the socketio event listeners
|
realtime(io) // sets up the socketio event listeners
|
||||||
|
|
||||||
|
app.use(cookieParser())
|
||||||
|
|
||||||
// serve the whole public folder as static files
|
// serve the whole public folder as static files
|
||||||
app.use(express.static(path.join(__dirname, 'public')))
|
app.use(express.static(path.join(__dirname, 'public')))
|
||||||
|
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
/* global $, CanvasLoader */
|
|
||||||
|
|
||||||
const Account = {
|
|
||||||
init: function(serverData) {
|
|
||||||
Account.userIconUrl = serverData['user.png']
|
|
||||||
},
|
|
||||||
listenersInitialized: false,
|
|
||||||
userIconUrl: null,
|
|
||||||
initListeners: function() {
|
|
||||||
var self = Account
|
|
||||||
|
|
||||||
$('#user_image').change(self.showImagePreview)
|
|
||||||
self.listenersInitialized = true
|
|
||||||
},
|
|
||||||
toggleChangePicture: function() {
|
|
||||||
var self = Account
|
|
||||||
|
|
||||||
$('.userImageMenu').toggle()
|
|
||||||
if (!self.listenersInitialized) self.initListeners()
|
|
||||||
},
|
|
||||||
openChangePicture: function() {
|
|
||||||
var self = Account
|
|
||||||
|
|
||||||
$('.userImageMenu').show()
|
|
||||||
if (!self.listenersInitialized) self.initListeners()
|
|
||||||
},
|
|
||||||
closeChangePicture: function() {
|
|
||||||
$('.userImageMenu').hide()
|
|
||||||
},
|
|
||||||
showLoading: function() {
|
|
||||||
var loader = new CanvasLoader('accountPageLoading')
|
|
||||||
loader.setColor('#4FC059') // default is '#000000'
|
|
||||||
loader.setDiameter(28) // default is 40
|
|
||||||
loader.setDensity(41) // default is 40
|
|
||||||
loader.setRange(0.9) // default is 1.3
|
|
||||||
loader.show() // Hidden by default
|
|
||||||
$('#accountPageLoading').show()
|
|
||||||
},
|
|
||||||
showImagePreview: function() {
|
|
||||||
var file = $('#user_image')[0].files[0]
|
|
||||||
|
|
||||||
var reader = new window.FileReader()
|
|
||||||
|
|
||||||
reader.onload = function(e) {
|
|
||||||
var $canvas = $('<canvas>').attr({
|
|
||||||
width: 84,
|
|
||||||
height: 84
|
|
||||||
})
|
|
||||||
var context = $canvas[0].getContext('2d')
|
|
||||||
var imageObj = new window.Image()
|
|
||||||
|
|
||||||
imageObj.onload = function() {
|
|
||||||
$('.userImageDiv canvas').remove()
|
|
||||||
$('.userImageDiv img').hide()
|
|
||||||
|
|
||||||
var imgWidth = imageObj.width
|
|
||||||
var imgHeight = imageObj.height
|
|
||||||
|
|
||||||
var dimensionToMatch = imgWidth > imgHeight ? imgHeight : imgWidth
|
|
||||||
// draw cropped image
|
|
||||||
var nonZero = Math.abs(imgHeight - imgWidth) / 2
|
|
||||||
var sourceX = dimensionToMatch === imgWidth ? 0 : nonZero
|
|
||||||
var sourceY = dimensionToMatch === imgHeight ? 0 : nonZero
|
|
||||||
var sourceWidth = dimensionToMatch
|
|
||||||
var sourceHeight = dimensionToMatch
|
|
||||||
var destX = 0
|
|
||||||
var destY = 0
|
|
||||||
var destWidth = 84
|
|
||||||
var destHeight = 84
|
|
||||||
|
|
||||||
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight)
|
|
||||||
$('.userImageDiv').prepend($canvas)
|
|
||||||
}
|
|
||||||
imageObj.src = reader.result
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
reader.readAsDataURL(file)
|
|
||||||
$('.userImageMenu').hide()
|
|
||||||
$('#remove_image').val('0')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removePicture: function() {
|
|
||||||
var self = Account
|
|
||||||
|
|
||||||
$('.userImageDiv canvas').remove()
|
|
||||||
$('.userImageDiv img').attr('src', self.userIconUrl).show()
|
|
||||||
$('.userImageMenu').hide()
|
|
||||||
|
|
||||||
var input = $('#user_image')
|
|
||||||
input.replaceWith(input.val('').clone(true))
|
|
||||||
$('#remove_image').val('1')
|
|
||||||
},
|
|
||||||
changeName: function() {
|
|
||||||
$('.accountName').hide()
|
|
||||||
$('.changeName').show()
|
|
||||||
},
|
|
||||||
showPass: function() {
|
|
||||||
$('.toHide').show()
|
|
||||||
$('.changePass').hide()
|
|
||||||
},
|
|
||||||
hidePass: function() {
|
|
||||||
$('.toHide').hide()
|
|
||||||
$('.changePass').show()
|
|
||||||
|
|
||||||
$('#current_password').val('')
|
|
||||||
$('#user_password').val('')
|
|
||||||
$('#user_password_confirmation').val('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Account
|
|
|
@ -1,10 +1,20 @@
|
||||||
|
function fetchWithCookies(url) {
|
||||||
|
return fetch(url, { credentials: 'same-origin' })
|
||||||
|
}
|
||||||
|
|
||||||
async function getMetacodes() {
|
async function getMetacodes() {
|
||||||
const res = await fetch('/metacodes.json')
|
const res = await fetchWithCookies('/metacodes.json')
|
||||||
|
const data = await res.json()
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCurrentUser() {
|
||||||
|
const res = await fetchWithCookies('/users/current.json')
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getMetacodes
|
getMetacodes,
|
||||||
|
getCurrentUser
|
||||||
}
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import Account from './Account'
|
|
||||||
import Active from './Active'
|
import Active from './Active'
|
||||||
import Admin from './Admin'
|
import Admin from './Admin'
|
||||||
import AutoLayout from './AutoLayout'
|
import AutoLayout from './AutoLayout'
|
||||||
|
@ -32,7 +31,6 @@ import Views from './Views'
|
||||||
import Visualize from './Visualize'
|
import Visualize from './Visualize'
|
||||||
|
|
||||||
const Metamaps = window.Metamaps || {}
|
const Metamaps = window.Metamaps || {}
|
||||||
Metamaps.Account = Account
|
|
||||||
Metamaps.Active = Active
|
Metamaps.Active = Active
|
||||||
Metamaps.Admin = Admin
|
Metamaps.Admin = Admin
|
||||||
Metamaps.AutoLayout = AutoLayout
|
Metamaps.AutoLayout = AutoLayout
|
||||||
|
@ -91,6 +89,12 @@ document.addEventListener('DOMContentLoaded', async function() {
|
||||||
try {
|
try {
|
||||||
const metacodes = await DataFetcher.getMetacodes()
|
const metacodes = await DataFetcher.getMetacodes()
|
||||||
Metamaps.ServerData.Metacodes = metacodes
|
Metamaps.ServerData.Metacodes = metacodes
|
||||||
|
|
||||||
|
const activeMapper = await DataFetcher.getCurrentUser()
|
||||||
|
if (activeMapper) {
|
||||||
|
Metamaps.ServerData.ActiveMapper = activeMapper
|
||||||
|
$('body').removeClass('unauthenticated').addClass('authenticated')
|
||||||
|
}
|
||||||
runInitFunctions(Metamaps.ServerData)
|
runInitFunctions(Metamaps.ServerData)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import onClickOutsideAddon from 'react-onclickoutside'
|
import onClickOutsideAddon from 'react-onclickoutside'
|
||||||
|
|
||||||
|
@ -22,15 +23,15 @@ class AccountMenu extends Component {
|
||||||
<ul>
|
<ul>
|
||||||
<li className="accountListItem accountSettings">
|
<li className="accountListItem accountSettings">
|
||||||
<div className="accountIcon"></div>
|
<div className="accountIcon"></div>
|
||||||
<a href={`/users/${currentUser.id}/edit`}>Settings</a>
|
<Link to={`/users/${currentUser.id}/edit`}>Settings</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="accountListItem accountAdmin">
|
<li className="accountListItem accountAdmin">
|
||||||
<div className="accountIcon"></div>
|
<div className="accountIcon"></div>
|
||||||
<a href="/metacodes">Admin</a>
|
<Link to="/metacodes">Admin</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="accountListItem accountApps">
|
<li className="accountListItem accountApps">
|
||||||
<div className="accountIcon"></div>
|
<div className="accountIcon"></div>
|
||||||
<a href="/oauth/authorized_applications">Apps</a>
|
<Link to="/oauth/authorized_applications">Apps</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="accountListItem accountInvite" onClick={onInviteClick}>
|
<li className="accountListItem accountInvite" onClick={onInviteClick}>
|
||||||
<div className="accountIcon"></div>
|
<div className="accountIcon"></div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import onClickOutsideAddon from 'react-onclickoutside'
|
import onClickOutsideAddon from 'react-onclickoutside'
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ class LoginForm extends Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="clearfloat"></div>
|
<div className="clearfloat"></div>
|
||||||
<div className="accountForgotPass">
|
<div className="accountForgotPass">
|
||||||
<a href="/users/password/new">Forgot password?</a>
|
<Link to="/users/password/new">Forgot password?</Link>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import _ from 'lodash'
|
||||||
|
|
||||||
const PROP_LIST = [
|
const PROP_LIST = [
|
||||||
'matchChildRoutes',
|
'matchChildRoutes',
|
||||||
'hardReload',
|
|
||||||
'show',
|
'show',
|
||||||
'text',
|
'text',
|
||||||
'href',
|
'href',
|
||||||
|
@ -15,7 +14,6 @@ const PROP_LIST = [
|
||||||
class NavBarLink extends Component {
|
class NavBarLink extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
matchChildRoutes: PropTypes.bool,
|
matchChildRoutes: PropTypes.bool,
|
||||||
hardReload: PropTypes.bool,
|
|
||||||
show: PropTypes.bool,
|
show: PropTypes.bool,
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
href: PropTypes.string,
|
href: PropTypes.string,
|
||||||
|
@ -29,7 +27,6 @@ class NavBarLink extends Component {
|
||||||
render = () => {
|
render = () => {
|
||||||
const {
|
const {
|
||||||
matchChildRoutes,
|
matchChildRoutes,
|
||||||
hardReload,
|
|
||||||
show,
|
show,
|
||||||
text,
|
text,
|
||||||
href,
|
href,
|
||||||
|
@ -45,14 +42,6 @@ class NavBarLink extends Component {
|
||||||
if (!show) {
|
if (!show) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (hardReload) {
|
|
||||||
return (
|
|
||||||
<a { ...otherProps } href={href} className={classes.join(' ')}>
|
|
||||||
{linkClass && <div className="navBarIcon"></div>}
|
|
||||||
<div className="navBarLinkText">{text}</div>
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Link { ...otherProps } to={href} className={classes.join(' ')}>
|
<Link { ...otherProps } to={href} className={classes.join(' ')}>
|
||||||
{linkClass && <div className="navBarIcon"></div>}
|
{linkClass && <div className="navBarIcon"></div>}
|
||||||
|
|
|
@ -16,8 +16,7 @@ class UpperLeftUI extends Component {
|
||||||
const { map, currentUser, userRequested, requestAnswered, requestApproved, onRequestClick } = this.props
|
const { map, currentUser, userRequested, requestAnswered, requestApproved, onRequestClick } = this.props
|
||||||
return <div className="upperLeftUI">
|
return <div className="upperLeftUI">
|
||||||
<div className="homeButton">
|
<div className="homeButton">
|
||||||
{currentUser && <Link to="/">METAMAPS</Link>}
|
<Link to="/">METAMAPS</Link>
|
||||||
{!currentUser && <a href="/">METAMAPS</a>}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="sidebarSearch">
|
<div className="sidebarSearch">
|
||||||
<input type="text" className="sidebarSearchField" placeholder="Search for topics, maps, and mappers..." />
|
<input type="text" className="sidebarSearchField" placeholder="Search for topics, maps, and mappers..." />
|
||||||
|
|
|
@ -6,10 +6,10 @@ class Admin extends Component {
|
||||||
render = () => {
|
render = () => {
|
||||||
return (
|
return (
|
||||||
<NavBar>
|
<NavBar>
|
||||||
<NavBarLink show hardReload href="/metacode_sets" text="Metacode Sets" />
|
<NavBarLink show href="/metacode_sets" text="Metacode Sets" />
|
||||||
<NavBarLink show hardReload href="/metacode_sets/new" text="New Set" />
|
<NavBarLink show href="/metacode_sets/new" text="New Set" />
|
||||||
<NavBarLink show hardReload href="/metacodes" text="Metacodes" />
|
<NavBarLink show href="/metacodes" text="Metacodes" />
|
||||||
<NavBarLink show hardReload href="/metacodes/new" text="New Metacode" />
|
<NavBarLink show href="/metacodes/new" text="New Metacode" />
|
||||||
</NavBar>
|
</NavBar>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ class Apps extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavBar>
|
<NavBar>
|
||||||
{currentUser && currentUser.get('admin') && <NavBarLink show hardReload
|
{currentUser && currentUser.get('admin') && <NavBarLink show
|
||||||
matchChildRoutes href="/oauth/applications" linkClass="activeMaps"
|
matchChildRoutes href="/oauth/applications" linkClass="activeMaps"
|
||||||
text="Registered Apps" />}
|
text="Registered Apps" />}
|
||||||
<NavBarLink show hardReload matchChildRoutes
|
<NavBarLink show matchChildRoutes
|
||||||
href="/oauth/authorized_applications"
|
href="/oauth/authorized_applications"
|
||||||
linkClass="authedApps" text="Authorized Apps" />
|
linkClass="authedApps" text="Authorized Apps" />
|
||||||
<NavBarLink show href="/" linkClass="myMaps" text="Maps" />
|
<NavBarLink show href="/" linkClass="myMaps" text="Maps" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
class LoggedOutHome extends Component {
|
class LoggedOutHome extends Component {
|
||||||
render = () => {
|
render = () => {
|
||||||
|
@ -17,8 +18,8 @@ class LoggedOutHome extends Component {
|
||||||
<h3>Who finds it useful?</h3>
|
<h3>Who finds it useful?</h3>
|
||||||
<p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p>
|
<p>Designers, inventors, artists, educators, strategists, consultants, facilitators, entrepreneurs, systems thinkers, changemakers, analysts, students, researchers... maybe you!</p>
|
||||||
<button type="button" className="button learnMoreCTA" onClick={() => {Metamaps.GlobalUI.openLightbox('about')}}>LEARN MORE</button>
|
<button type="button" className="button learnMoreCTA" onClick={() => {Metamaps.GlobalUI.openLightbox('about')}}>LEARN MORE</button>
|
||||||
<a href="/explore/featured" data-router="true" className="exploreFeaturedCTA">EXPLORE FEATURED MAPS</a>
|
<Link to="/explore/featured" data-router="true" className="exploreFeaturedCTA">EXPLORE FEATURED MAPS</Link>
|
||||||
<a href="/request" className="requestInviteCTA">REQUEST INVITE</a>
|
<Link to="/request" className="requestInviteCTA">REQUEST INVITE</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="clearfloat"></div>
|
<div className="clearfloat"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
246
src/routes/UserSettings.js
Normal file
246
src/routes/UserSettings.js
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
import Loading from '../components/Loading'
|
||||||
|
|
||||||
|
class UserSettings extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
userImageMenuOpen: false,
|
||||||
|
changePasswordOpen: false,
|
||||||
|
changeName: false,
|
||||||
|
loading: false,
|
||||||
|
imagePreview: null,
|
||||||
|
currentPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
newPasswordConfirmation: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
emailsAllowed: false,
|
||||||
|
followTopicOnCreated: false,
|
||||||
|
followTopicOnContributed: false,
|
||||||
|
followMapOnCreated: false,
|
||||||
|
followMapOnContributed: false,
|
||||||
|
removeImage: '0' // can be '0' or '1', 0 means keep, 1 means remove
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.setState({
|
||||||
|
name: this.props.currentUser.get('name'),
|
||||||
|
email: this.props.currentUser.get('email'),
|
||||||
|
image: this.props.currentUser.get('image'),
|
||||||
|
emailsAllowed: this.props.currentUser.get('emails_allowed'),
|
||||||
|
followTopicOnCreated: this.props.currentUser.get('follow_topic_on_created'),
|
||||||
|
followTopicOnContributed: this.props.currentUser.get('follow_topic_on_contributed'),
|
||||||
|
followMapOnCreated: this.props.currentUser.get('follow_map_on_created'),
|
||||||
|
followMapOnContributed: this.props.currentUser.get('follow_map_on_contributed')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
init = (serverData) => {
|
||||||
|
Account.userIconUrl = serverData['user.png']
|
||||||
|
}
|
||||||
|
|
||||||
|
initListeners = () => {
|
||||||
|
/*
|
||||||
|
$('#user_image').change(self.showImagePreview)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleChangePicture = () => {
|
||||||
|
this.setState({
|
||||||
|
userImageMenuOpen: !this.state.userImageMenuOpen
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
openChangePicture = () => {
|
||||||
|
this.setState({
|
||||||
|
userImageMenuOpen: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
closeChangePicture = () => {
|
||||||
|
this.setState({
|
||||||
|
userImageMenuOpen: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
showLoading = () => {
|
||||||
|
this.setState({ loading: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
showImagePreview = () => {
|
||||||
|
var file = $('#user_image')[0].files[0]
|
||||||
|
|
||||||
|
var reader = new window.FileReader()
|
||||||
|
|
||||||
|
reader.onload = function(e) {
|
||||||
|
var $canvas = $('<canvas>').attr({
|
||||||
|
width: 84,
|
||||||
|
height: 84
|
||||||
|
})
|
||||||
|
var context = $canvas[0].getContext('2d')
|
||||||
|
var imageObj = new window.Image()
|
||||||
|
|
||||||
|
imageObj.onload = function() {
|
||||||
|
$('.userImageDiv canvas').remove()
|
||||||
|
$('.userImageDiv img').hide()
|
||||||
|
|
||||||
|
var imgWidth = imageObj.width
|
||||||
|
var imgHeight = imageObj.height
|
||||||
|
|
||||||
|
var dimensionToMatch = imgWidth > imgHeight ? imgHeight : imgWidth
|
||||||
|
// draw cropped image
|
||||||
|
var nonZero = Math.abs(imgHeight - imgWidth) / 2
|
||||||
|
var sourceX = dimensionToMatch === imgWidth ? 0 : nonZero
|
||||||
|
var sourceY = dimensionToMatch === imgHeight ? 0 : nonZero
|
||||||
|
var sourceWidth = dimensionToMatch
|
||||||
|
var sourceHeight = dimensionToMatch
|
||||||
|
var destX = 0
|
||||||
|
var destY = 0
|
||||||
|
var destWidth = 84
|
||||||
|
var destHeight = 84
|
||||||
|
|
||||||
|
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight)
|
||||||
|
$('.userImageDiv').prepend($canvas)
|
||||||
|
}
|
||||||
|
imageObj.src = reader.result
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
$('.userImageMenu').hide()
|
||||||
|
$('#remove_image').val('0')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removePicture = () => {
|
||||||
|
/*
|
||||||
|
$('.userImageDiv canvas').remove()
|
||||||
|
$('.userImageDiv img').attr('src', '/images/user.png').show()
|
||||||
|
$('.userImageMenu').hide()
|
||||||
|
|
||||||
|
var input = $('#user_image')
|
||||||
|
input.replaceWith(input.val('').clone(true))
|
||||||
|
$('#remove_image').val('1')
|
||||||
|
*/
|
||||||
|
this.setState({ removeImage: '1' })
|
||||||
|
}
|
||||||
|
|
||||||
|
changeName = () => {
|
||||||
|
this.setState({ changeName: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
showPass = () => {
|
||||||
|
this.setState({ changePasswordOpen: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
hidePass = () => {
|
||||||
|
this.setState({
|
||||||
|
changePasswordOpen: false,
|
||||||
|
currentPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
newPasswordConfirmation: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateForKey = (key) => {
|
||||||
|
return (event) => {
|
||||||
|
const newState = {}
|
||||||
|
if (event.target.type === 'checkbox') {
|
||||||
|
newState[key] = !this.state[key]
|
||||||
|
} else {
|
||||||
|
newState[key] = event.target.value
|
||||||
|
}
|
||||||
|
this.setState(newState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
const id = this.props.currentUser.get('id')
|
||||||
|
const name = this.props.currentUser.get('name')
|
||||||
|
return (
|
||||||
|
<div id="yield">
|
||||||
|
<form className="edit_user centerGreyForm" id={`edit_user_${id}`} encType="multipart/form-data" action={`/users/${id}`} acceptCharset="UTF-8" method="patch">
|
||||||
|
<input name="utf8" type="hidden" value="✓" />
|
||||||
|
<h3>Edit Settings</h3>
|
||||||
|
<div className="userImage">
|
||||||
|
<div className="userImageDiv" onClick={this.toggleChangePicture}>
|
||||||
|
<img src={this.state.image} alt="11835c3" width="84" height="84" />
|
||||||
|
<div className="editPhoto"></div>
|
||||||
|
</div>
|
||||||
|
{this.state.userImageMenuOpen && <div className="userImageMenu">
|
||||||
|
<div className="userMenuArrow"></div>
|
||||||
|
<ul>
|
||||||
|
<li className="upload">
|
||||||
|
Upload Photo
|
||||||
|
<input type="hidden" name="remove_image" id="remove_image" value={this.state.removeImage} />
|
||||||
|
<input type="file" name="user[image]" id="user_image" />
|
||||||
|
<label htmlFor="user_image">Image</label>
|
||||||
|
</li>
|
||||||
|
<li className="remove" onClick={this.removePicture}>Remove</li>
|
||||||
|
<li className="cancel" onClick={this.closeChangePicture}>Cancel</li>
|
||||||
|
</ul>
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
{!this.state.changeName && <div className="accountName" onClick={this.changeName}>
|
||||||
|
<div className="nameEdit">{ name }</div>
|
||||||
|
</div>}
|
||||||
|
{this.state.changeName && <div className="changeName">
|
||||||
|
<label className="firstFieldText" htmlFor="user_name">Name:</label>
|
||||||
|
<input type="text" name="user[name]" id="user_name" value={this.state.name} onChange={this.updateForKey('name')} />
|
||||||
|
</div>}
|
||||||
|
<div>
|
||||||
|
<label className="firstFieldText" htmlFor="user_email">Email:</label>
|
||||||
|
<input type="email" value={this.state.email} onChange={this.updateForKey('email')} name="user[email]" id="user_email" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="firstFieldText" htmlFor="user_emails_allowed">
|
||||||
|
<input className="inline" type="checkbox" value={this.state.emailsAllowed ? '1' : '0'} checked={this.state.emailsAllowed} onChange={this.updateForKey('emailsAllowed')} name="user[emails_allowed]" id="user_emails_allowed" />
|
||||||
|
Send Metamaps notifications to my email.
|
||||||
|
</label>
|
||||||
|
<label className="firstFieldText" htmlFor="settings_follow_topic_on_created">
|
||||||
|
<input className="inline" type="checkbox" value={this.state.followTopicOnCreated ? '1' : '0'} checked={this.state.followTopicOnCreated} onChange={this.updateForKey('followTopicOnCreated')} name="settings[follow_topic_on_created]" id="settings_follow_topic_on_created" />
|
||||||
|
Auto-follow topics you create.
|
||||||
|
</label>
|
||||||
|
<label className="firstFieldText" htmlFor="settings_follow_topic_on_contributed">
|
||||||
|
<input className="inline" type="checkbox" value={this.state.followTopicOnContributed ? '1' : '0'} checked={this.state.followTopicOnContributed} onChange={this.updateForKey('followTopicOnContributed')} name="settings[follow_topic_on_contributed]" id="settings_follow_topic_on_contributed" />
|
||||||
|
Auto-follow topics you edit.
|
||||||
|
</label>
|
||||||
|
<label className="firstFieldText" htmlFor="settings_follow_map_on_created">
|
||||||
|
<input className="inline" type="checkbox" value={this.state.followMapOnCreated ? '1' : '0'} checked={this.state.followMapOnCreated} onChange={this.updateForKey('followMapOnCreated')} name="settings[follow_map_on_created]" id="settings_follow_map_on_created" />
|
||||||
|
Auto-follow maps you create.
|
||||||
|
</label>
|
||||||
|
<label className="firstFieldText" htmlFor="settings_follow_map_on_contributed">
|
||||||
|
<input className="inline" type="checkbox" value={this.state.followMapOnContributed ? '1' : '0'} checked={this.state.followMapOnContributed} onChange={this.updateForKey('followMapOnContributed')} name="settings[follow_map_on_contributed]" id="settings_follow_map_on_contributed" />
|
||||||
|
Auto-follow maps you edit.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{!this.state.changePasswordOpen && <div className="changePass" onClick={this.showPass}>Change Password</div>}
|
||||||
|
{this.state.changePasswordOpen && <div>
|
||||||
|
<div>
|
||||||
|
<label className="firstFieldText" htmlFor="user_current_password">Current Password:</label>
|
||||||
|
<input type="password" name="current_password" id="current_password" value={this.state.currentPassword} onChange={this.updateForKey('currentPassword')} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="firstFieldText" htmlFor="user_password">New Password:</label>
|
||||||
|
<input autoComplete="off" type="password" name="user[password]" id="user_password" value={this.state.newPassword} onChange={this.updateForKey('newPassword')} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="firstFieldText" htmlFor="user_password_confirmation">Confirm New Password:</label>
|
||||||
|
<input autoComplete="off" type="password" name="user[password_confirmation]" id="user_password_confirmation" value={this.state.newPasswordConfirmation} onChange={this.updateForKey('newPasswordConfirmation')} />
|
||||||
|
</div>
|
||||||
|
<div className="noChangePass" onClick={this.hidePass}>Oops, don't change password</div>
|
||||||
|
</div>}
|
||||||
|
<div id="accountPageLoading">
|
||||||
|
{this.state.loading && <Loading />}
|
||||||
|
</div>
|
||||||
|
<input type="submit" name="commit" value="Update" className="update" onClick={this.showLoading} data-disable-with="Update" />
|
||||||
|
<div className="clearfloat"></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserSettings
|
|
@ -12,6 +12,7 @@ import RequestAccess from './RequestAccess'
|
||||||
import RequestInvite from './RequestInvite'
|
import RequestInvite from './RequestInvite'
|
||||||
import Login from './Login'
|
import Login from './Login'
|
||||||
import Join from './Join'
|
import Join from './Join'
|
||||||
|
import UserSettings from './UserSettings'
|
||||||
|
|
||||||
function nullComponent(props) {
|
function nullComponent(props) {
|
||||||
return null
|
return null
|
||||||
|
@ -42,7 +43,7 @@ export default function makeRoutes (currentUser) {
|
||||||
<Route path=":id" component={Notifications} />
|
<Route path=":id" component={Notifications} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="users">
|
<Route path="users">
|
||||||
<Route path=":id/edit" component={nullComponent} />
|
<Route path=":id/edit" component={UserSettings} />
|
||||||
<Route path="password" component={nullComponent} />
|
<Route path="password" component={nullComponent} />
|
||||||
<Route path="password/new" component={nullComponent} />
|
<Route path="password/new" component={nullComponent} />
|
||||||
<Route path="password/edit" component={nullComponent} />
|
<Route path="password/edit" component={nullComponent} />
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
import React, { Component } from react
|
|
||||||
|
|
||||||
class MyComponent extends Component {
|
|
||||||
render = () => {
|
|
||||||
return (
|
|
||||||
<div id="yield">
|
|
||||||
{ form_for @user, url: user_url, :html =>{ :multipart => true, :className => "edit_user centerGreyForm"} do |form| }
|
|
||||||
<h3>Edit Settings</h3>
|
|
||||||
<div className="userImage">
|
|
||||||
<div className="userImageDiv" onclick="Metamaps.Account.toggleChangePicture()">
|
|
||||||
{ image_tag @user.image.url(:ninetysix), :size => "84x84" }
|
|
||||||
<div className="editPhoto"></div>
|
|
||||||
</div>
|
|
||||||
<div className="userImageMenu">
|
|
||||||
<div className="userMenuArrow"></div>
|
|
||||||
<ul>
|
|
||||||
<li className="upload">
|
|
||||||
Upload Photo
|
|
||||||
{ hidden_field_tag "remove_image", "0" }
|
|
||||||
{ form.file_field :image }
|
|
||||||
{ form.label :image }
|
|
||||||
</li>
|
|
||||||
<li className="remove" onclick="Metamaps.Account.removePicture()">Remove</li>
|
|
||||||
<li className="cancel" onclick="Metamaps.Account.closeChangePicture()">Cancel</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div className="accountName" onclick="Metamaps.Account.changeName()">
|
|
||||||
<div className="nameEdit">{ @user.name }</div>
|
|
||||||
</div>
|
|
||||||
<div className="changeName">
|
|
||||||
{ form.label :name, "Name:", className: 'firstFieldText' }
|
|
||||||
{ form.text_field :name }
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{ form.label :email, "Email:", className: 'firstFieldText' }
|
|
||||||
{ form.email_field :email }
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{ form.label :emails_allowed, className: 'firstFieldText' do }
|
|
||||||
{ form.check_box :emails_allowed, className: 'inline' }
|
|
||||||
Send Metamaps notifications to my email.
|
|
||||||
{ end }
|
|
||||||
{ fields_for :settings, @user.settings do |settings| }
|
|
||||||
{ settings.label :follow_topic_on_created, className: 'firstFieldText' do }
|
|
||||||
{ settings.check_box :follow_topic_on_created, className: 'inline' }
|
|
||||||
Auto-follow topics you create.
|
|
||||||
{ end }
|
|
||||||
{ settings.label :follow_topic_on_contributed, className: 'firstFieldText' do }
|
|
||||||
{ settings.check_box :follow_topic_on_contributed, className: 'inline' }
|
|
||||||
Auto-follow topics you edit.
|
|
||||||
{ end }
|
|
||||||
{ settings.label :follow_map_on_created, className: 'firstFieldText' do }
|
|
||||||
{ settings.check_box :follow_map_on_created, className: 'inline' }
|
|
||||||
Auto-follow maps you create.
|
|
||||||
{ end }
|
|
||||||
{ settings.label :follow_map_on_contributed, className: 'firstFieldText' do }
|
|
||||||
{ settings.check_box :follow_map_on_contributed, className: 'inline' }
|
|
||||||
Auto-follow maps you edit.
|
|
||||||
{ end }
|
|
||||||
{ end }
|
|
||||||
</div>
|
|
||||||
<div className="changePass" onclick="Metamaps.Account.showPass()">Change Password</div>
|
|
||||||
<div className="toHide">
|
|
||||||
<div>
|
|
||||||
{ form.label :current_password, "Current Password:", :className => "firstFieldText" }
|
|
||||||
{ password_field_tag :current_password, params[:current_password] }
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{ form.label :password, "New Password:", :className => "firstFieldText" }
|
|
||||||
{ form.password_field :password, :autocomplete => :off}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{ form.label :password_confirmation, "Confirm New Password:", :className => "firstFieldText" }
|
|
||||||
{ form.password_field :password_confirmation, :autocomplete => :off}
|
|
||||||
</div>
|
|
||||||
<div className="noChangePass" onclick="Metamaps.Account.hidePass()">Oops, don't change password</div>
|
|
||||||
</div>
|
|
||||||
<div id="accountPageLoading"></div>
|
|
||||||
{ form.submit "Update", className: "update", onclick: "Metamaps.Account.showLoading()" }
|
|
||||||
<div className="clearfloat"></div>
|
|
||||||
{ end }
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MyComponent
|
|
Loading…
Reference in a new issue