Let Owners edit their Events in details-view

Resolved ticket #876997 (https://bugzilla.mozilla.org/show_bug.cgi?id=876997).
This commit is contained in:
Hike Danakian 2013-06-11 13:23:38 -07:00
Родитель ce49addade
Коммит 41f0c248e8
15 изменённых файлов: 494 добавлений и 345 удалений

Просмотреть файл

@ -1,11 +1,11 @@
@import "ui";
body#events .overlay-container {
body#events.map .overlay-container {
position: relative;
margin: 0px auto;
max-width: 980px;
}
body#events .map-overlay {
body#events.map .map-overlay {
position: absolute;
z-index: 1;
margin: 20px;
@ -165,7 +165,6 @@ body#events .map-overlay {
font-size: 13px;
}
.md-editor,input {
background: white;
outline: 0px;
border: 0.5px solid #444;
margin: 6px 4px;
@ -182,48 +181,6 @@ body#events .map-overlay {
margin-top: 8px;
margin-bottom: 4px;
}
.md-editor {
background: #222;
margin-left: -1px;
padding: 4px;
padding-top: 0px;
clear: left;
textarea {
height: 34ex;
padding: 8px 10px;
font-family: inherit;
font-size: 14px;
}
.md-preview {
min-height: 5ex;
padding: 8px 10px;
color: #333;
}
.md-header {
background: #222;
}
.btn-group {
display: inline-block;
}
button {
.ui-btn;
.clickable;
background: inherit;
border: 0px;
border-radius: 1px;
padding: 4px 8px;
color: #eee;
&:hover {
background: #fafafa;
text-shadow: none;
color: #222;
}
}
}
input[name="title"] {
min-width: 21em;
}
@ -264,8 +221,3 @@ body#events .map-overlay {
}
}
}
.ui-datepicker {
border: 1px solid #ddd;
margin-left: -34.5px;
margin-top: 11px;
}

Просмотреть файл

@ -136,4 +136,20 @@ body#events.details {
border-radius: 0px 0px 4px 4px;
}
form {
input {
border: 1px solid #ccc;
padding-left: 3px;
padding-left: 4px;
}
input[name="title"] {
padding-left: 10px;
font-weight: 300;
font-size: 35px;
}
input[name="address"] {
width: 21em;
}
}
}

Просмотреть файл

@ -13,7 +13,6 @@ body#events {
margin-top: 0px;
}
}
.clear { clear: both; }
.hidden { display: none; }
.clickable {
@ -33,3 +32,50 @@ body#events {
-ms-user-select: none;
user-select: none;
}
.ui-datepicker {
border: 1px solid #ddd;
margin-left: -34.5px;
margin-top: 11px;
}
.md-editor {
background: #222;
margin-left: -1px;
padding: 4px;
padding-top: 0px;
clear: left;
textarea {
height: 34ex;
padding: 8px 10px;
font-family: inherit;
font-size: 14px;
}
.md-preview {
min-height: 5ex;
padding: 8px 10px;
color: #333;
}
.md-header {
background: #222;
}
.btn-group {
display: inline-block;
}
button {
.ui-btn;
.clickable;
background: inherit;
border: 0px;
border-radius: 1px;
padding: 4px 8px;
color: #eee;
&:hover {
background: #fafafa;
text-shadow: none;
color: #222;
}
}
}

Просмотреть файл

@ -21,6 +21,14 @@ module.exports = function () {
+ '/' + filename
: this.client.url(filename)
},
delete: function (url) {
var match = url.match(/\/([^\/]+)\/?$/);
if (match) {
this.client.del(match[1]);
return true;
} else console.error("Error: S3 url ("+url+") seems to be invalid.");
return false;
},
client: noxmox[s3_mode].createClient(s3_conf)
};
};

Просмотреть файл

