Repository: fossasia/open-event-server

Issue:
Enhance Form for Call of Speakers
The form to answer the call for speakers needs to be improved to be fully usable, e.g. if a speaker wants to submit two proposals it is currently not possible. Therefore, please implement the following:

* [ ] When the user clicks "Submit Proposal" on Call for Speakers page open a pop up with the following options a) Register as a Speaker and b) Propose Session
* [ ] Split forms for Speakers and Registration into separate forms
* [ ] If speaker has already filled in a session form offer option: "Add Another Session"


Discussion:
@mariobehling is the pop up - a modal form pop up with the options a) Register as a Speaker and b) Propose Session?
@mariobehling Should I go about this way?
![screenshot from 2017-02-13 06-42-37](https://cloud.githubusercontent.com/assets/20799954/22868103/047f7c22-f1b8-11e6-976a-2ab9d080ed76.png)

**Case 1: Only Speaker Form (Register As Speaker)**
![screenshot from 2017-02-13 06-42-47](https://cloud.githubusercontent.com/assets/20799954/22868113/22391db8-f1b8-11e6-9e57-e7c8fc5442c3.png)

**Case 2: Only Session Form (Propose Session)**
![screenshot from 2017-02-13 06-43-34](https://cloud.githubusercontent.com/assets/20799954/22868115/26ab8dea-f1b8-11e6-8c6c-6e8654c6831a.png)

**Case 3: Both Session and Speaker Form (Propose Session and add speaker)**
![screenshot from 2017-02-13 06-44-29](https://cloud.githubusercontent.com/assets/20799954/22868119/2babd4a8-f1b8-11e6-92e4-f9cc2f43c358.png)

Yes, the first screenshot is going into the right direction. Let' do as follows:
* [ ] Show "Add Speaker Information" (if the speaker information is complete show green tick, if all required fields are filled in show a relevant [orange exclamation mark](https://farm2.staticflickr.com/1149/1070601182_0fe532a667.jpg), if it is empty and missing required fields show a gray incomplete symbol or something similar)
* [ ] below that show 
   * a) Existing Session Proposals
![screenshot from 2017-02-13 08-57-52](https://cloud.githubusercontent.com/assets/1583873/22875378/abb6d914-f1cb-11e6-893b-da3f6c561752.png)
   * and b) "Add Session Proposal"
* [ ] Use the same way as for "Add Speaker Information" (green tick, orange exclamation mark, gray incomplete symbol)

Resolving patch:
diff --git a/app/helpers/sessions_speakers/speakers.py b/app/helpers/sessions_speakers/speakers.py
--- a/app/helpers/sessions_speakers/speakers.py
+++ b/app/helpers/sessions_speakers/speakers.py
@@ -47,7 +47,8 @@ def save_speaker(request, event_id=None, speaker=None, user=None):
         save_to_db(speaker)
 
     speaker.email = trim_get_form(request.form, 'email', None)
-    speaker.name = trim_get_form(request.form, 'name', None)
+    if trim_get_form(request.form, 'name', None):
+        speaker.name = trim_get_form(request.form, 'name', None)
 
     if not speaker.user:
         if user:
diff --git a/app/views/public/event_detail.py b/app/views/public/event_detail.py
--- a/app/views/public/event_detail.py
+++ b/app/views/public/event_detail.py
@@ -189,6 +189,9 @@ def display_event_schedule_xcal(identifier):
 def display_event_cfs(identifier, via_hash=False):
     event = get_published_event_or_abort(identifier)
     placeholder_images = DataGetter.get_event_default_images()
+    if login.current_user.is_authenticated:
+        email = login.current_user.email
+        user_speaker = DataGetter.get_speaker_by_email(email)
     if event.sub_topic:
         custom_placeholder = DataGetter.get_custom_placeholder_by_name(event.sub_topic)
     elif event.topic:
@@ -218,12 +221,20 @@ def display_event_cfs(identifier, via_hash=False):
         state = "future"
     speakers = DataGetter.get_speakers(event.id).all()
     accepted_sessions_count = get_count(DataGetter.get_sessions(event.id))
-    return render_template('gentelella/guest/event/cfs.html', event=event,
+    if not login.current_user.is_authenticated:
+        return render_template('gentelella/guest/event/cfs.html', event=event,
                            speaker_form=speaker_form,
                            accepted_sessions_count=accepted_sessions_count,
                            session_form=session_form, call_for_speakers=call_for_speakers,
                            placeholder_images=placeholder_images, state=state, speakers=speakers,
                            via_hash=via_hash, custom_placeholder=custom_placeholder)
+    else:
+        return render_template('gentelella/guest/event/cfs.html', event=event,
+                           speaker_form=speaker_form,
+                           accepted_sessions_count=accepted_sessions_count,
+                           session_form=session_form, call_for_speakers=call_for_speakers,
+                           placeholder_images=placeholder_images, state=state, speakers=speakers,
+                           via_hash=via_hash, custom_placeholder=custom_placeholder, user_speaker=user_speaker)
 
 
 @event_detail.route('/cfs/<hash>/', methods=('GET', 'POST'))
@@ -310,7 +321,7 @@ def process_event_cfs(identifier, via_hash=False):
                                accepted_sessions_count=accepted_sessions_count,
                                session_form=session_form, call_for_speakers=call_for_speakers,
                                placeholder_images=placeholder_images, state=state, speakers=speakers,
-                               via_hash=via_hash, custom_placeholder=custom_placeholder)
+                               via_hash=via_hash, custom_placeholder=custom_placeholder, from_path="cfs")
 
     if request.method == 'POST':
         email = request.form['email']
@@ -328,6 +339,120 @@ def process_event_cfs(identifier, via_hash=False):
             return redirect(url_for('admin.login_view', next=url_for('my_sessions.display_my_sessions_view')))
 
 
+@event_detail.route('/<identifier>/cfs/new_session/', methods=('POST', 'GET'))
+def process_event_cfs_session(identifier, via_hash=False):
+    if request.method == 'GET':
+        event = get_published_event_or_abort(identifier)
+        placeholder_images = DataGetter.get_event_default_images()
+        if event.sub_topic:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name(event.sub_topic)
+        elif event.topic:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name(event.topic)
+        else:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name('Other')
+        if not event.has_session_speakers:
+            abort(404)
+
+        call_for_speakers = DataGetter.get_call_for_papers(event.id).first()
+
+        if not call_for_speakers or (not via_hash and call_for_speakers.privacy == 'private'):
+            abort(404)
+
+        form_elems = DataGetter.get_custom_form_elements(event.id)
+        speaker_form = json.loads(form_elems.speaker_form)
+        session_form = json.loads(form_elems.session_form)
+
+        now = datetime.now(pytz.timezone(event.timezone
+                                                  if (event.timezone and event.timezone != '') else 'UTC'))
+        start_date = pytz.timezone(event.timezone).localize(call_for_speakers.start_date)
+        end_date = pytz.timezone(event.timezone).localize(call_for_speakers.end_date)
+        state = "now"
+        if end_date < now:
+            state = "past"
+        elif start_date > now:
+            state = "future"
+        speakers = DataGetter.get_speakers(event.id).all()
+        accepted_sessions_count = get_count(DataGetter.get_sessions(event.id))
+        return render_template('gentelella/guest/event/cfs_new_session.html', event=event,
+                               speaker_form=speaker_form,
+                               accepted_sessions_count=accepted_sessions_count,
+                               session_form=session_form, call_for_speakers=call_for_speakers,
+                               placeholder_images=placeholder_images, state=state, speakers=speakers,
+                               via_hash=via_hash, custom_placeholder=custom_placeholder, from_path="cfs")
+
+    if request.method == 'POST':
+        email = request.form['email']
+        event = DataGetter.get_event_by_identifier(identifier)
+        if not event.has_session_speakers:
+            abort(404)
+        DataManager.add_session_to_event(request, event.id)
+        if login.current_user.is_authenticated:
+            flash("Your session proposal has been submitted", "success")
+            return redirect(url_for('my_sessions.display_my_sessions_view', event_id=event.id))
+        else:
+            flash(Markup(
+                "Your session proposal has been submitted. Please login/register with <strong><u>" + email + "</u></strong> to manage it."),
+                "success")
+            return redirect(url_for('admin.login_view', next=url_for('my_sessions.display_my_sessions_view')))
+
+
+@event_detail.route('/<identifier>/cfs/new_speaker/', methods=('POST', 'GET'))
+def process_event_cfs_speaker(identifier, via_hash=False):
+    if request.method == 'GET':
+        event = get_published_event_or_abort(identifier)
+        placeholder_images = DataGetter.get_event_default_images()
+        if event.sub_topic:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name(event.sub_topic)
+        elif event.topic:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name(event.topic)
+        else:
+            custom_placeholder = DataGetter.get_custom_placeholder_by_name('Other')
+        if not event.has_session_speakers:
+            abort(404)
+
+        call_for_speakers = DataGetter.get_call_for_papers(event.id).first()
+
+        if not call_for_speakers or (not via_hash and call_for_speakers.privacy == 'private'):
+            abort(404)
+
+        form_elems = DataGetter.get_custom_form_elements(event.id)
+        speaker_form = json.loads(form_elems.speaker_form)
+        session_form = json.loads(form_elems.session_form)
+
+        now = datetime.now(pytz.timezone(event.timezone
+                                                  if (event.timezone and event.timezone != '') else 'UTC'))
+        start_date = pytz.timezone(event.timezone).localize(call_for_speakers.start_date)
+        end_date = pytz.timezone(event.timezone).localize(call_for_speakers.end_date)
+        state = "now"
+        if end_date < now:
+            state = "past"
+        elif start_date > now:
+            state = "future"
+        speakers = DataGetter.get_speakers(event.id).all()
+        accepted_sessions_count = get_count(DataGetter.get_sessions(event.id))
+        return render_template('gentelella/guest/event/cfs_new_speaker.html', event=event,
+                               speaker_form=speaker_form,
+                               accepted_sessions_count=accepted_sessions_count,
+                               session_form=session_form, call_for_speakers=call_for_speakers,
+                               placeholder_images=placeholder_images, state=state, speakers=speakers,
+                               via_hash=via_hash, custom_placeholder=custom_placeholder)
+
+    if request.method == 'POST':
+        email = request.form['email']
+        event = DataGetter.get_event_by_identifier(identifier)
+        if not event.has_session_speakers:
+            abort(404)
+        DataManager.add_session_to_event(request, event.id)
+        if login.current_user.is_authenticated:
+            flash("You have been registered as Speaker", "success")
+            return redirect(url_for('event_detail.display_event_cfs', identifier=identifier))
+        else:
+            flash(Markup(
+                "You have been registered as Speaker. Please login/register with <strong><u>" + email + "</u></strong> to manage it."),
+                "success")
+            return redirect(url_for('admin.login_view', next=url_for('my_sessions.display_my_sessions_view')))
+
+
 @event_detail.route('/temp/', methods=('POST',))
 def add_session_media():
     if 'slides' in request.files and request.files['slides'].filename != '':


Test patch: