Browse Source

Users can create and remove Projects -- WIP

pull/217/head
Pēteris Caune 6 years ago
parent
commit
4e6fa38ec6
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
14 changed files with 277 additions and 19 deletions
  1. +1
    -0
      hc/accounts/admin.py
  2. +1
    -1
      hc/accounts/models.py
  3. +45
    -2
      hc/accounts/views.py
  4. +1
    -2
      hc/front/views.py
  5. +2
    -0
      hc/urls.py
  6. +21
    -1
      static/css/profile.css
  7. +2
    -2
      static/css/settings.css
  8. +13
    -0
      static/js/profile.js
  9. +1
    -1
      templates/accounts/billing.html
  10. +143
    -4
      templates/accounts/profile.html
  11. +45
    -3
      templates/accounts/project.html
  12. +0
    -1
      templates/base.html
  13. +1
    -1
      templates/front/channels.html
  14. +1
    -1
      templates/front/remove_check_modal.html

+ 1
- 0
hc/accounts/admin.py View File

@ -107,6 +107,7 @@ class ProfileAdmin(admin.ModelAdmin):
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
readonly_fields = ("code", "owner")
list_select_related = ("owner", )
list_display = ("id", "name_", "users", "engagement", "switch")


+ 1
- 1
hc/accounts/models.py View File

@ -202,7 +202,7 @@ class Profile(models.Model):
class Project(models.Model):
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
code = models.UUIDField(default=uuid.uuid4, unique=True)
name = models.CharField(max_length=200, blank=True)
owner = models.ForeignKey(User, models.CASCADE)
api_key = models.CharField(max_length=128, blank=True)


+ 45
- 2
hc/accounts/views.py View File

@ -183,6 +183,7 @@ def profile(request):
ctx = {
"page": "profile",
"profile": profile,
"my_projects_status": "default"
}
if request.method == "POST":
@ -192,16 +193,50 @@ def profile(request):
elif "set_password" in request.POST:
profile.send_set_password_link()
return redirect("hc-link-sent")
elif "leave_project" in request.POST:
code = request.POST["code"]
try:
project = Project.objects.get(code=code,
member__user=request.user)
except Project.DoesNotExist:
return HttpResponseBadRequest()
if profile.current_project == project:
profile.current_project = None
profile.save()
Member.objects.filter(project=project, user=request.user).delete()
ctx["left_project"] = project
ctx["my_projects_status"] = "info"
# Retrieve projects right before rendering the template--
# The list of the projects might have *just* changed
ctx["projects"] = list(profile.projects())
return render(request, "accounts/profile.html", ctx)
@login_required
@require_POST
def add_project(request):
form = ProjectNameForm(request.POST)
if not form.is_valid():
return HttpResponseBadRequest()
project = Project(owner=request.user)
project.code = project.badge_key = str(uuid.uuid4())
project.name = form.cleaned_data["name"]
project.save()
return redirect("hc-switch-project", project.code)
@login_required
def project(request, code):
project = Project.objects.get(code=code, owner_id=request.user.id)
ctx = {
"page": "profile",
"page": "project",
"project": project,
"show_api_keys": False,
"project_name_status": "default",
@ -460,3 +495,11 @@ def close(request):
request.session.flush()
return redirect("hc-index")
@require_POST
@login_required
def remove_project(request, code):
project = Project.objects.get(code=code, owner=request.user)
project.delete()
return redirect("hc-profile")

+ 1
- 2
hc/front/views.py View File

@ -7,7 +7,7 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core import signing
from django.db.models import Count, Q
from django.db.models import Count
from django.http import (Http404, HttpResponse, HttpResponseBadRequest,
HttpResponseForbidden, JsonResponse)
from django.shortcuts import get_object_or_404, redirect, render
@ -17,7 +17,6 @@ from django.utils import timezone
from django.utils.crypto import get_random_string
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from hc.accounts.models import Project
from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
Ping, Notification)
from hc.api.transports import Telegram


