from app.rediscache import has_key, set_key, make_download_key
from app.models import *
-from app.tasks.importtasks import makeVCSRelease, checkZipRelease
+from app.tasks.importtasks import makeVCSRelease, checkZipRelease, updateMetaFromRelease
from app.utils import *
from celery import uuid
db.session.commit()
checkZipRelease.apply_async((rel.id, uploadedPath), task_id=rel.task_id)
+ updateMetaFromRelease.delay(rel.id, uploadedPath)
msg = "Release {} created".format(rel.title)
addNotification(package.maintainers, current_user, msg, rel.getEditURL(), package)
return render_template("packages/release_new.html", package=package, form=form)
+
@bp.route("/packages/<author>/<name>/releases/<id>/download/")
@is_package_page
def download_release(package, id):
return redirect(release.url, code=300)
+
@bp.route("/packages/<author>/<name>/releases/<id>/", methods=["GET", "POST"])
@login_required
@is_package_page
$.fn.selectSelector = function(source, select) {
return this.each(function() {
- var selector = $(this),
- input = $('input[type=text]', this);
+ var selector = $(this),
+ input = $('input[type=text]', this);
- selector.click(function() { input.focus(); })
- .delegate('.badge a', 'click', function() {
- var id = $(this).parent().data("id");
- select.find("option[value=" + id + "]").attr("selected", false)
- recreate();
- });
+ selector.click(function() { input.focus(); })
+ .delegate('.badge a', 'click', function() {
+ var id = $(this).parent().data("id");
+ select.find("option[value=" + id + "]").attr("selected", false)
+ recreate();
+ });
- function addTag(id, text) {
- $('<span class="badge badge-pill badge-primary"/>')
- .text(text + ' ')
- .data("id", id)
- .append('<a>x</a>')
- .insertBefore(input);
- input.attr("placeholder", null);
- select.find("option[value='" + id + "']").attr("selected", "selected")
- hide_error(input);
- }
+ function addTag(id, text) {
+ $('<span class="badge badge-pill badge-primary"/>')
+ .text(text + ' ')
+ .data("id", id)
+ .append('<a>x</a>')
+ .insertBefore(input);
+ input.attr("placeholder", null);
+ select.find("option[value='" + id + "']").attr("selected", "selected")
+ hide_error(input);
+ }
- function recreate() {
- selector.find("span").remove();
- select.find("option").each(function() {
- if (this.hasAttribute("selected")) {
- addTag(this.getAttribute("value"), this.innerText);
- }
- });
+ function recreate() {
+ selector.find("span").remove();
+ select.find("option").each(function() {
+ if (this.hasAttribute("selected")) {
+ addTag(this.getAttribute("value"), this.innerText);
+ }
+ });
+ }
+ recreate();
+
+ input.focusout(function(e) {
+ var value = input.val().trim()
+ if (value != "") {
+ show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
}
- recreate();
+ })
- input.focusout(function(e) {
- var value = input.val().trim()
- if (value != "") {
- show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
- }
+ input.keydown(function(e) {
+ if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
+ e.preventDefault();
})
+ .autocomplete({
+ minLength: 0,
+ source: source,
+ select: function(event, ui) {
+ addTag(ui.item.id, ui.item.toString());
+ input.val("");
+ return false;
+ }
+ }).focus(function() {
+ // The following works only once.
+ // $(this).trigger('keydown.autocomplete');
+ // As suggested by digitalPBK, works multiple times
+ // $(this).data("autocomplete").search($(this).val());
+ // As noted by Jonny in his answer, with newer versions use uiAutocomplete
+ $(this).data("ui-autocomplete").search($(this).val());
+ });
- input.keydown(function(e) {
- if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
- e.preventDefault();
- })
- .autocomplete({
- minLength: 0,
- source: source,
- select: function(event, ui) {
- addTag(ui.item.id, ui.item.toString());
- input.val("");
- return false;
- }
- }).focus(function() {
- // The following works only once.
- // $(this).trigger('keydown.autocomplete');
- // As suggested by digitalPBK, works multiple times
- // $(this).data("autocomplete").search($(this).val());
- // As noted by Jonny in his answer, with newer versions use uiAutocomplete
- $(this).data("ui-autocomplete").search($(this).val());
- });
-
- input.data('ui-autocomplete')._renderItem = function(ul, item) {
- return $('<li/>')
- .data('item.autocomplete', item)
- .append($('<a/>').text(item.toString()))
- .appendTo(ul);
- };
+ input.data('ui-autocomplete')._renderItem = function(ul, item) {
+ return $('<li/>')
+ .data('item.autocomplete', item)
+ .append($('<a/>').text(item.toString()))
+ .appendTo(ul);
+ };
- input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
- var ul = this.menu.element;
- ul.outerWidth(Math.max(
- ul.width('').outerWidth(),
- selector.outerWidth()
- ));
- };
- });
+ input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
+ var ul = this.menu.element;
+ ul.outerWidth(Math.max(
+ ul.width('').outerWidth(),
+ selector.outerWidth()
+ ));
+ };
+ });
}
$.fn.csvSelector = function(source, name, result, allowSlash) {
--- /dev/null
+{% extends "base.html" %}
+
+{% block title %}
+ Tags
+{% endblock %}
+
+{% block content %}
+
+<style>
+ table {
+ width:auto;
+ }
+ td {
+ white-space:nowrap;
+ }
+ table td:last-child {
+ width: 100%;
+ }
+</style>
+
+<table class="table">
+ <tr>
+ <th>Package</th>
+ <th>Tags</th>
+ </tr>
+ {% for package in packages %}
+ <tr>
+ <td>
+ <a href="{{ package.getDetailsURL() }}">
+ {{ package.title }}
+ </a>
+
+ by {{ package.author.display_name }}
+ </td>
+ <td class="tags">
+ {% for tag in package.tags %}
+ <span class="badge badge-primary mr-1">{{ tag.title }}</span>
+ {% endfor %}
+ <a class="badge badge-secondary add-btn px-2" href="#">
+ <i class="fas fa-plus"></i>
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+
+<div class="modal">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title">{{ _("Edit tags") }}</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <select name="tags" multiple>
+ {% for tag in tags %}
+ <option value="{{ tag.name }}">{{ tag.title }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary">Update</button>
+ </div>
+ </div>
+ </div>
+</div>
+{% endblock %}
+
+{% from "macros/forms.html" import form_scripts %}
+
+{% block scriptextra %}
+{{ form_scripts() }}
+
+<script>
+ $(".add-btn").click(function() {
+ const row = $(this).parent().parent()
+
+ $(".modal select option").removeAttr("selected");
+ $(".multichoice_selector").remove();
+
+ $(".modal .modal-body").prepend(`
+ <div class="multichoice_selector bulletselector form-control">
+ <input type="text" placeholder="Start typing to see suggestions">
+ <div class="clearboth"></div>
+ </div>
+ `);
+
+ $(".modal").modal("show");
+ $(".modal input").focus();
+ $(".multichoice_selector").each(function() {
+ var ele = $(this);
+ var sel = ele.parent().find("select");
+ sel.hide();
+
+ var options = [];
+ sel.find("option").each(function() {
+ var text = $(this).text();
+ options.push({
+ id: $(this).attr("value"),
+ value: text,
+ toString: function() { return text; },
+ });
+ });
+
+ ele.selectSelector(options, sel);
+ });
+ });
+
+</script>
+{% endblock %}