| {#- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| -#} |
| {% extends g.theme.master %} |
| |
| {% block title %}{{c.project.name}} / Categorization{% endblock %} |
| |
| {% block header %}Project Categorization{% endblock %} |
| |
| {% macro show_trove_base_cat(base) %} |
| <h3>{{base.fullname}}</h3> |
| {% set help_text = config.get('trovecategories.admin.help.'+base.shortname, '') %} |
| {% if help_text %} |
| <div class="grid-19"> |
| {{ help_text|safe }} |
| <br><br> |
| </div> |
| {% endif %} |
| <div id="trove_existing_{{base.shortname}}" class="trove_existing grid-19"> |
| {% for cat in c.project.troves_by_type(base.shortname)|sort(attribute='fullpath') %} |
| <div style="clear: both"> |
| <span class="trove_fullpath">{{cat.fullpath_within_type}}</span> |
| <form id="delete_trove_{{base.shortname}}_{{cat.trove_cat_id}}" |
| action="delete_trove" method="post" class="trove_deleter"> |
| <input type="hidden" name="type" value="{{base.shortname}}"> |
| <input type="hidden" name="trove" value="{{cat.trove_cat_id}}"> |
| <input type="submit" value="Delete"> |
| {{lib.csrf_token()}} |
| </form> |
| </div> |
| {% else %} |
| <span class="empty_msg">No {{base.fullname}} categories have been selected.</span> |
| {% endfor %} |
| </div> |
| <div class="grid-19 trove_add_container"> |
| {% if trove_recommendations[base.shortname] %} |
| Recommended to choose from: |
| {% for trove_id, label in trove_recommendations[base.shortname].iteritems() %} |
| <a href="#" data-id="{{ trove_id }}" data-trove="{{ base.shortname }}" class="recommended_trove"><i class="fa fa-plus-circle"></i> {{ label }}</a> |
| {% endfor %} |
| <br> |
| Or <a href="#" class="choose_other">choose from other options...</a> |
| {% else %} |
| <label for="new_trove_{{base.shortname}}">Add a new {{base.fullname}} category:</label> |
| <br> |
| {% endif %} |
| |
| <form id="add_trove_{{base.shortname}}" |
| action="add_trove" method="post" class="trove_adder" |
| {% if trove_recommendations[base.shortname] %}style="display:none"{% endif -%} |
| > |
| <input type="hidden" name="type" value="{{base.shortname}}"> |
| <select name="new_trove" id="new_trove_{{base.shortname}}" data-placeholder="Choose one..."> |
| <option value=""></option> |
| {% for cat in base.children if not cat.parent_only %} |
| <option value="{{cat.trove_cat_id}}">{{cat.fullpath_within_type}}</option> |
| {% endfor %} |
| </select> |
| <br> |
| <input type="submit" value="Add"> |
| {{lib.csrf_token()}} |
| </form> |
| </div> |
| {% endmacro %} |
| |
| {% block content %} |
| {% if c.project.deleted %} |
| <div class="notice">This project has been deleted and is not visible to non-admin users</div> |
| {% endif %} |
| |
| <div class="project_labels"> |
| <h3>Project Labels</h3> |
| <div class="grid-19 trove_add_container"> |
| <form method="POST" class="can-retry" action="update_labels" id="label_edit_form"> |
| {{ c.label_edit.display(id='labels', name='labels', value=c.project.labels) }} |
| <br style="clear:both"> |
| <input type="submit" value="Save"> |
| {{lib.csrf_token()}} |
| </form> |
| </div> |
| </div> |
| {% for base in base_troves if hasattr(c.project, "trove_{}".format(base.shortname))%} |
| {{show_trove_base_cat(base)}} |
| {% endfor %} |
| {% endblock %} |
| |
| {% do g.register_forge_js('js/chosen.jquery.min.js') %} |
| {% do g.register_forge_css('css/chosen.min.css') %} |
| |
| {% block extra_js %} |
| <script type="text/javascript"> |
| $(document).ready(function () { |
| var chosen_opts = {search_contains:true}; |
| $('.trove_add_container form:visible select').chosen(chosen_opts); |
| |
| function add_trove(session_id, type, new_id) { |
| $.post('add_trove_js',{ |
| _session_id:session_id, |
| type:type, |
| new_trove:new_id},function(resp){ |
| if(resp.error_msg){ |
| $('#messages').notify(resp.error_msg, { |
| title: 'Error', |
| status: 'error' |
| }); |
| } |
| else{ |
| var $existing = $('#trove_existing_'+type); |
| $existing.find('span.empty_msg').remove(); |
| var insertAfter = null; |
| $existing.children().each(function() { |
| if($('.trove_fullpath', this).text() < resp.trove_full_path) { |
| insertAfter = this; |
| } |
| }); |
| var $newItem = $('<div><span class="trove_fullpath">'+resp.trove_full_path+'</span> <form class="trove_deleter"><input type="hidden" name="type" value="'+type+'"><input type="hidden" name="trove" value="'+new_id+'">'+del_btn+'</form></div>'); |
| if (insertAfter) { |
| $newItem.insertAfter(insertAfter); |
| } else { |
| $newItem.prependTo($existing); |
| } |
| } |
| }); |
| } |
| |
| var session_id = $('input[name=_session_id]').val(); |
| var del_btn = '<a href="#" class="del_btn" title="Delete"><b data-icon="{{g.icons["delete"].char}}" class="ico {{g.icons["delete"].css}}"></b></a>'; |
| $('form.trove_adder').submit(function(evt){ |
| evt.preventDefault(); |
| var $this = $(this); |
| var type = $this.find('input[name=type]').val(); |
| var new_id = $this.find('select').last().val(); |
| add_trove(session_id, type, new_id); |
| }); |
| $('form.trove_deleter').each(function(){ |
| $(this).find('input[type="submit"]').remove(); |
| $(this).append($(del_btn)); |
| }); |
| $('div.trove_existing').delegate("a.del_btn", "click", function(evt){ |
| evt.preventDefault(); |
| var $form = $(this).closest('form'); |
| var type = $form.find('input[name="type"]').val(); |
| $.post('delete_trove',{ |
| _session_id:session_id, |
| type:type, |
| trove:$form.find('input[name="trove"]').val()},function(){ |
| $form.closest('div').remove(); |
| var holder = $('#trove_existing_'+type); |
| if(!holder.find('div').length){ |
| holder.append('<span class="empty_msg">No categories have been selected.</span>'); |
| } |
| }); |
| }); |
| $('a.choose_other').on('click', function(e){ |
| e.preventDefault(); |
| var $form = $(this).next('form'); |
| $form.show(); |
| $('select', $form).chosen(chosen_opts); |
| }); |
| $('a.recommended_trove').on('click', function(e) { |
| e.preventDefault(); |
| var type = $(this).data('trove'); |
| var new_id = $(this).data('id'); |
| add_trove(session_id, type, new_id); |
| }) |
| }); |
| </script> |
| {% endblock %} |
| |
| {% block extra_css %} |
| <style type="text/css"> |
| .trove_deleter{ |
| display:inline; |
| } |
| .trove_deleter input[type="submit"]{ |
| float:none; |
| } |
| .trove_fullpath{ |
| vertical-align:middle; |
| } |
| .trove_existing{ |
| margin-bottom: 1em; |
| } |
| .trove_add_container { |
| margin-bottom: 1em; |
| padding-bottom: 1em; |
| border: 0 solid #ccc; |
| border-width: 0 0 1px 0; |
| } |
| .recommended_trove { |
| margin-right: 0.5em; |
| } |
| |
| /* for Chosen plugin to display well. Super-long thread with other possible options: https://github.com/harvesthq/chosen/issues/86 */ |
| .trove_add_container{ |
| overflow: visible; |
| } |
| :not(.project_labels) > .trove_add_container:last-of-type { |
| margin-bottom: 250px; |
| } |
| /* for Chosen plugin, use Font-Awesome for icons instead of their sprite |
| Because when we have debug=False in the .ini file, the CSS concatenation makes the path to the sprite incorrect */ |
| .chosen-container-single .chosen-search:after { |
| font-family: FontAwesome; |
| content: "\f002"; /* fa-search */ |
| position: relative; |
| left: -1.5em; |
| } |
| .chosen-container-single .chosen-single div b { |
| background: none; /* cancel out existing sprite, so its not duplicated */ |
| } |
| .chosen-container-single .chosen-single div b:after { |
| content: "▾"; |
| } |
| .chosen-container-single.chosen-with-drop .chosen-single div b:after { |
| content: "▴"; |
| } |
| </style> |
| {% endblock %} |