Skip to content

Commit ad053fd

Browse files
Merge pull request #410 from DemocracyLab/peter/findevents
Peter/findevents
2 parents abc50e7 + bc4de96 commit ad053fd

23 files changed

+1345
-49
lines changed

civictechprojects/forms.py

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from dateutil.parser import parse
21
from django.forms import ModelForm
32
from django.core.exceptions import PermissionDenied
43
from django.utils import timezone
54
from .models import Project, ProjectLink, ProjectFile, ProjectPosition, FileCategory, Event, Group
65
from .sitemaps import SitemapPages
76
from democracylab.emails import send_project_creation_notification, send_group_creation_notification
87
from democracylab.models import get_request_contributor
8+
from common.helpers.date_helpers import parse_front_end_datetime
99
from common.helpers.form_helpers import is_creator_or_staff, is_co_owner_or_staff, read_form_field_string, read_form_field_boolean, \
1010
merge_json_changes, merge_single_file, read_form_field_tags, read_form_field_datetime, read_form_fields_point
1111

@@ -87,48 +87,24 @@ class Meta:
8787
fields = '__all__'
8888

8989
@staticmethod
90-
def create_event(request):
91-
90+
def create_or_edit_event(request, event_id):
9291
form = EventCreationForm(request.POST)
93-
# TODO: Form validation
94-
event = Event.objects.create(
95-
event_creator=get_request_contributor(request),
96-
event_date_created=timezone.now(),
97-
event_name=form.data.get('event_name'),
98-
event_location=form.data.get('event_location'),
99-
event_rsvp_url=form.data.get('event_rsvp_url'),
100-
event_date_start=parse(form.data.get('event_date_start'), fuzzy=True),
101-
event_date_end=parse(form.data.get('event_date_end'), fuzzy=True),
102-
event_short_description=form.data.get('event_short_description'),
103-
is_created=True,
104-
is_searchable=True
105-
)
106-
event = Event.objects.get(id=event.id)
107-
108-
merge_single_file(event, form, FileCategory.THUMBNAIL, 'event_thumbnail_location')
109-
110-
event.save()
111-
return event
112-
113-
@staticmethod
114-
def delete_event(request, event_id):
115-
event = Event.objects.get(id=event_id)
116-
117-
if not is_creator_or_staff(request.user, event):
118-
raise PermissionDenied()
119-
120-
event.delete()
121-
122-
123-
@staticmethod
124-
def edit_event(request, event_id):
125-
event = Event.objects.get(id=event_id)
92+
if event_id is not None:
93+
event = Event.objects.get(id=event_id)
94+
else:
95+
event = Event.objects.create(
96+
event_creator=get_request_contributor(request),
97+
event_date_created=timezone.now(),
98+
event_name=form.data.get('event_name'),
99+
event_date_start=parse_front_end_datetime(form.data.get('event_date_start')),
100+
event_date_end=parse_front_end_datetime(form.data.get('event_date_end')),
101+
is_created=False,
102+
is_searchable=True
103+
)
126104

127105
if not is_co_owner_or_staff(request.user, event):
128106
raise PermissionDenied()
129-
130-
form = ProjectCreationForm(request.POST)
131-
107+
132108
read_form_field_string(event, form, 'event_agenda')
133109
read_form_field_string(event, form, 'event_description')
134110
read_form_field_string(event, form, 'event_short_description')
@@ -144,15 +120,24 @@ def edit_event(request, event_id):
144120
read_form_field_boolean(event, form, 'is_created')
145121

146122
read_form_field_tags(event, form, 'event_legacy_organization')
147-
123+
148124
event.event_date_modified = timezone.now()
149125

150126
merge_single_file(event, form, FileCategory.THUMBNAIL, 'event_thumbnail_location')
151127

152128
event.save()
153-
129+
154130
return event
155131

