BIN
app/public/static/images/ui-bg_glass_20_555555_1x400.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
app/public/static/images/ui-bg_glass_40_0078a3_1x400.png
Normal file
After Width: | Height: | Size: 342 B |
BIN
app/public/static/images/ui-bg_glass_40_ffc73d_1x400.png
Normal file
After Width: | Height: | Size: 316 B |
BIN
app/public/static/images/ui-bg_gloss-wave_25_333333_500x100.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 276 B |
BIN
app/public/static/images/ui-bg_inset-soft_25_000000_1x100.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/public/static/images/ui-bg_inset-soft_30_f58400_1x100.png
Normal file
After Width: | Height: | Size: 340 B |
BIN
app/public/static/images/ui-icons_222222_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
app/public/static/images/ui-icons_4b8e0b_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/public/static/images/ui-icons_a83300_256x240.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/public/static/images/ui-icons_cccccc_256x240.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
app/public/static/images/ui-icons_ffffff_256x240.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
7
app/public/static/jquery-ui.min.css
vendored
Normal file
9
app/public/static/jquery-ui.min.js
vendored
Normal file
99
app/public/static/tagselector.js
Normal file
@ -0,0 +1,99 @@
|
||||
/*!
|
||||
* Tag Selector plugin for jQuery: Facilitates selecting multiple tags by extending jQuery UI Autocomplete.
|
||||
* You may use Tag Selector under the terms of either the MIT License or the GNU General Public License (GPL) Version 2.
|
||||
* https://petprojects.googlecode.com/svn/trunk/MIT-LICENSE.txt
|
||||
* https://petprojects.googlecode.com/svn/trunk/GPL-LICENSE.txt
|
||||
*/
|
||||
(function($) {
|
||||
$.fn.tagSelector = function(source, name, select) {
|
||||
return this.each(function() {
|
||||
var selector = $(this),
|
||||
input = $('input[type=text]', this);
|
||||
|
||||
selector.click(function() { input.focus(); })
|
||||
.delegate('.tag a', 'click', function() {
|
||||
var id = $(this).parent().data("id");
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
if (source[i].id == id) {
|
||||
source[i].selected = null;
|
||||
}
|
||||
}
|
||||
select.find("option[value=" + id + "]").attr("selected", null)
|
||||
recreate();
|
||||
});
|
||||
|
||||
function addTag(item) {
|
||||
var tag = $('<span class="tag"/>')
|
||||
.text(item.toString() + ' ')
|
||||
.data("id", item.id)
|
||||
.append('<a>x</a>')
|
||||
.insertBefore(input);
|
||||
input.attr("placeholder", null);
|
||||
select.find("option[value=" + item.id + "]").attr("selected", "selected")
|
||||
}
|
||||
|
||||
function recreate() {
|
||||
selector.find("span").remove();
|
||||
for (var i = 0; i < source.length; i++) {
|
||||
if (source[i].selected) {
|
||||
addTag(source[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
recreate();
|
||||
|
||||
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);
|
||||
input.val("");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
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()
|
||||
));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$(".multichoice_selector").each(function() {
|
||||
var ele = $(this);
|
||||
var sel = ele.parent().find("select");
|
||||
console.log(sel.attr("name"));
|
||||
sel.css("display", "none");
|
||||
|
||||
var options = [];
|
||||
|
||||
sel.find("option").each(function() {
|
||||
var text = $(this).text();
|
||||
options.push({
|
||||
id: $(this).attr("value"),
|
||||
value: text,
|
||||
selected: $(this).attr("selected") ? true : false,
|
||||
toString: function() { return text; },
|
||||
});
|
||||
});
|
||||
|
||||
console.log(options);
|
||||
ele.tagSelector(options, sel.attr("name"), sel);
|
||||
})
|
||||
});
|
||||
})(jQuery);
|
@ -87,7 +87,7 @@ a:hover {
|
||||
}
|
||||
|
||||
.button, .buttonset li a, input[type=submit], input[type=text],
|
||||
input[type=password], textarea, select {
|
||||
input[type=password], textarea, select, .multichoice_selector {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
padding: 0.4em 1em;
|
||||
@ -101,16 +101,39 @@ a:hover {
|
||||
|
||||
header {
|
||||
.button, .buttonset li a, input[type=submit], input[type=text],
|
||||
input[type=password], textarea, select {
|
||||
input[type=password], textarea, select, .multichoice_selector {
|
||||
background: rgba(255,255,255,0.1);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
}
|
||||
|
||||
input[type=text], input[type=password], textarea, select {
|
||||
input[type=text], input[type=password], textarea, select, .multichoice_selector {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ui-autocomplete, ui-front {
|
||||
position:absolute;
|
||||
cursor:default;
|
||||
z-index:1001 !important
|
||||
}
|
||||
|
||||
.ui-autocomplete {
|
||||
background: #333 !important;
|
||||
border: 1px solid #444 !important;
|
||||
|
||||
li {
|
||||
display: block !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 0.3em 0.5em !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
min-width: 200px;
|
||||
}
|
||||
@ -129,13 +152,13 @@ select:not([multiple]) {
|
||||
padding: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.form-group input, .form-group textarea {
|
||||
.form-group input, .form-group textarea, .form-group .multichoice_selector {
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.box .form-group input, .box .form-group textarea {
|
||||
.box .form-group input, .box .form-group textarea, .form-group .multichoice_selector {
|
||||
min-width: 95%;
|
||||
max-width: 95%;
|
||||
}
|
||||
@ -178,6 +201,43 @@ select:not([multiple]) {
|
||||
margin: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
|
||||
.multichoice_selector input {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
width: auto;
|
||||
min-width: 50px;
|
||||
float: left;
|
||||
padding: 4px 0;
|
||||
white-space: nowrap;
|
||||
background: transparent;
|
||||
}
|
||||
.multichoice_selector .tag {
|
||||
background: #375D81;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
color: #FFF;
|
||||
float: left;
|
||||
height: 15px;
|
||||
padding: 0.1em 0.4em 0.5em;
|
||||
margin-right: 0.3em;
|
||||
margin-bottom: 0.3em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
.multichoice_selector .tag a {
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
.multichoice_selector .tag a:hover {
|
||||
color: #0099CC;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
/* Alerts */
|
||||
|
||||
.alert {
|
||||
|
@ -1,42 +1,68 @@
|
||||
{% macro render_field(field, label=None, label_visible=true, right_url=None, right_label=None) -%}
|
||||
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
|
||||
{% if field.type != 'HiddenField' and label_visible %}
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label>
|
||||
{% endif %}
|
||||
{{ field(class_='form-control', **kwargs) }}
|
||||
{% if field.errors %}
|
||||
{% for e in field.errors %}
|
||||
<p class="help-block">{{ e }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
|
||||
{% if field.type != 'HiddenField' and label_visible %}
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label>
|
||||
{% endif %}
|
||||
{{ field(class_='form-control', **kwargs) }}
|
||||
{% if field.errors %}
|
||||
{% for e in field.errors %}
|
||||
<p class="help-block">{{ e }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro form_includes() -%}
|
||||
<link href="/static/jquery-ui.min.css" rel="stylesheet" type="text/css">
|
||||
<script src="/static/jquery.min.js"></script>
|
||||
<script src="/static/jquery-ui.min.js"></script>
|
||||
<script src="/static/tagselector.js"></script>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_multiselect_field(field, label=None, label_visible=true, right_url=None, right_label=None) -%}
|
||||
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
|
||||
{% if field.type != 'HiddenField' and label_visible %}
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label>
|
||||
{% endif %}
|
||||
<div class="multichoice_selector">
|
||||
<input type="text" placeholder="Start typing to see suggestions">
|
||||
<div class="clearboth"></div>
|
||||
</div>
|
||||
{{ field(class_='form-control', **kwargs) }}
|
||||
{% if field.errors %}
|
||||
{% for e in field.errors %}
|
||||
<p class="help-block">{{ e }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_checkbox_field(field, label=None) -%}
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
{{ field(type='checkbox', **kwargs) }} {{ label }}
|
||||
</label>
|
||||
</div>
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
{{ field(type='checkbox', **kwargs) }} {{ label }}
|
||||
</label>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro render_radio_field(field) -%}
|
||||
{% for value, label, checked in field.iter_choices() %}
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="{{ field.id }}" id="{{ field.id }}" value="{{ value }}"{% if checked %} checked{% endif %}>
|
||||
{{ label }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for value, label, checked in field.iter_choices() %}
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="{{ field.id }}" id="{{ field.id }}" value="{{ value }}"{% if checked %} checked{% endif %}>
|
||||
{{ label }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro render_submit_field(field, label=None, tabindex=None) -%}
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
{#<button type="submit" class="form-control btn btn-default btn-primary">{{label}}</button>#}
|
||||
<input type="submit" value="{{label}}"
|
||||
{% if tabindex %}tabindex="{{ tabindex }}"{% endif %}
|
||||
>
|
||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||
{#<button type="submit" class="form-control btn btn-default btn-primary">{{label}}</button>#}
|
||||
<input type="submit" value="{{label}}"
|
||||
{% if tabindex %}tabindex="{{ tabindex }}"{% endif %}
|
||||
>
|
||||
{%- endmacro %}
|
||||
|
@ -10,7 +10,9 @@
|
||||
{% block content %}
|
||||
<h2>Create Package</h2>
|
||||
|
||||
{% from "macros/forms.html" import render_field, render_submit_field %}
|
||||
{% from "macros/forms.html" import render_field, render_submit_field, form_includes, render_multiselect_field %}
|
||||
{{ form_includes() }}
|
||||
|
||||
<form method="POST" action="" class="tableform">
|
||||
{{ form.hidden_tag() }}
|
||||
|
||||
@ -20,9 +22,9 @@
|
||||
{{ render_field(form.desc, class_="pkg_meta") }}
|
||||
{{ render_field(form.type, class_="pkg_meta") }}
|
||||
{{ render_field(form.license, class_="pkg_meta") }}
|
||||
{{ render_field(form.tags, class_="pkg_meta") }}
|
||||
{{ render_field(form.harddeps, class_="pkg_meta") }}
|
||||
{{ render_field(form.softdeps, class_="pkg_meta") }}
|
||||
{{ render_multiselect_field(form.tags, class_="pkg_meta") }}
|
||||
{{ render_multiselect_field(form.harddeps, class_="pkg_meta") }}
|
||||
{{ render_multiselect_field(form.softdeps, class_="pkg_meta") }}
|
||||
|
||||
<div class="pkg_wiz_1">
|
||||
<p>Enter the repo URL for the package.
|
||||
@ -48,7 +50,6 @@
|
||||
</form>
|
||||
|
||||
{% if enable_wizard %}
|
||||
<script src="/static/jquery.min.js"></script>
|
||||
<script src="/static/url.min.js"></script>
|
||||
<script src="/static/polltask.js"></script>
|
||||
<script src="/static/package_create.js"></script>
|
||||
|
@ -5,7 +5,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% from "macros/forms.html" import render_field, render_submit_field %}
|
||||
{% from "macros/forms.html" import render_field, render_submit_field, form_includes, render_multiselect_field %}
|
||||
{{ form_includes() }}
|
||||
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
|
||||
@ -15,7 +17,7 @@
|
||||
{{ render_field(form.desc) }}
|
||||
{{ render_field(form.type) }}
|
||||
{{ render_field(form.license) }}
|
||||
{{ render_field(form.tags) }}
|
||||
{{ render_multiselect_field(form.tags) }}
|
||||
{{ render_field(form.repo) }}
|
||||
{{ render_field(form.website) }}
|
||||
{{ render_field(form.issueTracker) }}
|
||||
|
@ -124,9 +124,9 @@ class PackageForm(FlaskForm):
|
||||
desc = TextAreaField("Long Description", [Optional(), Length(0,10000)])
|
||||
type = SelectField("Type", [InputRequired()], choices=PackageType.choices(), coerce=PackageType.coerce, default=PackageType.MOD)
|
||||
license = QuerySelectField("License", [InputRequired()], query_factory=lambda: License.query, get_pk=lambda a: a.id, get_label=lambda a: a.name)
|
||||
tags = QuerySelectMultipleField('Tags', query_factory=lambda: Tag.query, get_pk=lambda a: a.id, get_label=lambda a: a.title)
|
||||
harddeps = QuerySelectMultipleField('Dependencies', query_factory=lambda: Package.query, get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
|
||||
softdeps = QuerySelectMultipleField('Soft Dependencies', query_factory=lambda: Package.query, get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
|
||||
tags = QuerySelectMultipleField('Tags', query_factory=lambda: Tag.query.order_by(db.asc(Tag.name)), get_pk=lambda a: a.id, get_label=lambda a: a.title)
|
||||
harddeps = QuerySelectMultipleField('Dependencies', query_factory=lambda: Package.query.join(User).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
|
||||
softdeps = QuerySelectMultipleField('Soft Dependencies', query_factory=lambda: Package.query.join(User).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
|
||||
repo = StringField("Repo URL", [Optional(), URL()])
|
||||
website = StringField("Website URL", [Optional(), URL()])
|
||||
issueTracker = StringField("Issue Tracker URL", [Optional(), URL()])
|
||||
|