pretty tag fields in new resource form
authorJan Szejko <janek37@gmail.com>
Tue, 11 Apr 2017 13:00:00 +0000 (15:00 +0200)
committerJan Szejko <janek37@gmail.com>
Tue, 11 Apr 2017 13:00:00 +0000 (15:00 +0200)
apps/catalogue/forms.py
apps/catalogue/templates/catalogue/document_create_missing.html
apps/catalogue/views.py
redakcja/settings/compress.py
redakcja/static/js/catalogue/catalogue.js
redakcja/static/js/lib/chosen-1.6.2/README.md [new file with mode: 0644]
redakcja/static/js/lib/chosen-1.6.2/bootstrap-chosen.css [new file with mode: 0644]

index 5a8e4b2..6c704b9 100644 (file)
@@ -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']
index affd797..4876d4f 100644 (file)
                 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:"" }}</textarea>
-        {% comment %}
         {% for tag_form in tag_forms %}
-            {{ tag_form.as_p }}
+            {% for tag_field in tag_form %}
+                <label for="id_{{ tag_form.prefix }}-{{ tag_field.name }}">{{ tag_field.label }}</label>
+                {{ tag_field.errors }}
+                {{ tag_field }}
+            {% endfor %}
         {% endfor %}
-        {% endcomment %}
 
         <button style="margin-top:1em;" class="btn btn-default" type="submit">{% trans "Create resource" %}</button>
     </form>
index cf1ec12..d2e135c 100644 (file)
@@ -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": '/',
     })
index a66b049..4ded9c0 100644 (file)
@@ -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',
index 796e3e8..a56afdb 100755 (executable)
@@ -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 (file)
index 0000000..ffce853
--- /dev/null
@@ -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 (file)
index 0000000..54e6a13
--- /dev/null
@@ -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 */