132+
@staticmethod
133+
def delete_event(request, event_id):
134+
event = Event.objects.get(id=event_id)
135+
136+
if not is_creator_or_staff(request.user, event):
137+
raise PermissionDenied()
138+
139+
event.delete()
140+
156141

157142
class GroupCreationForm(ModelForm):
158143
class Meta:
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
.FindEventsController-topsplash .SplashScreen-content {
2+
padding-bottom: 3rem;
3+
}
4+
5+
.EventCardContainer-section-header {
6+
margin-top: 1.25rem;
7+
}
8+
9+
.EventCard-root {
10+
background-color: $color-background-light;
11+
border: 1px solid $color-grey-frame-border;
12+
color: $color-text-dark;
13+
width: 100%;
14+
}
15+
16+
// only round corners for top edge of first, bottom edge of last item per day grouping
17+
.EventCard-root:first-of-type {
18+
border-top-left-radius: 8px;
19+
border-top-right-radius: 8px;
20+
}
21+
.EventCard-root:last-of-type {
22+
border-bottom-right-radius: 8px;
23+
border-bottom-left-radius: 8px;
24+
}
25+
26+
// avoid double border for days with multiple events (thus multiple cards)
27+
.EventCard-root:nth-of-type(n+2) {
28+
border-top: none;
29+
}
30+
31+
32+
.FindEventsController-topsplash h1 {
33+
font-size: 4rem;
34+
}
35+
.EventCard-root h2 {
36+
font-size: 22px;
37+
margin: 22px 0 12px 0;
38+
}
39+
.EventCard-root h4 {
40+
font-size: 16px;
41+
margin-bottom: 16px;
42+
color: $color-text-grey;
43+
}
44+
.EventCard-dateheader, .EventCard-day-container {
45+
width: 100%;
46+
}
47+
.EventCard-dateheader {
48+
margin-top: 2rem;
49+
font-size: 24px;
50+
font-weight: 500;
51+
}
52+
.EventCard-info {
53+
display: flex;
54+
flex-direction: column;
55+
}
56+
.EventCard-info li {
57+
font-size: 18px;
58+
}
59+
.EventCard-info li i {
60+
font-size: 13px; /* ratio determined, should be standardized */
61+
margin-right: 5px;
62+
}
63+
.EventCard-root a {
64+
text-decoration: none;
65+
color: $color-text-dark;
66+
display: grid;
67+
grid-template-columns: auto;
68+
grid-template-rows: auto;
69+
height: 100%;
70+
}
71+
// margin-bottom because we don't have pagination, keeping cards off the edge of the footer
72+
.EventCards-card-container {
73+
margin-bottom: 3rem;
74+
}
75+
.EventCard-info, .EventCard-time {
76+
margin-left: 0.5rem;
77+
}
78+
79+
.EventCard-logo {
80+
grid-column: 1;
81+
grid-row: 1;
82+
display: grid;
83+
}
84+
.EventCard-url-text {
85+
overflow: hidden;
86+
text-overflow: ellipsis;
87+
white-space: nowrap;
88+
margin: auto;
89+
}
90+
.EventCard-logo img {
91+
max-width: 98%;
92+
display: block;
93+
margin: 2px auto; /* handles rounded edges better to push it off the top a touch */
94+
}
95+
.EventCard-info {
96+
grid-column: 1;
97+
grid-row: 2;
98+
overflow-wrap: break-word;
99+
}
100+
.EventCard-info ul {
101+
color: $color-text-grey;
102+
list-style-type: none;
103+
font-size: 0.875rem;
104+
padding: 0;
105+
}
106+
.EventCard-info li {
107+
margin-top: 0.25rem;
108+
display: block;
109+
}
110+
.EventCard-time {
111+
grid-column: 1;
112+
grid-row: 3;
113+
h2 {
114+
font-weight: 400;
115+
}
116+
}
117+
118+
@include media-breakpoint-up(md) {
119+
.EventCard-root a {
120+
grid-template-columns: 37% 48% 15%;
121+
grid-template-rows: 100%;
122+
}
123+
.EventCard-logo {
124+
grid-column: 1;
125+
grid-row: 1;
126+
}
127+
.EventCard-info {
128+
grid-column: 2;
129+
grid-row: 1;
130+
}
131+
.EventCard-info ul {
132+
margin-top: auto;
133+
}
134+
.EventCard-time {
135+
grid-column: 3;
136+
grid-row: 1;
137+
margin: 0 8px 0 auto;
138+
}
139+
.EventCard-logo img {
140+
margin: auto;
141+
}
142+
}