@ -28,64 +28,21 @@ module.exports = function (init) {
},
create: function(req, res)
{
var event = req.body.event || req.body;
console.log(event);
var fields = { // undefined fields are required
title: undefined,
description: undefined,
address: undefined,
organizer: undefined,
organizerId: undefined,
latitude: null,
longitude: null,
attendees: 3,
beginDate: null,
endDate: null,
beginTime: null,
endTime: null,
registerLink: null
};
var required = [ 'title', 'description', 'latitude', 'longitude', 'address' ];
var event = event_input_filter(req.body.event || req.body);
if (!event)
return res.reply(400, 'Invalid Event provided');
if (!(event.organizer = req.session.email))
return res.reply(401, 'Log in to create Events');
event.organizerId = req.session.username;
if (event.picture) {
var match = event.picture.match(/^data:(image\/[\w+-]+);.*?base64,(.*)/);
event.picture = match ? {
type: match[1],
data: new Buffer(match[2], 'base64')
} : null
}
// pre-process the Date/Time fields
['begin', 'end'].forEach(function (pfx) {
datetime_transform('Date', function (val) {
return new Date(val.split('-'));
});
datetime_transform('Time', function (val) {
var ts = val.split(':');
return new Date(0, 0, 0, ts[0], ts[1]);
});
function datetime_transform(f, transform) {
var dtf = pfx + f;
event[dtf] = (function(event) {
if (!event[dtf]) return null;
var new_time = transform(event[dtf]);
return new_time != "Invalid Date" ? new_time : null;
})(event)
}
});
function empty(x) { return x === '' || x === undefined }
var trns_event = {};
Object.keys(fields).forEach(function (f) {
trns_event[f] = empty(event[f]) ? fields[f] : event[f];
});
if (!required.every(function (f) { return !empty(trns_event[f]) }))
return res.reply(400, 'Invalid Event provided');
var picture = event.picture;
Event.create(trns_event, Object.keys(fields)).success(function (event) {
delete event.picture;
var fields = ['title', 'description', 'address', 'latitude',
'longitude', 'attendees', 'beginDate', 'endDate', 'beginTime',
'endTime', 'registerLink', 'organizer', 'organizerId'];
Event.create(trns_event, fields).success(function (event) {
if (picture) {
var filename = uuid.v4();
var s3_req = s3.client.put(filename, {
@ -108,48 +65,60 @@ module.exports = function (init) {
},
details: function(req, res)
{
Event.find(req.params.id).success(function (event) {
if (!event) return res.reply(404, 'Event not found');
fetch_event(req, function (event) {
res.format({
json: function () { res.reply(200, { event: event }) },
html: function () {
function fmtDate(x) { return new Date(x).toDateString() }
function fmtTime(x) { return new Date(x).toTimeString().split(' ')[0] }
var evt = {};
for (var p in event) switch(p) {
case 'beginDate':
case 'endDate':
evt[p] = fmtDate(event[p]);
break;
case 'beginTime':
case 'endTime':
evt[p] = fmtTime(event[p]);
break;
case 'description':
evt[p] = markdown.toHTML(event[p]);
default:
evt[p] = event[p];
}
res.reply('details', { event: evt });
res.reply('details', { event: event_output_filter(event) });
}
});
});
},
update: function(req, res)
change: function(req, res)
{
Event.find(req.params.id).success(function (event) {
event.updateAttributes(req.params.id).success(function () {
res.reply(200, 'Event updated', { event: event });
console.log(req.body.event || req.body);
var changes = event_input_filter(req.body.event || req.body, false, true, false);
console.log(changes);
if (!changes)
return res.reply(400, 'Invalid Event changes requested');
var allowed = [ 'title', 'description', 'address', 'latitude',
'longitude', 'attendees', 'beginDate', 'endDate',
'beginTime', 'endTime', 'registerLink' ];
Object.keys(changes).forEach(function (k) {
if (empty(changes[k]))
delete changes[k];
});
var picture = changes.picture;
fetch_event(req, function (event) {
event.updateAttributes(changes, allowed).success(function () {
if (picture) {
var filename = uuid.v4();
var s3_req = s3.client.put(filename, {
'Content-Length': picture.data.length,
'Content-Type': picture.type,
'x-amz-acl': 'public-read'
});
s3_req.on('response', function(s3_res) {
if (s3_res.statusCode === 200)
s3.delete(event.picture);
event.updateAttributes({
picture: s3.url(filename)
});
});
s3_req.end(picture.data);
}
res.reply(200, 'Event modified', { event: event });
});
}).error(function (err) {
res.reply(404, 'Event not found');
});
},
destroy: function(req, res)
{
Event.find(req.params.id).success(function (event) {
var picture = event.picture;
event.destroy().success(function () {
if (picture)
s3.delete(picture);
res.reply(200, 'Event deleted');
});
}).error(function (err) {
@ -157,4 +126,103 @@ module.exports = function (init) {
});
}
};
function empty(x) { return x === '' || x === undefined }
function event_input_filter(event, set_defaults, do_transforms, check_required) {
if (!event) return null;
set_defaults = set_defaults === undefined ? true : set_defaults;
do_transforms = do_transforms === undefined ? true : do_transforms;
check_required = check_required === undefined ? true : check_required;
var fields = { // undefined fields are required
title: undefined,
description: undefined,
address: undefined,
latitude: null,
longitude: null,
attendees: 3,
beginDate: null,
endDate: null,
beginTime: null,
endTime: null,
registerLink: null
};
var required = [ 'title', 'description', 'latitude', 'longitude', 'address' ];
var transforms = {
picture: function (event) {
if (!event.picture) return;
var match = event.picture.match(/^data:(image\/[\w+-]+);.*?base64,(.*)/);
return match ? {
type: match[1],
data: new Buffer(match[2], 'base64')
} : undefined
}
};
// pre-process the Date/Time fields
['begin', 'end'].forEach(function (pfx) {
datetime_transform('Date', function (val) {
return new Date(val.split('-'));
});
datetime_transform('Time', function (val) {
var ts = val.split(':');
return new Date(0, 0, 0, ts[0], ts[1]);
});
function datetime_transform(f, transform) {
var dtf = pfx + f;
transforms[dtf] = function(event) {
if (!event[dtf]) return;
var new_time = transform(event[dtf]);
if (new_time != "Invalid Date")
return new_time;
};
}
});
var evt = {};
if (do_transforms)
Object.keys(transforms).forEach(function (f) {
evt[f] = transforms[f](event);
});
console.log(evt);
Object.keys(fields).forEach(function (f) {
if (!(f in evt)) evt[f] = event[f];
});
if (set_defaults)
Object.keys(fields).forEach(function (f) {
evt[f] = empty(event[f]) ? fields[f] : event[f];
});
if (check_required)
evt = required.every(function (f) { return !empty(evt[f]) }) ? evt : null;
return evt
}
function event_output_filter(event) {
function fmtDate(x) { return new Date(x).toDateString() }
function fmtTime(x) { return new Date(x).toTimeString().split(' ')[0] }
var evt = {};
for (var p in event) switch(p) {
case 'beginDate':
case 'endDate':
evt[p] = fmtDate(event[p]);
break;
case 'beginTime':
case 'endTime':
evt[p] = fmtTime(event[p]);
break;
case 'description':
evt[p] = markdown.toHTML(event[p]);
default:
evt[p] = event[p];
}
return evt;
}
function fetch_event(req, success) {
return Event.find(req.params.id).success(function (event) {
if (!event) return req.res.reply(404, 'Event not found');
success(event);
}).error(function (err) {
req.res.reply(404, 'Event not found');
});
}
};

Просмотреть файл

@ -38,6 +38,7 @@ exports.init = function (app, nunjucksEnv, lessMiddleware, app_root) {
// Controllers
ctx.controllers = require('./controllers').call(ctx, app);
app.use(express.methodOverride());
process.nextTick(require('./routes').bind(ctx, ctx.controllers, app));
// Handy shortcuts

Просмотреть файл

@ -3,9 +3,10 @@ module.exports = function (C, app) {
app[method.toLowerCase()](path + '.:format?', action);
}
route( 'GET', '/events', C.Events.index );
route( 'GET', '/events/:id', C.Events.details );
route( 'POST', '/events', C.Events.create );
route( 'PUT', '/events/:id', C.Events.update );
route( 'DELETE', '/events/:id', C.Events.destroy );
route( 'GET', '/events', C.Events.index );
route( 'GET', '/events/:id', C.Events.details );
route( 'POST', '/events', C.Events.create );
route( 'PATCH', '/events/:id', C.Events.change );
//route( 'PUT', '/events/:id', C.Events.update );
route( 'DELETE', '/events/:id', C.Events.destroy );
};

Просмотреть файл

@ -0,0 +1,17 @@
define(['jquery', 'forms', 'domReady!'],
function ($, forms) {
var $editForm = $('form#edit-event');
function toggleEditMode() {
$('.show').toggleClass('hidden');
$('.edit').toggleClass('hidden');
}
$editForm.find('button#edit-mode').click(function(ev) {
toggleEditMode();
});
$editForm.find('button#cancel-edit').click(function(ev) {
toggleEditMode();
});
$editForm.find('button#delete-event').click(function(ev) {
// TODO: show modal with confirmation
});
});

Просмотреть файл

@ -1,146 +1,10 @@
define(['jquery', 'model', '../base/ui', 'bootstrap-markdown', 'jquery.timepicker', 'jquery-ui.datepicker', 'domReady!'],
function ($, EventModel, UI) { return function (mapMaker) {
$.event.props.push('dataTransfer');
var $createForm = $('form#create-event');
var $findForm = $('form#find-event');
define(['jquery', '../base/ui', 'bootstrap-markdown', 'jquery.timepicker', 'jquery-ui.datepicker', 'domReady!'],
function ($, UI) {
var $fileInput = $createForm.find('input[type="file"]');
var $uploadDiv = $createForm.find('#image-upload');
$uploadDiv.on("click", function(ev) {
ev.preventDefault();
$fileInput.click();
}).on("dragenter dragover drop", function(ev) {
ev.preventDefault();
ev.stopPropagation();
}).on("drop", function(ev) {
ev.preventDefault();
ev.stopPropagation();
handleImg(ev.dataTransfer.files[0]);
});
$fileInput.on("change", function (ev) {
handleImg(this.files[0]);
});
// based on MDN example
function handleImg(file) {
if (file.type.match(/^image\//)) {
if (!$uploadDiv._prev_text)
$uploadDiv._prev_text = $uploadDiv.text();
$uploadDiv.html("<img />");
var img = $uploadDiv.find("img")[0];
img.file = file;
var reader = new FileReader();
reader.onload = (function(img) {
return function(ev) {
img.src = ev.target.result;
$createForm.find('input[name="picture"]').prop('value', img.src);
};
})(img);
reader.readAsDataURL(file);
}
}
$createForm.find('button[type="submit"]').click(function (ev) {
ev.preventDefault();
$createForm.submit();
});
$createForm.on("submit", function(ev) {
ev.preventDefault();
var form_fields = $createForm.serializeArray();
var data = { event: {} };
form_fields.forEach(function (f) {
if (f.name) switch (f.name) {
case '_csrf':
data[f.name] = f.value;
break;
case 'address': // TODO: split address into two lines
default:
data.event[f.name] = f.value;
}
});
$.post($createForm.attr('action'), data, function (data) {
console.log(data.event);
if (data.event) {
toggleCreateForm();
mapMaker.addMarker(new EventModel(data.event));
}
}, 'json');
return false;
});
$findForm.find('button[type="submit"]').click(function (ev) {
ev.preventDefault();
$findForm.submit();
});
var $when = $findForm.find('input[name="find-when"]');
$when.blur(function(ev) { $findForm.submit() });
mmm = mapMaker;
$findForm.on("submit", function(ev) {
ev.preventDefault();
EventModel.all(function (models) {
mapMaker.clearMarkers();
var targetDateStr = $when[0].value;
if (!targetDateStr)
mapMaker.dropPins(models, false);
else {
var targetDate = new Date(targetDateStr.split('-'));
mapMaker.dropPins(models, false, function (model) {
var beginDate = new Date(model.beginDate),
endDate = new Date(model.endDate);
if (model.beginDate && model.endDate)
return beginDate <= targetDate
&& endDate >= targetDate
else if (beginDate)
return beginDate <= targetDate
else if (endDate)
return endDate >= targetDate
else return true
});
}
});
});
// setup form toggle button
function toggleCreateForm() {
var $select = $('select[name="attendees"]');
$createForm[0].reset();
$select.next('.ui-select').remove();
UI.select($select);
$createForm.find('input[name="picture"]').prop('value', '');
$uploadDiv.find('> img').prop('src', '');
$uploadDiv.text($uploadDiv._prev_text);
$createForm.toggleClass('hidden');
$("#add-event-button").toggleClass('hidden');
}
$(".formExpandButton").click(function(ev) {
ev.preventDefault();
toggleCreateForm();
});
mapMaker.setupAutocomplete($('input[name="address"]')[0], false, function (place) {
var loc = { latitude: place.geometry.location.lat(),
longitude: place.geometry.location.lng() };
for (var k in loc)
$('form#create-event').find('input[name="'+k+'"]').val(loc[k]);
});
mapMaker.setupAutocomplete($('input[name="find-where"]')[0], true, function (place) {
if (place.geometry) {
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
this.google_map.fitBounds(place.geometry.viewport);
} else {
this.google_map.setCenter(place.geometry.location);
this.google_map.setZoom(14);
}
}
});
$createForm.find('.datepicker').datepicker().each(function(i, elem) {
$('.datepicker').datepicker().each(function(i, elem) {
$(elem).next('.icon').click(function () { $(elem).focus() });
});
$createForm.find('.timepicker').timepicker().each(function(i, elem) {
$('.timepicker').timepicker().each(function(i, elem) {
$(elem).next('.icon').click(function () { $(elem).focus() });
}).on('showTimepicker', function () {
var $parent = $(this).parent();
@ -150,11 +14,7 @@ function ($, EventModel, UI) { return function (mapMaker) {
});
var $beginTime = $('[name="beginTime"]'),
$endTime = $('[name="endTime"]');
$beginTime.timepicker({
appendTo: function (elem) { return $(elem).parent() }
});
$endTime.timepicker({
appendTo: function (elem) { return $(elem).parent() },
durationTime: function () {
var beginTime = $beginTime.timepicker('getTime');
return beginTime ? beginTime : '0:00am';
@ -162,7 +22,58 @@ function ($, EventModel, UI) { return function (mapMaker) {
showDuration: true
});
EventModel.all(function (models) { mapMaker.dropPins(models) });
window.scroll(0,0);
}})
return {
setupImageUpload: function ($form) {
var $fileInput = $form.find('input[type="file"]');
var $uploadDiv = $form.find('#image-upload');
$.event.props.push('dataTransfer');
$uploadDiv.on("click", function(ev) {
ev.preventDefault();
$fileInput.click();
}).on("dragenter dragover drop", function(ev) {
ev.preventDefault();
ev.stopPropagation();
}).on("drop", function(ev) {
ev.preventDefault();
ev.stopPropagation();
handleImg(ev.dataTransfer.files[0]);
});
$fileInput.on("change", function (ev) {
handleImg(this.files[0]);
});
// based on MDN example
function handleImg(file) {
if (file.type.match(/^image\//)) {
if (!$uploadDiv._prev_text)
$uploadDiv._prev_text = $uploadDiv.text();
$uploadDiv.html("<img />");
var img = $uploadDiv.find("img")[0];
img.file = file;
var reader = new FileReader();
reader.onload = (function(img) {
return function(ev) {
img.src = ev.target.result;
$form.find('input[name="picture"]').prop('value', img.src);
};
})(img);
reader.readAsDataURL(file);
}
}
$form.on('reset', function () {
$uploadDiv.find('> img').prop('src', '');
$uploadDiv.text($uploadDiv._prev_text);
$form.find('input[name="picture"]').prop('value', '');
});
},
setupSelectUI: function ($form) {
$form.on('reset', function () {
var $select = $('select[name="attendees"]');
$select.next('.ui-select').remove();
UI.select($select);
});
},
};
})

Просмотреть файл

@ -1,5 +1,5 @@
require.config({
deps: ['main', 'jquery.css3finalize', 'jquery-ui.datepicker', 'bootstrap-markdown'],
deps: ['main', 'jquery.css3finalize', 'bootstrap-markdown', 'jquery.timepicker', 'jquery-ui.datepicker'],
paths: {
'html': '/js/html',
'base': '/js/base',

Просмотреть файл

@ -0,0 +1,97 @@
define(['jquery', 'model', 'forms', 'bootstrap-markdown', 'domReady!'],
function ($, EventModel, forms) { return function (mapMaker) {
var $findForm = $('form#find-event');
$findForm.find('button[type="submit"]').click(function (ev) {
ev.preventDefault();
$findForm.submit();
});
var $when = $findForm.find('input[name="find-when"]');
$when.blur(function(ev) { $findForm.submit() });
$findForm.on("submit", function(ev) {
ev.preventDefault();
EventModel.all(function (models) {
mapMaker.clearMarkers();
var targetDateStr = $when[0].value;
if (!targetDateStr)
mapMaker.dropPins(models, false);
else {
var targetDate = new Date(targetDateStr.split('-'));
mapMaker.dropPins(models, false, function (model) {
var beginDate = new Date(model.beginDate),
endDate = new Date(model.endDate);
if (model.beginDate && model.endDate)
return beginDate <= targetDate
&& endDate >= targetDate
else if (beginDate)
return beginDate <= targetDate
else if (endDate)
return endDate >= targetDate
else return true
});
}
});
});
var $createForm = $('form#create-event');
$createForm.on('submit', function(ev) {
ev.preventDefault();
var form_fields = $createForm.serializeArray();
var data = { event: {} };
form_fields.forEach(function (f) {
if (f.name) switch (f.name) {
case '_csrf':
data[f.name] = f.value;
break;
case 'address': // TODO: split address into two lines
default:
data.event[f.name] = f.value;
}
});
$.post($createForm.attr('action'), data, function (data) {
console.log(data.event);
if (data.event) {
toggleCreateForm();
mapMaker.addMarker(new EventModel(data.event));
}
}, 'json');
return false;
});
var $beginTime = $createForm.find('[name="beginTime"]'),
$endTime = $createForm.find('[name="endTime"]');
$beginTime.timepicker({ appendTo: function (elem) { return $(elem).parent() } });
$endTime.timepicker({ appendTo: function (elem) { return $(elem).parent() } });
forms.setupImageUpload($createForm);
forms.setupSelectUI($createForm);
// setup form toggle button
function toggleCreateForm() {
$createForm[0].reset();
$createForm.toggleClass('hidden');
$("#add-event-button").toggleClass('hidden');
}
$(".formExpandButton").click(function(ev) {
ev.preventDefault();
toggleCreateForm();
});
mapMaker.setupAutocomplete($('input[name="address"]')[0], false, function (place) {
var loc = { latitude: place.geometry.location.lat(),
longitude: place.geometry.location.lng() };
for (var k in loc)
$createForm.find('input[name="'+k+'"]').val(loc[k]);
});
mapMaker.setupAutocomplete($('input[name="find-where"]')[0], true, function (place) {
if (place.geometry) {
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
this.google_map.fitBounds(place.geometry.viewport);
} else {
this.google_map.setCenter(place.geometry.location);
this.google_map.setZoom(14);
}
}
});
EventModel.all(function (models) { mapMaker.dropPins(models) });
}});

Просмотреть файл

@ -6,7 +6,7 @@ require.config({
'markerclusterer': 'map/markerclusterer',
}
});
define(['jquery', 'google', 'map/map_maker', 'forms'],
define(['jquery', 'google', 'map/map_maker', 'map/forms'],
function ($, google, MapMaker, EventForms) {
var defaultZoom = 13;

Просмотреть файл

@ -3,62 +3,93 @@
{% block title %}{{ event.title }}{% endblock %}
{% block body %}
<div class="ui-wrapper ui-body">
{{ super() }}
<form id="edit-event" action="/events/{{ event.id }}" method="POST">
<input name="_csrf" value="{{ csrf }}" type="hidden">
<div class="ui-wrapper ui-body">
<div id="details-pane" class="ui-section">
<div class="gallery-sidebar">
{% if event.picture %}
<img id="event-picture" src="{{ event.picture }}" onerror="this.style.display='none'" />
{% endif %}
{% if event.registerLink %}
<div id="event-registration">
<a id="registerLink" href="{{ event.registerLink }}">Sign up for the event <span class="icon-chevron-right"></span></a>
<p>This link will take you to an external event registration service, such as Eventbrite.</p>
<div class="gallery-sidebar">
{% if event.picture %}
<img id="event-picture" src="{{ event.picture }}" onerror="this.style.display='none'" />
{% endif %}
{% if event.registerLink %}
<div id="event-registration">
<a id="registerLink" href="{{ event.registerLink }}">Sign up for the event <span class="icon-chevron-right"></span></a>
<p>This link will take you to an external event registration service, such as Eventbrite.</p>
</div>
{% endif %}
</div>
<span><div id="event-description">
<h1 class="show">{{ event.title }}</h1>
<span class="edit hidden">
<input type="text" name="title" placeholder="{{ event.title }}" />
</span>
<div id="event-whenwhere">
<div class="temporal-local">
<img class="calendar-icon" src="/img/map/calendar.png" />
<div class="datetime-range">
<span class="show">
<div>
{{ event.beginDate }}
{% if event.beginDate and event.endDate %} - {% endif %}
{{ event.endDate }}
</div>
<div>
{{ event.beginTime }}
{% if event.beginTime and event.endTime %} - {% endif %}
{{ event.endTime }}
</div>
</span>
<span class="edit hidden">
<div> <input type="text" name="beginDate" class="datepicker" placeholder="{{ event.beginDate }}" />
- <input type="text" name="endDate" class="datepicker" placeholder="{{ event.endDate }}" />
</div>
<div> <input type="text" name="beginTime" class="timepicker" placeholder="{{ event.beginTime }}" />
- <input type="text" name="endTime" class="timepicker" placeholder="{{ event.endTime }}" />
</div>
</span>
</div>
</div>
<div class="temporal-local">
<img class="pin-icon" src="/img/map/pin-event-red.png" />
{% if event.address %}
<span class="show">
<div class="address">{{ event.address }}</div>
</span>
{% endif %}
<span class="edit hidden">
<input type="text" name="address" class="edit address" placeholder="{{ event.address }}" />
</span>
</div>
</div>
<span><div id="event-description">
<h1>{{ event.title }}</h1>
<div id="event-whenwhere">
<div class="temporal-local">
{% if event.beginDate or event.endDate %}
<img class="calendar-icon" src="/img/map/calendar.png" />
{% endif %}
<div class="datetime-range">
<div> {{ event.beginDate }}
{% if event.beginDate and event.endDate %} - {% endif %}
{{ event.endDate }} </div>
<div> {{ event.beginTime }}
{% if event.beginTime and event.endTime %} - {% endif %}
{{ event.endTime }} </div>
</div>
</div>
<div class="temporal-local">
{% if event.address %}
<img class="pin-icon" src="/img/map/pin-event-red.png" />
<div class="address">
<div> {{ event.address }} </div>
<div> {{ event.city }} </div>
</div>
{% endif %}
</div>
</div>
{% if event.organizer %}
<div id="event-organizer">
<img src="http://lorempixel.com/25/25/people/" />
<span>Organized by <strong class="organizer">{{ event.organizerId }}</strong></span>
</div>
{% endif %}
{% if email and event.organizer == email %}
<button id="edit-event" class="owner-btn ui-btn">Edit</button>
<button id="delete-event" class="owner-btn ui-btn">Delete</button>
{% endif %}
<p>{{ event.description }}</p>
<div id="event-organizer">
<img src="{{ event.organizerImg }}" />
<span>Organized by <strong class="organizer">{{ event.organizerId }}</strong></span>
</div>
{% if email and event.organizer == email %}
<div>
<span class="show">
<button id="edit-mode" type="button" class="owner-btn ui-btn">Edit</button>
</span>
<span class="edit hidden">
<button id="save-edit" class="owner-btn ui-btn"
type="submit" name="_method" value="PATCH">Save</button>
<button id="cancel-edit" type="button" class="owner-btn ui-btn">Cancel</button>
<button id="delete-event" class="owner-btn ui-btn"
type="submit" name="_method" value="DELETE">Delete</button>
</span>
</div>
{% endif %}
<p class="show">{{ event.description }}</p>
<span class="edit hidden">
<textarea name="description" data-provide="markdown">{{ event.description }}</textarea>
</span>
<div class="clear"></div>
</div></span>
<div class="clear"></div>
</div></span>
</div>
<div id="bottom-stripe"></div>
</div>
</div>
</form>
{% endblock %}

Просмотреть файл

@ -2,11 +2,18 @@
{% include 'macros.html' %}
{% block title %}{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet" href="/ext/css/jquery-ui-1.10.3.custom.css" />
<link rel="stylesheet" href="/ext/css/jquery.timepicker.css">
<link rel="stylesheet" href="/ext/css/bootstrap-markdown.css">
<link rel="stylesheet" href="/css/events.css">
{% endblock %}
{% block body %}{% endblock %}
{% block body %}
{{ gallery() }}
{% endblock %}
{% block require_main %}/js/events/index{% endblock %}
{% block scripts %}

Просмотреть файл

@ -1,21 +1,15 @@
{% extends "events/layout.html" %}
{% block title %}Event Map{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet" href="/ext/css/jquery-ui-1.10.3.custom.css" />
<link rel="stylesheet" href="/ext/css/jquery.timepicker.css">
<link rel="stylesheet" href="/ext/css/bootstrap-markdown.css">
{% endblock %}
{% block body %}
{{ super() }}
<div class="overlay-container">
<div class="map-overlay">
<form id="find-event" action="/events" method="GET">
<h2><span class="icon-search"></span> Find an event</h2>
<input name="_csrf" type="hidden" value="{{ csrf_token }}" />
<input name="_csrf" type="hidden" value="{{ csrf }}" />
<input name="find-where" type="text" placeholder="Where?" />
<input name="find-when" type="text" placeholder="When?" class="datepicker" />
<button type="submit"><span class="icon-chevron-right"></span></button>
@ -25,7 +19,7 @@
<h2 class='formExpandButton'><span class="icon-plus"></span> Add an event</h2>
</div>
<form id="create-event" action="/events" method="POST" enctype="multipart/form-data" class='hidden'>
<form id="create-event" action="/events" method="POST" class='hidden'>
<h2 class='formExpandButton'><span class="icon-remove"></span> Add an event</h2>
<fieldset>
<label for="title"> Name your event </label>
@ -86,7 +80,7 @@
<input name="picture" type="hidden" />
<div id="image-upload">Upload an image</div>
</div>
<input name="_csrf" type="hidden" value="{{ csrf_token }}" />
<input name="_csrf" type="hidden" value="{{ csrf }}" />
<button type="submit"><span class="icon-plus"></span> Submit your event</button>
</fieldset>