+ 2
- 0
hc/urls.py View File

@ -7,7 +7,9 @@ urlpatterns = [
path('admin/login/', accounts_views.login),
path('admin/', admin.site.urls),
path('accounts/', include('hc.accounts.urls')),
path('projects/add/', accounts_views.add_project, name="hc-add-project"),
path('projects/<uuid:code>/settings/', accounts_views.project, name="hc-project-settings"),
path('projects/<uuid:code>/remove/', accounts_views.remove_project, name="hc-remove-project"),
path('', include('hc.api.urls')),
path('', include('hc.front.urls')),
path('', include('hc.payments.urls'))


+ 21
- 1
static/css/profile.css View File

@ -45,4 +45,24 @@ span.loading {
font-size: 12px;
border-radius: 2px;
padding: 2px 6px;
}
}
#my-projects th {
border-top: 0;
}
#my-projects td {
vertical-align: middle;
}
#my-projects .num-checks {
}
#my-projects .name {
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

+ 2
- 2
static/css/settings.css View File

@ -15,13 +15,13 @@
color: #5cb85c;
}
#close-account {
#close-account, #remove-project {
margin-left: 24px;
border-color: #d43f3a;
color: #d43f3a;
}
#close-account:hover {
#close-account:hover, #remove-project:hover {
background-color: #ffebea;
}


+ 13
- 0
static/js/profile.js View File

@ -0,0 +1,13 @@
$(function() {
$(".leave-project").click(function() {
var $this = $(this);
$("#leave-project-name").text($this.data("name"));
$("#leave-project-code").val($this.data("code"));
$('#leave-project-modal').modal("show");
return false;
});
});

+ 1
- 1
templates/accounts/billing.html View File

@ -180,7 +180,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Change Billing Plan</h4>
<h4>Change Billing Plan</h4>
</div>
<div class="modal-body">
<div class="row">


+ 143
- 4
templates/accounts/profile.html View File

@ -60,6 +60,73 @@
</div>
</div>
<div class="panel panel-{{ my_projects_status }}">
<div class="panel-body settings-block">
{% csrf_token %}
<h2>My Projects</h2>
{% if projects %}
<table id="my-projects" class="table">
<tr>
<th>Project</th>
<th>Checks</th>
<th>My Role</th>
<th></th>
</tr>
{% for project in profile.projects %}
<tr>
<td>
<div class="name">{{ project }}</div>
</td>
<td>
<a class="num-checks" href="{% url 'hc-switch-project' project.code %}">
{% with project.check_set.count as n %}
{{ n }} check{{ n|pluralize }}
{% endwith %}
</a>
</td>
<td>
{% if project.owner == request.user %}
Owner
{% else %}
Member
{% endif %}
</td>
<td>
{% if project.owner == request.user %}
<a
href="{% url 'hc-project-settings' project.code %}"
class="pull-right">Settings</a>
{% else %}
<a
href="#"
data-name="{{ project }}"
data-code="{{ project.code }}"
class="pull-right leave-project">Leave</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>You don't have any projects. Create one!</p>
{% endif %}
<a
id="create-project"
href="#"
class="btn btn-default pull-right"
data-toggle="modal"
data-target="#create-project-modal">Create Project</a>
</div>
{% if left_project %}
<div class="panel-footer">
Left project <strong>{{ left_project }}</strong>.
</div>
{% endif %}
</div>
<div class="panel panel-default">
<div class="panel-body settings-block">
{% csrf_token %}
@ -71,8 +138,6 @@
data-toggle="modal"
data-target="#close-account-modal">Close Account</a>
This will permanently remove your {% site_name %} account
<form action="{% url 'hc-close' %}" method="post">
</form>
</div>
</div>
</div>
@ -80,12 +145,12 @@
<div id="close-account-modal" class="modal">
<div class="modal-dialog">
<form id="close-account-form" method="post" action="{% url 'hc-close' %}">
<form method="post" action="{% url 'hc-close' %}">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Close Account?</h4>
<h4>Close Account?</h4>
</div>
<div class="modal-body">
<p></p>
@ -104,4 +169,78 @@
</form>
</div>
</div>
<div id="create-project-modal" class="modal">
<div class="modal-dialog">
<form method="post" action="{% url 'hc-add-project' %}" class="form-horizontal">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4>Create Project</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="project-name" class="col-sm-4 control-label">Project Name</label>
<div class="col-sm-7">
<input
type="text"
class="form-control"
id="project-name"
name="name">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button
type="submit"
name="set_project_name"
class="btn btn-primary">Create Project</button>
</div>
</div>
</form>
</div>
</div>
<div id="leave-project-modal" class="modal">
<div class="modal-dialog">
<form id="leave-project-form" method="post">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4>Leave This Project?</h4>
</div>
<div class="modal-body">
<p>
You are about to leave project <strong id="leave-project-name"></strong>.
You will lose access to its checks and integrations.
</p>
<p>Are you sure?</p>
<input
type="hidden"
name="code"
id="leave-project-code" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button
type="submit"
name="leave_project"
class="btn btn-danger">Leave Project</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% block scripts %}
{% compress js %}
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/profile.js' %}"></script>
{% endcompress %}
{% endblock %}

