mirror of https://git.sr.ht/~sircmpwn/hub.sr.ht
Add project config page
This commit is contained in:
parent
cbc4326657
commit
2ec9808304
|
@ -6,7 +6,7 @@ from hubsrht.types import Project, RepoType, Visibility
|
||||||
from srht.database import db
|
from srht.database import db
|
||||||
from srht.flask import paginate_query
|
from srht.flask import paginate_query
|
||||||
from srht.oauth import current_user, loginrequired
|
from srht.oauth import current_user, loginrequired
|
||||||
from srht.validation import Validation
|
from srht.validation import Validation, valid_url
|
||||||
|
|
||||||
projects = Blueprint("projects", __name__)
|
projects = Blueprint("projects", __name__)
|
||||||
|
|
||||||
|
@ -93,3 +93,32 @@ def create_POST():
|
||||||
return redirect(url_for("projects.summary_GET",
|
return redirect(url_for("projects.summary_GET",
|
||||||
owner=current_user.canonical_name,
|
owner=current_user.canonical_name,
|
||||||
project_name=project.name))
|
project_name=project.name))
|
||||||
|
|
||||||
|
@projects.route("/<owner>/<project_name>/settings")
|
||||||
|
@loginrequired
|
||||||
|
def config_GET(owner, project_name):
|
||||||
|
owner, project = get_project(owner, project_name, ProjectAccess.write)
|
||||||
|
return render_template("project-config.html", view="add more",
|
||||||
|
owner=owner, project=project)
|
||||||
|
|
||||||
|
@projects.route("/<owner>/<project_name>/settings", methods=["POST"])
|
||||||
|
@loginrequired
|
||||||
|
def config_POST(owner, project_name):
|
||||||
|
owner, project = get_project(owner, project_name, ProjectAccess.write)
|
||||||
|
|
||||||
|
valid = Validation(request)
|
||||||
|
description = valid.require("description")
|
||||||
|
website = valid.optional("website")
|
||||||
|
valid.expect(not website or valid_url(website),
|
||||||
|
"Website must be a valid http or https URL")
|
||||||
|
if not valid.ok:
|
||||||
|
return render_template("project-config.html", view="add more",
|
||||||
|
owner=owner, project=project, **valid.kwargs)
|
||||||
|
|
||||||
|
project.description = description
|
||||||
|
project.website = website
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return redirect(url_for("projects.summary_GET",
|
||||||
|
owner=current_user.canonical_name,
|
||||||
|
project_name=project.name))
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
{% extends "project-base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 event-list">
|
||||||
|
<form class="event" method="POST">
|
||||||
|
{{csrf_token()}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">
|
||||||
|
Project name <small class="text-muted">(you can't edit this)</small>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
class="form-control"
|
||||||
|
readonly
|
||||||
|
value="{{project.name}}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description">Description</label>
|
||||||
|
<input
|
||||||
|
class="form-control {{valid.cls("description")}}"
|
||||||
|
type="text"
|
||||||
|
id="description"
|
||||||
|
name="description"
|
||||||
|
placeholder="Short description of your project, shown in lists"
|
||||||
|
value="{{description or project.description}}"
|
||||||
|
required />
|
||||||
|
{{valid.summary("description")}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="project-website">Website</label>
|
||||||
|
<input
|
||||||
|
class="form-control {{valid.cls("website")}}"
|
||||||
|
type="text"
|
||||||
|
id="website"
|
||||||
|
name="website"
|
||||||
|
placeholder="http://example.org"
|
||||||
|
value="{{website or project.website or ""}}" />
|
||||||
|
{{valid.summary("website")}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend>Project Visibility</legend>
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="form-check-label">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="visibility"
|
||||||
|
value="public"
|
||||||
|
checked> Public
|
||||||
|
<small id="visibility-public-help" class="form-text text-muted">
|
||||||
|
Shown on your profile and listed in the public project index
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<label
|
||||||
|
class="form-check-label"
|
||||||
|
title="Visible to anyone with the link, but not shown on your profile"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="visibility"
|
||||||
|
value="unlisted"> Unlisted
|
||||||
|
<small id="visibility-unlisted-help" class="form-text text-muted">
|
||||||
|
Visible to anyone who knows the URL, but not shown on your profile
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<label
|
||||||
|
class="form-check-label"
|
||||||
|
title="Only visible to you and your collaborators"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="visibility"
|
||||||
|
value="private"> Private
|
||||||
|
<small id="visibility-unlisted-help" class="form-text text-muted">
|
||||||
|
Only visible to you and your collaborators
|
||||||
|
</small>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row form-group" style="margin-top: 1rem">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block">
|
||||||
|
Save details {{icon('caret-right')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-10 event-list">
|
||||||
|
<div class="event">
|
||||||
|
<h3>Source code repositories</h3>
|
||||||
|
<p>
|
||||||
|
Git and Mercurial repositories help you share this project's source
|
||||||
|
code with your collaborators.
|
||||||
|
</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("sources.new_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-primary btn-block"
|
||||||
|
>
|
||||||
|
Add repository {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("sources.manage_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-default btn-block"
|
||||||
|
>
|
||||||
|
Manage sources {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="event">
|
||||||
|
<h3>Mailing lists</h3>
|
||||||
|
<p>
|
||||||
|
Mailing lists give users a place to ask questions about the project
|
||||||
|
or send patches to contribute to the code.
|
||||||
|
</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("mailing_lists.new_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-primary btn-block"
|
||||||
|
>
|
||||||
|
Add mailing list {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("mailing_lists.manage_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-default btn-block"
|
||||||
|
>
|
||||||
|
Manage mailing lists {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="event">
|
||||||
|
<h3>Ticket trackers</h3>
|
||||||
|
<p>
|
||||||
|
Bug trackers give you a place to organize your tasks and record known
|
||||||
|
defects.
|
||||||
|
</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("trackers.new_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-primary btn-block"
|
||||||
|
>
|
||||||
|
Add tracker {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="{{url_for("trackers.manage_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name)}}"
|
||||||
|
class="btn btn-default btn-block"
|
||||||
|
>
|
||||||
|
Manage trackers {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="event">
|
||||||
|
<h3>Delete project</h3>
|
||||||
|
<p>
|
||||||
|
This will permanently delete your project,
|
||||||
|
<strong>{{project.name}}</strong>. This cannot be undone.
|
||||||
|
</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="btn btn-danger btn-block"
|
||||||
|
>
|
||||||
|
Delete project {{icon('caret-right')}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -14,6 +14,15 @@
|
||||||
owner=owner.canonical_name,
|
owner=owner.canonical_name,
|
||||||
project_name=project.name), "summary")}}
|
project_name=project.name), "summary")}}
|
||||||
</li>
|
</li>
|
||||||
|
{% if project.website %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a
|
||||||
|
class="nav-link"
|
||||||
|
href="{{project.website}}"
|
||||||
|
rel="noopener nofollow"
|
||||||
|
>website {{icon('external-link-alt')}}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% if any(project.source_repos) %}
|
{% if any(project.source_repos) %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{{link(url_for("sources.sources_GET",
|
{{link(url_for("sources.sources_GET",
|
||||||
|
@ -36,11 +45,6 @@
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# TODO
|
{# TODO
|
||||||
<li class="nav-item">
|
|
||||||
<a
|
|
||||||
class="nav-link" href="#"
|
|
||||||
>website {{icon('external-link-alt')}}</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{{link("#", "documentation")}}
|
{{link("#", "documentation")}}
|
||||||
</li>
|
</li>
|
||||||
|
@ -48,7 +52,9 @@
|
||||||
{% if current_user and current_user.id == owner.id %}
|
{% if current_user and current_user.id == owner.id %}
|
||||||
<li class="flex-grow-1"></li>
|
<li class="flex-grow-1"></li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{{link("#", "add more +")}}
|
{{link(url_for("projects.config_GET",
|
||||||
|
owner=owner.canonical_name, project_name=project.name), "more +",
|
||||||
|
alternates=["add more"])}}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -63,8 +63,8 @@
|
||||||
>Add mailing lists {{icon('arrow-right')}}</a>
|
>Add mailing lists {{icon('arrow-right')}}</a>
|
||||||
<br />
|
<br />
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
Mailing lists give users a means of asking questions about the
|
Mailing lists give users a place to ask questions about the
|
||||||
project or sending patches to contribute to the source code.
|
project or send patches to contribute to the code.
|
||||||
</small>
|
</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
dismiss
|
dismiss
|
||||||
</button>
|
</button>
|
||||||
You're all set! If you want to set up more things for your project,
|
You're all set! If you want to set up more things for your project,
|
||||||
click "add more" on the top right.
|
click "more +" on the top right.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Project(Base):
|
||||||
|
|
||||||
name = sa.Column(sa.Unicode(128), nullable=False)
|
name = sa.Column(sa.Unicode(128), nullable=False)
|
||||||
description = sa.Column(sa.Unicode(512), nullable=False)
|
description = sa.Column(sa.Unicode(512), nullable=False)
|
||||||
|
website = sa.Column(sa.Unicode)
|
||||||
visibility = sa.Column(sau.ChoiceType(Visibility, impl=sa.String()),
|
visibility = sa.Column(sau.ChoiceType(Visibility, impl=sa.String()),
|
||||||
nullable=False, server_default="unlisted")
|
nullable=False, server_default="unlisted")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue