Improve package creation form

This commit is contained in:
rubenwardy 2018-12-22 11:23:58 +00:00
parent 35f798c862
commit 692628653c
8 changed files with 135 additions and 101 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
config.cfg config.cfg
config.prod.cfg config.prod.cfg
*.sqlite *.sqlite
main.css custom.css
tmp tmp
log.txt log.txt
*.rdb *.rdb

View File

@ -11,7 +11,7 @@
* Copyright 2011-2018 Twitter, Inc. * Copyright 2011-2018 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */
@import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic"); /* @import url("https://fonts.googleapis.com/css?family=Lato:400,700,400italic"); */
:root { :root {
--blue: #375a7f; --blue: #375a7f;
--indigo: #6610f2; --indigo: #6610f2;

View File

@ -5,13 +5,25 @@
* https://petprojects.googlecode.com/svn/trunk/GPL-LICENSE.txt * https://petprojects.googlecode.com/svn/trunk/GPL-LICENSE.txt
*/ */
(function($) { (function($) {
function hide_error(input) {
var err = input.parent().parent().find(".invalid-remaining");
err.hide();
}
function show_error(input, msg) {
var err = input.parent().parent().find(".invalid-remaining");
console.log(err.length);
err.text(msg);
err.show();
}
$.fn.selectSelector = function(source, name, select) { $.fn.selectSelector = function(source, name, select) {
return this.each(function() { return this.each(function() {
var selector = $(this), var selector = $(this),
input = $('input[type=text]', this); input = $('input[type=text]', this);
selector.click(function() { input.focus(); }) selector.click(function() { input.focus(); })
.delegate('.tag a', 'click', function() { .delegate('.badge a', 'click', function() {
var id = $(this).parent().data("id"); var id = $(this).parent().data("id");
for (var i = 0; i < source.length; i++) { for (var i = 0; i < source.length; i++) {
if (source[i].id == id) { if (source[i].id == id) {
@ -23,13 +35,14 @@
}); });
function addTag(item) { function addTag(item) {
var tag = $('<span class="tag"/>') var tag = $('<span class="badge badge-pill badge-primary"/>')
.text(item.toString() + ' ') .text(item.toString() + ' ')
.data("id", item.id) .data("id", item.id)
.append('<a>x</a>') .append('<a>x</a>')
.insertBefore(input); .insertBefore(input);
input.attr("placeholder", null); input.attr("placeholder", null);
select.find("option[value=" + item.id + "]").attr("selected", "selected") select.find("option[value=" + item.id + "]").attr("selected", "selected")
hide_error(input);
} }
function recreate() { function recreate() {
@ -42,6 +55,13 @@
} }
recreate(); 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) { input.keydown(function(e) {
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active) if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
e.preventDefault(); e.preventDefault();
@ -92,7 +112,7 @@
} }
selector.click(function() { input.focus(); }) selector.click(function() { input.focus(); })
.delegate('.tag a', 'click', function() { .delegate('.badge a', 'click', function() {
var id = $(this).parent().data("id"); var id = $(this).parent().data("id");
for (var i = 0; i < selected.length; i++) { for (var i = 0; i < selected.length; i++) {
if (selected[i] == id) { if (selected[i] == id) {
@ -113,13 +133,14 @@
} }
function addTag(id, value) { function addTag(id, value) {
var tag = $('<span class="tag"/>') var tag = $('<span class="badge badge-pill badge-primary"/>')
.text(value) .text(value)
.data("id", id) .data("id", id)
.append(' <a>x</a>') .append(' <a>x</a>')
.insertBefore(input); .insertBefore(input);
input.attr("placeholder", null); input.attr("placeholder", null);
hide_error(input);
} }
function recreate() { function recreate() {
@ -147,6 +168,18 @@
result.change(readFromResult); result.change(readFromResult);
input.focusout(function() {
var item = input.val();
if (item.length == 0) {
input.data("ui-autocomplete").search("");
} else if (item.match(/^([a-z0-9_]+)$/)) {
selectItem(item);
recreate();
input.val("");
}
return true;
});
input.keydown(function(e) { input.keydown(function(e) {
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active) if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
e.preventDefault(); e.preventDefault();
@ -159,7 +192,7 @@
recreate(); recreate();
input.val(""); input.val("");
} else { } else {
alert("Only lowercase alphanumeric and number names allowed."); show_error(input, "Only lowercase alphanumeric and number names allowed.");
} }
e.preventDefault(); e.preventDefault();
return true; return true;

View File

@ -38,27 +38,15 @@
white-space: nowrap; white-space: nowrap;
background: transparent; background: transparent;
} }
.bulletselector .tag { .bulletselector .badge {
background: #375D81;
border-radius: 3px;
-moz-border-radius: 3px;
color: #FFF;
float: left; float: left;
height: 15px; padding: 0.4em 0.8em;
padding: 0.1em 0.4em 0.5em;
margin-right: 0.3em; margin-right: 0.3em;
margin-bottom: 0.3em;
vertical-align: baseline;
}
.bulletselector .tag a {
color: #FFF;
cursor: pointer;
}
.bulletselector .tag a:hover {
color: #0099CC;
text-decoration: none;
} }
.invalid-remaining {
display: none;
}
.t-mll tr td:not(:first-child) { .t-mll tr td:not(:first-child) {
text-align: left; text-align: left;

View File

@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title> <title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
<link rel="stylesheet" type="text/css" href="/static/bootstrap.css"> <link rel="stylesheet" type="text/css" href="/static/bootstrap.css">
<link rel="stylesheet" type="text/css" href="/static/main.css"> <link rel="stylesheet" type="text/css" href="/static/custom.css">
{% block headextra %}{% endblock %} {% block headextra %}{% endblock %}
</head> </head>
@ -122,8 +122,9 @@
<a href="{{ url_for('flatpage', path='help/reporting') }}">Report / DMCA</a> <a href="{{ url_for('flatpage', path='help/reporting') }}">Report / DMCA</a>
</footer> </footer>
<script src="static/jquery.min.js"></script> <script src="/static/jquery.min.js"></script>
<script src="static/popper.min.js"></script> <script src="/static/popper.min.js"></script>
<script src="static/bootstrap.min.js"></script> <script src="/static/bootstrap.min.js"></script>
{% block scriptextra %}{% endblock %}
</body> </body>
</html> </html>

View File

@ -2,7 +2,7 @@
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}"> <div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if field.type != 'HiddenField' and label_visible %} {% if field.type != 'HiddenField' and label_visible %}
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label> <label for="{{ field.id }}">{{ label|safe }}</label>
{% endif %} {% endif %}
{{ field(class_='form-control', **kwargs) }} {{ field(class_='form-control', **kwargs) }}
{% if field.errors %} {% if field.errors %}
@ -13,9 +13,8 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{% macro form_includes() -%} {% macro form_scripts() -%}
<link href="/static/jquery-ui.min.css" rel="stylesheet" type="text/css"> <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/jquery-ui.min.js"></script>
<script src="/static/tagselector.js"></script> <script src="/static/tagselector.js"></script>
{% endmacro %} {% endmacro %}
@ -58,16 +57,17 @@
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}"> <div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if field.type != 'HiddenField' and label_visible %} {% if field.type != 'HiddenField' and label_visible %}
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label> <label for="{{ field.id }}">{{ label|safe }}</label>
{% endif %} {% endif %}
<div class="multichoice_selector bulletselector"> <div class="multichoice_selector bulletselector form-control">
<input type="text" placeholder="Start typing to see suggestions"> <input type="text" placeholder="Start typing to see suggestions">
<div class="clearboth"></div> <div class="clearboth"></div>
</div> </div>
<div class="invalid-remaining invalid-feedback"></div>
{{ field(class_='form-control', **kwargs) }} {{ field(class_='form-control', **kwargs) }}
{% if field.errors %} {% if field.errors %}
{% for e in field.errors %} {% for e in field.errors %}
<p class="help-block">{{ e }}</p> <div class="invalid-feedback">{{ e }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
@ -77,13 +77,14 @@
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}"> <div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if field.type != 'HiddenField' and label_visible %} {% if field.type != 'HiddenField' and label_visible %}
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label> <label for="{{ field.id }}">{{ label|safe }}</label>
{% endif %} {% endif %}
<div class="metapackage_selector bulletselector"> <div class="metapackage_selector bulletselector form-control">
<input type="text" placeholder="Comma-seperated values"> <input type="text" placeholder="Comma-seperated values">
<div class="clearboth"></div> <div class="clearboth"></div>
</div> </div>
{{ field(class_='form-control', **kwargs) }} {{ field(class_='form-control', **kwargs) }}
<div class="invalid-remaining invalid-feedback"></div>
{% if field.errors %} {% if field.errors %}
{% for e in field.errors %} {% for e in field.errors %}
<p class="help-block">{{ e }}</p> <p class="help-block">{{ e }}</p>
@ -96,13 +97,14 @@
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}"> <div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if field.type != 'HiddenField' and label_visible %} {% if field.type != 'HiddenField' and label_visible %}
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
<label for="{{ field.id }}" class="control-label">{{ label|safe }}</label> <label for="{{ field.id }}">{{ label|safe }}</label>
{% endif %} {% endif %}
<div class="deps_selector bulletselector"> <div class="deps_selector bulletselector form-control">
<input type="text" placeholder="Comma-seperated values"> <input type="text" placeholder="Comma-seperated values">
<div class="clearboth"></div> <div class="clearboth"></div>
</div> </div>
{{ field(class_='form-control', **kwargs) }} {{ field(class_='form-control', **kwargs) }}
<div class="invalid-remaining invalid-feedback"></div>
{% if field.errors %} {% if field.errors %}
{% for e in field.errors %} {% for e in field.errors %}
<p class="help-block">{{ e }}</p> <p class="help-block">{{ e }}</p>
@ -134,7 +136,7 @@
{% macro render_submit_field(field, label=None, tabindex=None) -%} {% macro render_submit_field(field, label=None, tabindex=None) -%}
{% if not label %}{% set label=field.label.text %}{% endif %} {% if not label %}{% set label=field.label.text %}{% endif %}
{#<button type="submit" class="form-control btn btn-default btn-primary">{{label}}</button>#} {#<button type="submit" class="form-control btn btn-default btn-primary">{{label}}</button>#}
<input type="submit" value="{{label}}" <input type="submit" value="{{label}}" class="btn btn-primary"
{% if tabindex %}tabindex="{{ tabindex }}"{% endif %} {% if tabindex %}tabindex="{{ tabindex }}"{% endif %}
> >
{%- endmacro %} {%- endmacro %}

View File

@ -7,69 +7,10 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% from "macros/forms.html" import render_field, render_submit_field, form_scripts, render_multiselect_field, render_mpackage_field, render_deps_field, package_lists %}
<h1>Create Package</h1>
<div class="box box_grey alert alert-info"> {% block scriptextra %}
Have you read the Package Inclusion Policy and Guidance yet? {{ form_scripts() }}
<a class="alert_right button" href="{{ url_for('flatpage', path='policy_and_guidance') }}">View</a>
</div>
{% from "macros/forms.html" import render_field, render_submit_field, form_includes, render_multiselect_field, render_mpackage_field, render_deps_field, package_lists %}
{{ form_includes() }}
{{ package_lists() }}
<form method="POST" action="" class="tableform">
{{ form.hidden_tag() }}
<h2 class="pkg_meta">Package</h2>
{{ render_field(form.type, class_="pkg_meta") }}
{{ render_field(form.name, class_="pkg_meta") }}
{{ render_field(form.title, class_="pkg_meta") }}
{{ render_field(form.shortDesc, class_="pkg_meta") }}
{{ render_field(form.desc, class_="pkg_meta") }}
{{ render_multiselect_field(form.tags, class_="pkg_meta") }}
<div class="pkg_meta">
{{ render_field(form.license, class_="not_txp") }}
</div>
{{ render_field(form.media_license, class_="pkg_meta") }}
<div class="pkg_meta">
<h2 class="not_txp">Dependency Info</h2>
{{ render_mpackage_field(form.provides_str, class_="not_txp", placeholder="Comma separated list") }}
{{ render_deps_field(form.harddep_str, class_="not_txp not_game", placeholder="Comma separated list") }}
{{ render_deps_field(form.softdep_str, class_="not_txp not_game", placeholder="Comma separated list") }}
</div>
<h2 class="pkg_meta">Repository and Links</h2>
<div class="pkg_wiz_1">
<p>Enter the repo URL for the package.
If the repo uses git then the metadata will be automatically imported.</p>
<p>Leave blank if you don't have a repo. Click skip if the import fails.</p>
</div>
{{ render_field(form.repo, class_="pkg_repo") }}
<div class="pkg_wiz_1">
<a id="pkg_wiz_1_next" class="btn btn-primary">Next (Autoimport)</a>
<a id="pkg_wiz_1_skip" class="btn btn-default">Skip Autoimport</a>
</div>
<div class="pkg_wiz_2">
Importing... (This may take a while)
</div>
{{ render_field(form.website, class_="pkg_meta") }}
{{ render_field(form.issueTracker, class_="pkg_meta") }}
{{ render_field(form.forums, class_="pkg_meta") }}
<div class="pkg_meta">{{ render_submit_field(form.submit) }}</div>
</form>
<script src="/static/simplemde.min.js"></script> <script src="/static/simplemde.min.js"></script>
<link rel="stylesheet" type="text/css" href="/static/simplemde.min.css"> <link rel="stylesheet" type="text/css" href="/static/simplemde.min.css">
@ -90,3 +31,72 @@
{% endif %} {% endif %}
<script src="/static/package_edit.js"></script> <script src="/static/package_edit.js"></script>
{% endblock %} {% endblock %}
{% block content %}
<h1>Create Package</h1>
<div class="box box_grey alert alert-info">
Have you read the Package Inclusion Policy and Guidance yet?
<a class="alert_right button" href="{{ url_for('flatpage', path='policy_and_guidance') }}">View</a>
</div>
{{ package_lists() }}
<form method="POST" action="" class="tableform">
{{ form.hidden_tag() }}
<fieldset>
<legend>Package</legend>
{{ render_field(form.type, class_="pkg_meta") }}
{{ render_field(form.name, class_="pkg_meta") }}
{{ render_field(form.title, class_="pkg_meta") }}
{{ render_field(form.shortDesc, class_="pkg_meta") }}
{{ render_field(form.desc, class_="pkg_meta") }}
{{ render_multiselect_field(form.tags, class_="pkg_meta") }}
<div class="pkg_meta">
{{ render_field(form.license, class_="not_txp") }}
</div>
{{ render_field(form.media_license, class_="pkg_meta") }}
</fieldset>
<fieldset class="pkg_meta">
<legend class="not_txp">Package</legend>
{{ render_mpackage_field(form.provides_str, class_="not_txp", placeholder="Comma separated list") }}
{{ render_deps_field(form.harddep_str, class_="not_txp not_game", placeholder="Comma separated list") }}
{{ render_deps_field(form.softdep_str, class_="not_txp not_game", placeholder="Comma separated list") }}
</fieldset>
<fieldset>
<legend class="pkg_meta">Repository and Links</legend>
<div class="pkg_wiz_1">
<p>Enter the repo URL for the package.
If the repo uses git then the metadata will be automatically imported.</p>
<p>Leave blank if you don't have a repo. Click skip if the import fails.</p>
</div>
{{ render_field(form.repo, class_="pkg_repo") }}
<div class="pkg_wiz_1">
<a id="pkg_wiz_1_next" class="btn btn-primary">Next (Autoimport)</a>
<a id="pkg_wiz_1_skip" class="btn btn-default">Skip Autoimport</a>
</div>
<div class="pkg_wiz_2">
Importing... (This may take a while)
</div>
{{ render_field(form.website, class_="pkg_meta") }}
{{ render_field(form.issueTracker, class_="pkg_meta") }}
{{ render_field(form.forums, class_="pkg_meta") }}
</fieldset>
<div class="pkg_meta">{{ render_submit_field(form.submit) }}</div>
</form>
{% endblock %}