+ 45
- 3
templates/accounts/project.html View File

@ -149,6 +149,21 @@
{% endif %}
</div>
<div class="panel panel-default">
<div class="panel-body settings-block">
{% csrf_token %}
<h2>Remove Project</h2>
<a href="#"
id="remove-project"
class="btn btn-default pull-right"
data-toggle="modal"
data-target="#remove-project-modal">Remove Project</a>
This will permanently remove project {{ project }}.
<form action="{% url 'hc-remove-project' project.code %}" method="post">
</form>
</div>
</div>
</div>
</div>
@ -159,7 +174,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Revoke API Keys?</h4>
<h4>Revoke API Keys?</h4>
</div>
<div class="modal-body">
<p>You are about to revoke your current API keys.</p>
@ -188,7 +203,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Remove Team Member</h4>
<h4>Remove Team Member</h4>
</div>
<div class="modal-body">
<p>You are about to remove <strong id="rtm-email"></strong> from the project.</p>
@ -217,7 +232,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Invite a Team Member</h4>
<h4>Invite a Team Member</h4>
</div>
<div class="modal-body">
<ul>
@ -281,6 +296,33 @@
</form>
</div>
</div>
<div id="remove-project-modal" class="modal">
<div class="modal-dialog">
<form method="post" action="{% url 'hc-remove-project' project.code %}">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4>Remove "{{ project }}"?</h4>
</div>
<div class="modal-body">
<p>Danger zone! You are about to permanently remove
project <strong>{{ project }}</strong> and all
of its associated checks and integrations. Are you sure?
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button
type="submit"
class="btn btn-danger">Remove Project</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% block scripts %}


+ 0
- 1
templates/base.html View File

@ -95,7 +95,6 @@
<li {% if page == 'channels' %} class="active" {% endif %}>
<a href="{% url 'hc-channels' %}">Integrations</a>
</li>
{% endif %}


+ 1
- 1
templates/front/channels.html View File

@ -306,7 +306,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">
<h4>
Remove this
<span class="remove-channel-kind">---</span>
Integration?


+ 1
- 1
templates/front/remove_check_modal.html View File

@ -9,7 +9,7 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="remove-check-title">Remove Check <span class="remove-check-name">{{ check.name_then_code }}</span></h4>
<h4>Remove Check <span class="remove-check-name">{{ check.name_then_code }}</span></h4>
</div>
<div class="modal-body">
<p>You are about to remove check


Loading…
Cancel
Save