From 5a649a9e943f331ec61d2e86c3840397777ccfb6 Mon Sep 17 00:00:00 2001 From: Jan Szejko Date: Tue, 11 Apr 2017 15:00:00 +0200 Subject: [PATCH 1/1] pretty tag fields in new resource form --- apps/catalogue/forms.py | 16 +- .../catalogue/document_create_missing.html | 8 +- apps/catalogue/views.py | 18 +- redakcja/settings/compress.py | 66 ++-- redakcja/static/js/catalogue/catalogue.js | 2 + redakcja/static/js/lib/chosen-1.6.2/README.md | 29 ++ .../js/lib/chosen-1.6.2/bootstrap-chosen.css | 346 ++++++++++++++++++ 7 files changed, 438 insertions(+), 47 deletions(-) create mode 100644 redakcja/static/js/lib/chosen-1.6.2/README.md create mode 100644 redakcja/static/js/lib/chosen-1.6.2/bootstrap-chosen.css diff --git a/apps/catalogue/forms.py b/apps/catalogue/forms.py index 5a8e4b2f..6c704b96 100644 --- a/apps/catalogue/forms.py +++ b/apps/catalogue/forms.py @@ -43,7 +43,7 @@ class TagForm(forms.Form): self.category = category self.instance = instance self.field().queryset = Tag.objects.filter(category=self.category) - self.field().label = self.category.label + self.field().label = self.category.label.capitalize() if self.instance: self.field().initial = self.initial() @@ -63,7 +63,12 @@ class TagForm(forms.Form): class TagSingleForm(TagForm): - tag = forms.ModelChoiceField(Tag.objects.none()) + tag = forms.ModelChoiceField( + Tag.objects.none(), + widget=forms.Select(attrs={ + 'class': 'form-control', + }) + ) def field(self): return self.fields['tag'] @@ -76,7 +81,12 @@ class TagSingleForm(TagForm): class TagMultipleForm(TagForm): - tags = forms.ModelMultipleChoiceField(Tag.objects.none(), required=False) + tags = forms.ModelMultipleChoiceField( + Tag.objects.none(), required=False, + widget=forms.SelectMultiple(attrs={ + 'class': 'chosen-select', + 'data-placeholder': _('Choose'), + })) def field(self): return self.fields['tags'] diff --git a/apps/catalogue/templates/catalogue/document_create_missing.html b/apps/catalogue/templates/catalogue/document_create_missing.html index affd7977..4876d4ff 100644 --- a/apps/catalogue/templates/catalogue/document_create_missing.html +++ b/apps/catalogue/templates/catalogue/document_create_missing.html @@ -74,11 +74,13 @@ data-toggle="tutorial" data-tutorial="4" data-placement="top" data-content="{% trans 'You can provide a short description of the document here.' %}" >{{ form.description.value|default:"" }} - {% comment %} {% for tag_form in tag_forms %} - {{ tag_form.as_p }} + {% for tag_field in tag_form %} + + {{ tag_field.errors }} + {{ tag_field }} + {% endfor %} {% endfor %} - {% endcomment %} diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index cf1ec128..d2e135c5 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -73,11 +73,11 @@ def logout_then_redirect(request): def create_missing(request): if request.method == "POST": form = forms.DocumentCreateForm(request.POST, request.FILES) - # tag_forms = [ - # (TagMultipleForm if category.multiple else TagSingleForm)( - # category=category, data=request.POST, prefix=category.dc_tag) - # for category in Category.objects.all()] - if form.is_valid(): # and all(tag_form.is_valid() for tag_form in tag_forms): + tag_forms = [ + (TagMultipleForm if category.multiple else TagSingleForm)( + category=category, data=request.POST, prefix=category.dc_tag) + for category in Category.objects.all()] + if form.is_valid() and all(tag_form.is_valid() for tag_form in tag_forms): if request.user.is_authenticated(): creator = request.user @@ -147,13 +147,13 @@ def create_missing(request): form = forms.DocumentCreateForm(initial={'owner_organization': org}) - # tag_forms = [ - # (TagMultipleForm if category.multiple else TagSingleForm)(category=category, prefix=category.dc_tag) - # for category in Category.objects.all()] + tag_forms = [ + (TagMultipleForm if category.multiple else TagSingleForm)(category=category, prefix=category.dc_tag) + for category in Category.objects.all()] return render(request, "catalogue/document_create_missing.html", { "form": form, - # "tag_forms": tag_forms, + "tag_forms": tag_forms, "logout_to": '/', }) diff --git a/redakcja/settings/compress.py b/redakcja/settings/compress.py index a66b0492..4ded9c07 100644 --- a/redakcja/settings/compress.py +++ b/redakcja/settings/compress.py @@ -34,6 +34,7 @@ PIPELINE = { # 'css/filelist.css', 'css/base.css', 'datepicker/css/datepicker.css', + 'js/lib/chosen-1.6.2/bootstrap-chosen.css', ), 'output_filename': 'compressed/catalogue_styles.css', }, @@ -55,45 +56,46 @@ PIPELINE = { # everything except codemirror 'detail': { 'source_filenames': ( - # libraries - 'js/lib/jquery/jquery.autocomplete.js', - 'js/lib/jquery/jquery.blockui.js', - 'js/lib/jquery/jquery.elastic.js', - 'js/lib/jquery/jquery.xmlns.js', - 'js/button_scripts.js', - 'js/slugify.js', + # libraries + 'js/lib/jquery/jquery.autocomplete.js', + 'js/lib/jquery/jquery.blockui.js', + 'js/lib/jquery/jquery.elastic.js', + 'js/lib/jquery/jquery.xmlns.js', + 'js/button_scripts.js', + 'js/slugify.js', - # wiki scripts - 'js/wiki/wikiapi.js', - 'js/wiki/xslt.js', + # wiki scripts + 'js/wiki/wikiapi.js', + 'js/wiki/xslt.js', - # base UI - 'js/wiki/base.js', - 'js/wiki/toolbar.js', + # base UI + 'js/wiki/base.js', + 'js/wiki/toolbar.js', - # dialogs - 'js/wiki/dialog_save.js', - 'js/wiki/dialog_revert.js', - 'js/wiki/dialog_pubmark.js', + # dialogs + 'js/wiki/dialog_save.js', + 'js/wiki/dialog_revert.js', + 'js/wiki/dialog_pubmark.js', - # views - 'js/wiki/view_history.js', - 'js/wiki/view_summary.js', - 'js/wiki/view_editor_source.js', - 'js/wiki/view_editor_wysiwyg.js', - 'js/wiki/view_gallery.js', - 'js/wiki/view_annotations.js', - 'js/wiki/view_search.js', - 'js/wiki/view_column_diff.js', + # views + 'js/wiki/view_history.js', + 'js/wiki/view_summary.js', + 'js/wiki/view_editor_source.js', + 'js/wiki/view_editor_wysiwyg.js', + 'js/wiki/view_gallery.js', + 'js/wiki/view_annotations.js', + 'js/wiki/view_search.js', + 'js/wiki/view_column_diff.js', ), 'output_filename': 'compressed/detail_scripts.js', - }, + }, 'catalogue': { 'source_filenames': ( - 'js/catalogue/catalogue.js', - 'js/slugify.js', - 'email_mangler/email_mangler.js', - 'datepicker/js/bootstrap-datepicker.js', + 'js/catalogue/catalogue.js', + 'js/slugify.js', + 'email_mangler/email_mangler.js', + 'datepicker/js/bootstrap-datepicker.js', + 'js/lib/chosen-1.6.2/chosen.jquery.min.js', ), 'output_filename': 'compressed/catalogue_scripts.js', }, @@ -105,7 +107,7 @@ PIPELINE = { 'js/book_text/book.js', ), 'output_filename': 'compressed/book.js', - }, + }, 'book_list': { 'source_filenames': ( 'contextmenu/jquery.ui.position.js', diff --git a/redakcja/static/js/catalogue/catalogue.js b/redakcja/static/js/catalogue/catalogue.js index 796e3e8b..a56afdb3 100755 --- a/redakcja/static/js/catalogue/catalogue.js +++ b/redakcja/static/js/catalogue/catalogue.js @@ -51,6 +51,8 @@ } }); + $('.chosen-select').chosen(); + // tutorial mode diff --git a/redakcja/static/js/lib/chosen-1.6.2/README.md b/redakcja/static/js/lib/chosen-1.6.2/README.md new file mode 100644 index 00000000..ffce8530 --- /dev/null +++ b/redakcja/static/js/lib/chosen-1.6.2/README.md @@ -0,0 +1,29 @@ +# bootstrap-chosen (less/sass) + +![](https://github.com/alxlit/bootstrap-chosen/raw/master/example.png) + +An alternate stylesheet for [Chosen 1.0](http://harvesthq.github.com/chosen/). This +one is supposed to integrate better with [Bootstrap 3.0](http://getbootstrap.com/). + +[Here's the example page](http://alxlit.github.io/bootstrap-chosen/). + +How you add `bootstrap-chosen.less` to your build process is up to you. Just keep +in mind that it needs access to `variables.less` and `mixins.less`. + +You can tinker with the example page by: + +``` +$ git clone https://github.com/alxlit/bootstrap-chosen +$ cd bootstrap-chosen +bootstrap-chosen $ git clone --depth=1 https://github.com/twbs/bootstrap +bootstrap-chosen $ vi bootstrap/less/bootstrap.less + +// Add this to the bottom +@import "../../bootstrap-chosen.less"; + +bootstrap-chosen $ lessc bootstrap/less/bootstrap.less > bootstrap.css +bootstrap-chosen $ firefox example.html +``` + +License: [MIT](https://en.wikipedia.org/wiki/MIT_License) + diff --git a/redakcja/static/js/lib/chosen-1.6.2/bootstrap-chosen.css b/redakcja/static/js/lib/chosen-1.6.2/bootstrap-chosen.css new file mode 100644 index 00000000..54e6a139 --- /dev/null +++ b/redakcja/static/js/lib/chosen-1.6.2/bootstrap-chosen.css @@ -0,0 +1,346 @@ +.chosen-select { + width: 100%; } + +.chosen-select-deselect { + width: 100%; } + +.chosen-container { + display: inline-block; + font-size: 14px; + position: relative; + vertical-align: middle; } + .chosen-container .chosen-drop { + background: #fff; + border: 1px solid #ccc; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: 0 8px 8px rgba(0, 0, 0, 0.25); + box-shadow: 0 8px 8px rgba(0, 0, 0, 0.25); + margin-top: -1px; + position: absolute; + top: 100%; + left: -9000px; + z-index: 1060; } + .chosen-container.chosen-with-drop .chosen-drop { + left: 0; + right: 0; } + .chosen-container .chosen-results { + color: #555555; + margin: 0 4px 4px 0; + max-height: 240px; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; } + .chosen-container .chosen-results li { + display: none; + line-height: 1.42857; + list-style: none; + margin: 0; + padding: 5px 6px; } + .chosen-container .chosen-results li em { + background: #feffde; + font-style: normal; } + .chosen-container .chosen-results li.group-result { + display: list-item; + cursor: default; + color: #999; + font-weight: bold; } + .chosen-container .chosen-results li.group-option { + padding-left: 15px; } + .chosen-container .chosen-results li.active-result { + cursor: pointer; + display: list-item; } + .chosen-container .chosen-results li.highlighted { + background-color: #337ab7; + background-image: none; + color: white; } + .chosen-container .chosen-results li.highlighted em { + background: transparent; } + .chosen-container .chosen-results li.disabled-result { + display: list-item; + color: #777777; } + .chosen-container .chosen-results .no-results { + background: #eeeeee; + display: list-item; } + .chosen-container .chosen-results-scroll { + background: white; + margin: 0 4px; + position: absolute; + text-align: center; + width: 321px; + z-index: 1; } + .chosen-container .chosen-results-scroll span { + display: inline-block; + height: 1.42857; + text-indent: -5000px; + width: 9px; } + .chosen-container .chosen-results-scroll-down { + bottom: 0; } + .chosen-container .chosen-results-scroll-down span { + background: url("chosen-sprite.png") no-repeat -4px -3px; } + .chosen-container .chosen-results-scroll-up span { + background: url("chosen-sprite.png") no-repeat -22px -3px; } + +.chosen-container-single .chosen-single { + background-color: #fff; + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + color: #555555; + display: block; + height: 34px; + overflow: hidden; + line-height: 34px; + padding: 0 0 0 8px; + position: relative; + text-decoration: none; + white-space: nowrap; } + .chosen-container-single .chosen-single span { + display: block; + margin-right: 26px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .chosen-container-single .chosen-single abbr { + background: url("chosen-sprite.png") right top no-repeat; + display: block; + font-size: 1px; + height: 10px; + position: absolute; + right: 26px; + top: 12px; + width: 12px; } + .chosen-container-single .chosen-single abbr:hover { + background-position: right -11px; } + .chosen-container-single .chosen-single.chosen-disabled .chosen-single abbr:hover { + background-position: right 2px; } + .chosen-container-single .chosen-single div { + display: block; + height: 100%; + position: absolute; + top: 0; + right: 0; + width: 18px; } + .chosen-container-single .chosen-single div b { + background: url("chosen-sprite.png") no-repeat 0 7px; + display: block; + height: 100%; + width: 100%; } +.chosen-container-single .chosen-default { + color: #777777; } +.chosen-container-single .chosen-search { + margin: 0; + padding: 3px 4px; + position: relative; + white-space: nowrap; + z-index: 1000; } + .chosen-container-single .chosen-search input[type="text"] { + background: url("chosen-sprite.png") no-repeat 100% -20px, #fff; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + margin: 1px 0; + padding: 4px 20px 4px 4px; + width: 100%; } +.chosen-container-single .chosen-drop { + margin-top: -1px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; } + +.chosen-container-single-nosearch .chosen-search input[type="text"] { + position: absolute; + left: -9000px; } + +.chosen-container-multi .chosen-choices { + background-color: #fff; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + cursor: text; + height: auto !important; + height: 1%; + margin: 0; + overflow: hidden; + padding: 0; + position: relative; } + .chosen-container-multi .chosen-choices li { + float: left; + list-style: none; } + .chosen-container-multi .chosen-choices .search-field { + margin: 0; + padding: 0; + white-space: nowrap; } + .chosen-container-multi .chosen-choices .search-field input[type="text"] { + background: transparent !important; + border: 0 !important; + -webkit-box-shadow: none; + box-shadow: none; + color: #555555; + height: 32px; + margin: 0; + padding: 4px; + outline: 0; } + .chosen-container-multi .chosen-choices .search-field .default { + color: #999; } + .chosen-container-multi .chosen-choices .search-choice { + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + background-color: #eeeeee; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + color: #333333; + cursor: default; + line-height: 13px; + margin: 6px 0 3px 5px; + padding: 3px 20px 3px 5px; + position: relative; } + .chosen-container-multi .chosen-choices .search-choice .search-choice-close { + background: url("chosen-sprite.png") right top no-repeat; + display: block; + font-size: 1px; + height: 10px; + position: absolute; + right: 4px; + top: 5px; + width: 12px; + cursor: pointer; } + .chosen-container-multi .chosen-choices .search-choice .search-choice-close:hover { + background-position: right -11px; } + .chosen-container-multi .chosen-choices .search-choice-focus { + background: #d4d4d4; } + .chosen-container-multi .chosen-choices .search-choice-focus .search-choice-close { + background-position: right -11px; } +.chosen-container-multi .chosen-results { + margin: 0 0 0 0; + padding: 0; } +.chosen-container-multi .chosen-drop .result-selected { + display: none; } + +.chosen-container-active .chosen-single { + border: 1px solid #66afe9; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } +.chosen-container-active.chosen-with-drop .chosen-single { + background-color: #fff; + border: 1px solid #66afe9; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } + .chosen-container-active.chosen-with-drop .chosen-single div { + background: transparent; + border-left: none; } + .chosen-container-active.chosen-with-drop .chosen-single div b { + background-position: -18px 7px; } +.chosen-container-active .chosen-choices { + border: 1px solid #66afe9; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } + .chosen-container-active .chosen-choices .search-field input[type="text"] { + color: #111 !important; } +.chosen-container-active.chosen-with-drop .chosen-choices { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + +.chosen-disabled { + cursor: default; + opacity: 0.5 !important; } + .chosen-disabled .chosen-single { + cursor: default; } + .chosen-disabled .chosen-choices .search-choice .search-choice-close { + cursor: default; } + +.chosen-rtl { + text-align: right; } + .chosen-rtl .chosen-single { + padding: 0 8px 0 0; + overflow: visible; } + .chosen-rtl .chosen-single span { + margin-left: 26px; + margin-right: 0; + direction: rtl; } + .chosen-rtl .chosen-single div { + left: 7px; + right: auto; } + .chosen-rtl .chosen-single abbr { + left: 26px; + right: auto; } + .chosen-rtl .chosen-choices .search-field input[type="text"] { + direction: rtl; } + .chosen-rtl .chosen-choices li { + float: right; } + .chosen-rtl .chosen-choices .search-choice { + margin: 6px 5px 3px 0; + padding: 3px 5px 3px 19px; } + .chosen-rtl .chosen-choices .search-choice .search-choice-close { + background-position: right top; + left: 4px; + right: auto; } + .chosen-rtl.chosen-container-single .chosen-results { + margin: 0 0 4px 4px; + padding: 0 4px 0 0; } + .chosen-rtl .chosen-results .group-option { + padding-left: 0; + padding-right: 15px; } + .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { + border-right: none; } + .chosen-rtl .chosen-search input[type="text"] { + background: url("chosen-sprite.png") no-repeat -28px -20px, #fff; + direction: rtl; + padding: 4px 5px 4px 20px; } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 2dppx) { + .chosen-rtl .chosen-search input[type="text"], + .chosen-container-single .chosen-single abbr, + .chosen-container-single .chosen-single div b, + .chosen-container-single .chosen-search input[type="text"], + .chosen-container-multi .chosen-choices .search-choice .search-choice-close, + .chosen-container .chosen-results-scroll-down span, + .chosen-container .chosen-results-scroll-up span { + background-image: url("chosen-sprite@2x.png") !important; + background-size: 52px 37px !important; + background-repeat: no-repeat !important; } } + +/*# sourceMappingURL=bootstrap-chosen.css.map */ -- 2.20.1