civictechprojects/static/css/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,4 @@
9090
@import 'partials/LiveEvent';
9191
@import 'partials/CreateForm';
9292
@import 'partials/ApproveGroupsSection';
93+
@import 'partials/FindEventController';

civictechprojects/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def event_create(request):
233233

234234
event = None
235235
try:
236-
event = EventCreationForm.create_event(request)
236+
event = EventCreationForm.create_or_edit_event(request, None)
237237
except PermissionDenied:
238238
return HttpResponseForbidden()
239239
return JsonResponse(event.hydrate_to_json())
@@ -245,7 +245,7 @@ def event_edit(request, event_id):
245245

246246
event = None
247247
try:
248-
event = EventCreationForm.edit_event(request, event_id)
248+
event = EventCreationForm.create_or_edit_event(request, event_id)
249249
except PermissionDenied:
250250
return HttpResponseForbidden()
251251

common/components/chrome/MainHeader.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class MainHeader extends React.Component<{||}, State > {
117117
</Navbar>
118118
)
119119
}
120-
120+
121121
_renderEventNavItems(): ?React$Node {
122122
const eventLinks: Array<React$Node> = [];
123123
if(CurrentUser.isStaff()) {
@@ -126,6 +126,7 @@ class MainHeader extends React.Component<{||}, State > {
126126
if(window.EVENT_URL) {
127127
eventLinks.push(<NavDropdown.Item href={_.unescape(window.EVENT_URL)}>Upcoming Event</NavDropdown.Item>);
128128
}
129+
eventLinks.push(this._renderNavDropdownItem(Section.FindEvents, "Find Events"));
129130
return !_.isEmpty(eventLinks)
130131
? (
131132
<NavDropdown title="Events" id="nav-events">

common/components/componentsBySection/CreateEvent/EventPreviewForm.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ import React from "react";
44
import DjangoCSRFToken from "django-react-csrftoken";
55
import {OnReadySubmitFunc} from "./EventFormCommon.jsx";
66
import AboutEventDisplay from "./AboutEventDisplay.jsx";
7+
import type {EventData} from "../../utils/EventAPIUtils.js";
78

89
type Props = {|
9-
event: ?ProjectDetailsAPIData,
10+
project: ?EventData,
1011
readyForSubmit: OnReadySubmitFunc
1112
|};
1213

1314
/**
1415
* Shows preview for project before finalizing
1516
*/
16-
class ProjectPreviewForm extends React.PureComponent<Props> {
17+
class EventPreviewForm extends React.PureComponent<Props> {
1718
constructor(props: Props): void {
1819
super(props);
1920
// All fields optional
@@ -25,7 +26,7 @@ class ProjectPreviewForm extends React.PureComponent<Props> {
2526
return (
2627
<React.Fragment>
2728
<DjangoCSRFToken/>
28-
<input type="hidden" name="is_searchable" value="True"/>
29+
<input type="hidden" name="is_created" value="True"/>
2930
<AboutEventDisplay
3031
event={this.props.project}
3132
viewOnly={true}
@@ -35,4 +36,4 @@ class ProjectPreviewForm extends React.PureComponent<Props> {
3536
}
3637
}
3738

38-
export default ProjectPreviewForm;
39+
export default EventPreviewForm;

0 commit comments

Comments
 (0)