Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement labels (resolves #313) #392

Merged
merged 147 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
516d262
Revised labelset and label models
jace Apr 8, 2019
49af3f6
Fix docstrings, add columns
jace Apr 8, 2019
5dd3e91
Fix foreignkey
jace Apr 8, 2019
169cb1d
added migration for labels
Apr 8, 2019
d5ffbed
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 8, 2019
239fa9a
added tests for assigning labels
Apr 8, 2019
c1b655e
added tests for radio labelsets
Apr 9, 2019
f06ebcd
added mock usermanager for auth testing
Apr 10, 2019
cd4e894
updated scope for user, team, profile and project fixture
Apr 10, 2019
87b1f62
logging in without dummy usermanager
Apr 10, 2019
7b40639
Add manage label page(WIP) (#394)
vidya-ram Apr 11, 2019
909fa4e
added migration for moving old sections, session types and technical …
Apr 11, 2019
3e0c426
some comments
Apr 11, 2019
8c74b4a
added dynamic proposalform and handling of labels
Apr 12, 2019
ef7ee3a
added comments
Apr 12, 2019
e755ef3
added removal of labels in non radio mode
Apr 12, 2019
3400a3e
Add CTA button to proposal page
vidya-ram Apr 12, 2019
9e51ff3
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 12, 2019
040509c
Fix styling of proposal labels
vidya-ram Apr 12, 2019
e979dee
removed the inner outer form classes, added get_proposal_form
Apr 12, 2019
8f8e781
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 12, 2019
9f9c8e9
added archived flag
Apr 12, 2019
b99b672
fixed labelview loader
Apr 13, 2019
1ec283a
added view for admins to set labels to a proposal
Apr 13, 2019
97ab0c8
fixed new form
Apr 15, 2019
32e0db5
comment
Apr 15, 2019
eee9e83
fixed label loading in dynamic form
Apr 15, 2019
e74f8db
Fix labels UI
vidya-ram Apr 15, 2019
3551b8f
Sync with master
vidya-ram Apr 15, 2019
e99e34b
Remove LabelSet
jace Apr 15, 2019
b733c6b
Use self.is_parent
jace Apr 15, 2019
c3f61e6
Required flag must be false if not a parent label
jace Apr 15, 2019
c838cf3
Updated docstrings
jace Apr 16, 2019
81f65a3
Don't need use_alter for self-referential
jace Apr 16, 2019
ba9670c
Rename part_labels (column rename also needed)
jace Apr 16, 2019
9b5740e
added setter and expression for restricted and archived
Apr 16, 2019
a3f118f
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 16, 2019
12a2d17
modified migration for labels
Apr 16, 2019
10da32c
fixed expression for flags
Apr 16, 2019
d403b22
replaced labelset views and form
Apr 16, 2019
ea255bc
removed labelset form
Apr 16, 2019
a083c63
added missing project FK in migration
Apr 16, 2019
a2cb4b1
Label form(WIP)
vidya-ram Apr 17, 2019
49d505a
Remove unwanted fields from sublabel form and update the UI
vidya-ram Apr 17, 2019
5d8bd1f
Remove description and bgcolor
vidya-ram Apr 17, 2019
369c099
added sublabel form
Apr 17, 2019
0698e06
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 17, 2019
5cd4341
added sublabelform
Apr 17, 2019
95b1028
Add emoji picker
vidya-ram Apr 17, 2019
29b2be9
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 17, 2019
cb24ad8
saving sublabels with emojis
Apr 18, 2019
6d83dfd
removed length validator from emoji field
Apr 18, 2019
580dce1
sending an empty sublabel form to template
Apr 18, 2019
d5e5ecc
modified how choices are formatted
Apr 18, 2019
ecb8b00
using labels_form template for label edit
Apr 19, 2019
2de3337
sending sublabels to label edit form
Apr 19, 2019
ba2737d
Update the UI of manage label page
vidya-ram Apr 19, 2019
a8124b4
trying to use proxy for labelset
Apr 19, 2019
01d8390
saving labels
Apr 19, 2019
ece8fbf
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 19, 2019
9c442e2
moved keys method to wrapper
Apr 22, 2019
7dd9829
Rename label parent/children to main/options; fix archived expression
jace Apr 22, 2019
0563c56
Uncommitted file in label main/options commit
jace Apr 22, 2019
6350ae2
added migration for old labels
Apr 22, 2019
82c8236
Fixed proposal label form
jace Apr 22, 2019
6800399
Validator message
jace Apr 22, 2019
a6d1411
Check for emoji on proposal page
vidya-ram Apr 22, 2019
f802f49
Ignore archived label options
jace Apr 22, 2019
af8aee6
old labels are not restricted
Apr 22, 2019
d7d8f08
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 22, 2019
d28ec8c
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 22, 2019
6b3391b
Remove unused ProposalFormData (from #109)
jace Apr 22, 2019
1e8433d
No CSRF in form fields
jace Apr 22, 2019
33e5b0b
Check for emoji
vidya-ram Apr 22, 2019
647aae3
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 22, 2019
d424ee3
only showing icon emoji if it's available
Apr 22, 2019
ddefe22
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 22, 2019
bf1c304
Friendlier messaging in label form; appropriate name
jace Apr 22, 2019
7859fb5
Rename label.is_main to has_options
jace Apr 22, 2019
beadac5
Names should be in singular as per coding convention
jace Apr 22, 2019
02c9ae0
Remove label "icon" title in form (for now)
jace Apr 22, 2019
976a2d3
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 22, 2019
15c31da
Add drag functionality to set sequence of sub labels
vidya-ram Apr 22, 2019
43264cf
Add support to reorder main labels
vidya-ram Apr 23, 2019
d0f044c
added label form for admin panel and added id to labelform
Apr 23, 2019
4cbc4c6
id field is option for labelform
Apr 23, 2019
6949eba
id is optional for options form
Apr 23, 2019
b59a8b5
Layout of manage label page
vidya-ram Apr 23, 2019
2948838
Add proposal_label_admin_form (WIP)
vidya-ram Apr 23, 2019
1191e75
showing booleanfield for boolean labels
Apr 23, 2019
f506c37
showing emoji in front of label title in widget
Apr 23, 2019
3012115
saving labels in admin panel
Apr 23, 2019
12e970f
redirecting to labels page if there is an error in proposals page lab…
Apr 24, 2019
8bdb16a
Add label widget
vidya-ram Apr 24, 2019
af72226
Add functionality to add labels widget
vidya-ram Apr 24, 2019
e0a71e2
fixed view for saving labels
Apr 24, 2019
df75fd3
Fix label widget for checkbox options
vidya-ram Apr 24, 2019
779448b
refactored tests and added more
Apr 24, 2019
5e33781
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 24, 2019
baf9049
added test for label icon
Apr 24, 2019
ca55200
added test for restricted setter
Apr 24, 2019
e7b86b2
added simple integration test
Apr 24, 2019
4441f64
added test for label create view
Apr 25, 2019
87fd255
added test for adding labels with options
Apr 25, 2019
93718f8
added id field to labels form
Apr 25, 2019
b408afc
Style changes and moved widget JS code to JS bundle
vidya-ram Apr 25, 2019
2965703
Merge branch 'labels' of github.com:hasgeek/funnel into labels
vidya-ram Apr 25, 2019
ec9f418
Merge branch 'master' of github.com:hasgeek/funnel into labels
Apr 25, 2019
bd4d19f
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 25, 2019
0a6cbe1
running npm build in travis
Apr 25, 2019
14651de
Add seq and id field for all labels
vidya-ram Apr 25, 2019
ebb55d7
Update the UI of manage label page
vidya-ram Apr 25, 2019
3a8f4eb
Minor css updates of label page
vidya-ram Apr 25, 2019
fa4d228
calling reorder to fix ordering
Apr 25, 2019
53fba72
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 25, 2019
ead9434
saving main label order from manage label page
Apr 25, 2019
d5c260d
added csrf protection to labels reorder form
Apr 26, 2019
bb068fe
addded reordering of sublabels
Apr 26, 2019
72bd94a
added viewsfor delete and archive
Apr 26, 2019
fe8c478
added `has_proposals` to label model
Apr 26, 2019
faf4823
fix edit form
Apr 26, 2019
0191b36
repalce hyphne in permission name
Apr 26, 2019
b2f899a
Add confirmation dialog for delete and archive
vidya-ram Apr 26, 2019
beb56d6
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 26, 2019
e28132b
fixed label delete view
Apr 26, 2019
e3ab13c
using name instead of id
Apr 26, 2019
38fde91
not reusing forms for label
Apr 26, 2019
5dfaaf7
moved label assignment from proposal model to label model
Apr 26, 2019
5de04a7
Change delete and archive to ajax post
vidya-ram Apr 26, 2019
8f18f14
fixed migration
Apr 26, 2019
0ffebb1
linter fixes
Apr 26, 2019
c37f4b7
Fix the label widget
vidya-ram Apr 26, 2019
19a9b46
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 26, 2019
e8c8e78
deleting options before deleting main label
Apr 26, 2019
e88416e
removed labelseqform
Apr 26, 2019
953bc35
fixed syntax error
Apr 26, 2019
b4e7de1
fixed proposal edit page label form
Apr 26, 2019
98954c7
Add title_for_name
jace Apr 26, 2019
344ac3b
fixed archived getter
Apr 26, 2019
063d773
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 26, 2019
e0482fc
Linter fixes
jace Apr 26, 2019
e5fc767
added test for label create, reorder and delete
Apr 26, 2019
30bb4be
reordering after label delete
Apr 26, 2019
08d497e
Merge branch 'labels' of github.com:hasgeek/funnel into labels
Apr 26, 2019
4975b6f
added test for editing labels
Apr 26, 2019
b71bc4e
Session type hasn't been used for a while
jace Apr 26, 2019
8f9e45a
Rename sublabel to option
jace Apr 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ install:
- pip install -U pip wheel
- pip install -r requirements.txt
- pip install -r test_requirements.txt
- make
script:
- ./runtests.sh
after_success:
Expand Down
19 changes: 19 additions & 0 deletions funnel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@
app.assets.register('css_leaflet',
Bundle(assets.require('leaflet.css', 'leaflet-search.css'),
output='css/leaflet.packed.css', filters='cssmin'))
app.assets.register('js_emojionearea',
Bundle(assets.require('!jquery.js', 'emojionearea-material.js'),
output='js/emojionearea.packed.js', filters='uglipyjs'))
app.assets.register('css_emojionearea',
Bundle(assets.require('emojionearea-material.css'),
output='css/emojionearea.packed.css', filters='cssmin'))
app.assets.register('js_sortable',
Bundle(assets.require('!jquery.js', 'jquery.ui.js', 'jquery.ui.sortable.touch.js'),
output='js/sortable.packed.js', filters='uglipyjs'))


baseframe.init_app(funnelapp, requires=['funnel'], ext_requires=[
'pygments', 'toastr', 'baseframe-mui'], theme='mui')
Expand Down Expand Up @@ -133,6 +143,15 @@
funnelapp.assets.register('css_leaflet',
Bundle(assets.require('leaflet.css', 'leaflet-search.css'),
output='css/leaflet.packed.css', filters='cssmin'))
funnelapp.assets.register('js_emojionearea',
Bundle(assets.require('!jquery.js', 'emojionearea-material.js'),
output='js/emojionearea.packed.js', filters='uglipyjs'))
funnelapp.assets.register('css_emojionearea',
Bundle(assets.require('emojionearea-material.css'),
output='css/emojionearea.packed.css', filters='cssmin'))
funnelapp.assets.register('js_sortable',
Bundle(assets.require('!jquery.js', 'jquery.ui.js', 'jquery.ui.sortable.touch.js'),
output='js/sortable.packed.js', filters='uglipyjs'))

# FIXME: Hack for external build system generating relative /static URLs.
# Fix this by generating absolute URLs to the static subdomain during build.
Expand Down
63 changes: 63 additions & 0 deletions funnel/assets/js/proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,72 @@ export const Video = {
},
};

export const LabelsWidget = {
init() {
const Widget = this;
// On load, if the radio has been selected, then check mark the listwidget label
$('.listwidget input[type="radio"]').each(function() {
if(this.checked) {
$(this).siblings().find('.mui-form__label').addClass('checked');
}
});

$('.listwidget .mui-form__label').click(function() {
if($(this).hasClass('checked')) {
$(this).removeClass('checked');
$(this).siblings().find('input[type="radio"]').prop('checked', false);
Widget.updateLabels('', $(this).text().trim(), false);
} else {
$(this).addClass('checked');
$(this).siblings().find('input[type="radio"]').first().click();
}
});

// Add check mark to listwidget label
$('.listwidget input[type="radio"]').change(function() {
let label = $(this).parent().parent().prev('.mui-form__label');
label.addClass('checked');
let labelTxt = `${label.text()}: ${$(this).parent().find('label').text()}`.trim();
let attr = label.text().trim();
Widget.updateLabels(labelTxt, attr, this.checked);
});

$('.add-label-form input[type="checkbox"]').change(function() {
let labelTxt = $(this).parent('label').text().trim();
Widget.updateLabels(labelTxt, labelTxt, this.checked);
});

// Open and close dropdown
$(document).on('click', function(event) {
if ($('#label-select')[0] === event.target || !$(event.target).parents('#label-dropdown').length) {
Widget.handleDropdown();
}
});
},
handleDropdown() {
if($('#label-dropdown fieldset').hasClass('active')) {
$('#label-dropdown fieldset').removeClass('active');
} else {
$('#label-dropdown fieldset').addClass('active');
}
},
updateLabels(label='', attr='', action=true) {
if(action) {
if(label !== attr) {
$(`.label[data-labeltxt="${attr}"]`).remove();
}
let span = `<span class="label mui--text-caption mui--text-bold" data-labeltxt="${attr}">${label}</span>`;
$('#label-select').append(span);
} else {
$(`.label[data-labeltxt="${attr}"]`).remove();
}
}
};

$(() => {
window. HasGeek.ProposalInit = function ({pageUrl, videoWrapper= '', videoUrl= ''}) {
Comments.init(pageUrl);
LabelsWidget.init();

if (videoWrapper) {
Video.embedIframe(videoWrapper, videoUrl);
Expand Down
1 change: 1 addition & 0 deletions funnel/forms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
from .session import *
from .profile import *
from .participant import *
from .label import *
25 changes: 25 additions & 0 deletions funnel/forms/label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-

from baseframe import __
import baseframe.forms as forms

__all__ = ['LabelForm', 'LabelOptionForm']


class LabelForm(forms.Form):
name = forms.StringField("", widget=forms.HiddenInput(), validators=[forms.validators.Optional()])
title = forms.StringField(__("Label"),
validators=[forms.validators.DataRequired(__(u"This can’t be empty")), forms.validators.Length(max=250)])
icon_emoji = forms.StringField("")
required = forms.BooleanField(__("Make this label mandatory in proposal forms"), default=False,
description=__("If checked, proposers must select one of the options"))
restricted = forms.BooleanField(__("Restrict use of this label to editors"), default=False,
description=__("If checked, only editors and reviewers can apply this label on proposals"))


class LabelOptionForm(forms.Form):
name = forms.StringField("", widget=forms.HiddenInput(), validators=[forms.validators.Optional()])
title = forms.StringField(__("Option"),
validators=[forms.validators.DataRequired(__(u"This can’t be empty")), forms.validators.Length(max=250)])
icon_emoji = forms.StringField("")
seq = forms.IntegerField("", widget=forms.HiddenInput())
82 changes: 66 additions & 16 deletions funnel/forms/proposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,81 @@
from baseframe.forms.sqlalchemy import QuerySelectField
from ..models import Project, Profile

__all__ = ['TransferProposal', 'ProposalForm', 'ProposalTransitionForm', 'ProposalMoveForm']
__all__ = ['TransferProposal', 'ProposalForm', 'ProposalTransitionForm', 'ProposalLabelsForm',
'ProposalMoveForm', 'ProposalLabelsAdminForm']


def proposal_label_form(project, proposal):
"""
Returns a label form for the given project and proposal.
"""
class ProposalLabelForm(forms.Form):
pass

for label in project.labels:
if label.has_options and not label.archived and not label.restricted:
setattr(ProposalLabelForm, label.name, forms.RadioField(
label.form_label_text,
description=label.description,
validators=[forms.validators.DataRequired(__("Please select one"))] if label.required else [],
choices=[(option.name, option.title) for option in label.options if not option.archived]
))

return ProposalLabelForm(obj=proposal.formlabels if proposal else None, meta={'csrf': False})


def proposal_label_admin_form(project, proposal):
"""
Returns a label form to use in admin panel for given project and proposal
"""
class ProposalLabelAdminForm(forms.Form):
pass

for label in project.labels:
if not label.archived and (label.restricted or not label.has_options):
form_kwargs = {}
if label.has_options:
FieldType = forms.RadioField
form_kwargs['choices'] = [(option.name, option.title) for option in label.options if not option.archived]
else:
FieldType = forms.BooleanField

setattr(ProposalLabelAdminForm, label.name, FieldType(
label.form_label_text,
description=label.description,
validators=[forms.validators.DataRequired(__("Please select one"))] if label.required else [],
**form_kwargs
))

return ProposalLabelAdminForm(obj=proposal.formlabels if proposal else None, meta={'csrf': False})


class TransferProposal(forms.Form):
userid = forms.UserSelectField(__("Transfer to"), validators=[forms.validators.DataRequired()])


class ProposalLabelsForm(forms.Form):
formlabels = forms.FormField(forms.Form, __("Labels"))

def set_queries(self):
self.formlabels.form = proposal_label_form(project=self.edit_parent, proposal=self.edit_obj)


class ProposalLabelsAdminForm(forms.Form):
formlabels = forms.FormField(forms.Form, __("Labels"))

def set_queries(self):
self.formlabels.form = proposal_label_admin_form(project=self.edit_parent, proposal=self.edit_obj)


class ProposalForm(forms.Form):
speaking = forms.RadioField(__("Are you speaking?"), coerce=int,
choices=[(1, __(u"I will be speaking")),
(0, __(u"I’m proposing a topic for someone to speak on"))])
title = forms.StringField(__("Title"), validators=[forms.validators.DataRequired()],
description=__("The title of your session"))
section = QuerySelectField(__("Section"), get_label='title', validators=[forms.validators.DataRequired()],
widget=forms.ListWidget(prefix_label=False), option_widget=forms.RadioInput())
objective = forms.MarkdownField(__("Objective"), validators=[forms.validators.DataRequired()],
description=__("What is the expected benefit for someone attending this?"))
session_type = forms.RadioField(__("Session type"), validators=[forms.validators.DataRequired()], choices=[
('Lecture', __("Lecture")),
('Demo', __("Demo")),
('Tutorial', __("Tutorial")),
('Workshop', __("Workshop")),
('Discussion', __("Discussion")),
('Panel', __("Panel")),
])
technical_level = forms.RadioField(__("Technical level"), validators=[forms.validators.DataRequired()], choices=[
('Beginner', __("Beginner")),
('Intermediate', __("Intermediate")),
('Advanced', __("Advanced")),
])
description = forms.MarkdownField(__("Description"), validators=[forms.validators.DataRequired()],
description=__("A detailed description of the session"))
requirements = forms.MarkdownField(__("Requirements"),
Expand Down Expand Up @@ -63,6 +108,8 @@ class ProposalForm(forms.Form):
location = forms.StringField(__("Your location"), validators=[forms.validators.DataRequired(), forms.validators.Length(max=80)],
description=__("Your location, to help plan for your travel if required"))

formlabels = forms.FormField(forms.Form, __("Labels"))

def __init__(self, *args, **kwargs):
super(ProposalForm, self).__init__(*args, **kwargs)
project = kwargs.get('parent')
Expand All @@ -75,6 +122,9 @@ def __init__(self, *args, **kwargs):
if project.proposal_part_b.get('hint'):
self.description.description = project.proposal_part_b.get('hint')

def set_queries(self):
self.formlabels.form = proposal_label_form(project=self.edit_parent, proposal=self.edit_obj)


class ProposalTransitionForm(forms.Form):
transition = forms.SelectField(__("Status"), validators=[forms.validators.DataRequired()])
Expand Down
1 change: 1 addition & 0 deletions funnel/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
from .session import *
from .user import *
from .venue import *
from .label import *
Loading