Skip to content

Commit

Permalink
Add a "Run Pipeline" button in the Pipeline modal of the Project deta…
Browse files Browse the repository at this point in the history
…ils view #84 (#94)

* Add a "Run Pipeline" button in the Pipeline modal of the Project details view #84

Signed-off-by: Thomas Druez <tdruez@nexb.com>

* Enable Pipeline addition from the Project details view #84

Signed-off-by: Thomas Druez <tdruez@nexb.com>

* Set the proper type="reset" on close button #84

Signed-off-by: Thomas Druez <tdruez@nexb.com>
  • Loading branch information
tdruez committed Feb 12, 2021
1 parent 434f7f9 commit 97ed37d
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 6 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

### v1.1.0 (unreleased)

- Add a "Run Pipeline" button in the Pipeline modal of the Project details view
Pipelines can now be added from the Project details view
https://github.com/nexB/scancode.io/issues/84

- Upgrade scancode-toolkit to version 21.2.9

- Allow to start the pipeline run immediately on addition in the `add_pipeline` action
of the Project API endpoint.
of the Project API endpoint
https://github.com/nexB/scancode.io/issues/92

- Rename the pipes.outputs module to pipes.output for consistency
Expand Down
13 changes: 13 additions & 0 deletions scanpipe/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ProjectForm(forms.ModelForm):
)
run_pipeline = forms.BooleanField(
label="Run the selected pipeline",
initial=True,
required=False,
)

Expand Down Expand Up @@ -71,6 +72,18 @@ def save(self, *args, **kwargs):
return project


class AddPipelineForm(forms.Form):
pipeline = forms.ChoiceField(
choices=EMPTY_CHOICE + scanpipe_app_config.pipelines,
required=True,
)
run_pipeline = forms.BooleanField(
label="Run the selected pipeline",
initial=True,
required=False,
)


class ProjectFilterSet(django_filters.FilterSet):
search = django_filters.CharFilter(field_name="name", lookup_expr="icontains")

Expand Down
5 changes: 4 additions & 1 deletion scanpipe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import traceback
import uuid
from contextlib import suppress
from datetime import datetime
from pathlib import Path

from django.core import checks
Expand All @@ -34,6 +33,7 @@
from django.db import transaction
from django.db.models import Q
from django.forms import model_to_dict
from django.urls import reverse
from django.utils import timezone
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -375,6 +375,9 @@ def add_error(self, error, model, details=None):
traceback="".join(traceback.format_tb(error.__traceback__)),
)

def get_absolute_url(self):
return reverse("project_detail", args=[self.uuid])

@cached_property
def resource_count(self):
return self.codebaseresources.count()
Expand Down
32 changes: 32 additions & 0 deletions scanpipe/templates/scanpipe/includes/add_pipeline_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div id="add-pipeline-modal" class="modal is-desktop-size">
<div class="modal-background"></div>
<form method="post">{% csrf_token %}
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Add pipeline</p>
<button class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body">
<div class="field">
<label class="label" for="id_pipeline">Pipeline</label>
<div class="control">
<span class="select">
{{ add_pipeline_form.pipeline }}
</span>
</div>
</div>

<div class="field">
<label class="checkbox" for="id_run_pipeline">
{{ add_pipeline_form.run_pipeline }}
Run the selected pipeline
</label>
</div>
</section>
<footer class="modal-card-foot">
<button class="button is-link" type="submit">Add pipeline</button>
<button class="button" type="reset">Close</button>
</footer>
</div>
</form>
</div>
2 changes: 1 addition & 1 deletion scanpipe/templates/scanpipe/includes/breadcrumb.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<li class="is-active"><a href="#" aria-current="page">Projects</a></li>
{% elif current %}
<li><a href="{% url 'project_list' %}">Projects</a></li>
<li><a href="{% url 'project_detail' project.uuid %}">{{ project.name }}</a></li>
<li><a href="{{ project.get_absolute_url }}">{{ project.name }}</a></li>
<li class="is-active"><a href="#" aria-current="page">{{ current }}</a></li>
{% else %}
<li><a href="{% url 'project_list' %}">Projects</a></li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
{% for project in projects %}
<tr>
<th>
<a href="{% url 'project_detail' project.uuid %}">{{ project }}</a>
<a href="{{ project.get_absolute_url }}">{{ project }}</a>
</th>
<td>
{% if project.package_count %}
Expand Down
6 changes: 6 additions & 0 deletions scanpipe/templates/scanpipe/includes/run_modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
{% include "scanpipe/includes/run_status_tag.html" with run=run only %}
</div>
</div>
{% if not run.task_start_date %}
<a href="{% url 'project_run_pipeline' project.uuid run.uuid %}" class="has-text-weight-bold">
<i class="fas fa-play-circle"></i>
Run Pipeline
</a>
{% endif %}
{% if run.task_exitcode %}
<div class="control">
<div class="tags has-addons">
Expand Down
6 changes: 4 additions & 2 deletions scanpipe/templates/scanpipe/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
{% block content %}
<div class="container is-max-desktop">
{% include 'scanpipe/includes/navbar_header.html' %}
<div class="mx-5 mb-2">{% include 'scanpipe/includes/messages.html' %}</div>

<section class="mx-5 mb-3">
{% include 'scanpipe/includes/breadcrumb.html' %}
Expand Down Expand Up @@ -100,12 +101,13 @@
{% include "scanpipe/includes/run_status_tag.html" with run=run only %}
<span class="ml-2">{{ run.pipeline_basename }}</span>
</a>
{% include "scanpipe/includes/run_modal.html" with run=run only %}
{% include "scanpipe/includes/run_modal.html" with project=project run=run only %}
{% endfor %}
<div class="panel-block">
<button class="button is-link is-outlined is-fullwidth" disabled>
<button class="button is-link is-outlined is-fullwidth modal-button" data-target="add-pipeline-modal" aria-haspopup="true">
Add pipeline
</button>
{% include "scanpipe/includes/add_pipeline_modal.html" %}
</div>
</nav>
</div>
Expand Down
5 changes: 5 additions & 0 deletions scanpipe/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
views.ProjectResultsView.as_view(),
name="project_results",
),
path(
"project/<uuid:uuid>/run_pipeline/<uuid:run_uuid>/",
views.run_pipeline_view,
name="project_run_pipeline",
),
path(
"project/add/",
views.ProjectCreateView.as_view(),
Expand Down
29 changes: 29 additions & 0 deletions scanpipe/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
from django.http import FileResponse
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.views import generic

from django_filters.views import FilterView

from scanpipe import pipelines
from scanpipe.api.serializers import scanpipe_app_config
from scanpipe.forms import AddPipelineForm
from scanpipe.forms import PackageFilterSet
from scanpipe.forms import ProjectFilterSet
from scanpipe.forms import ProjectForm
Expand All @@ -41,6 +43,7 @@
from scanpipe.models import DiscoveredPackage
from scanpipe.models import Project
from scanpipe.models import ProjectError
from scanpipe.models import Run
from scanpipe.pipes import codebase
from scanpipe.pipes import output

Expand Down Expand Up @@ -168,10 +171,24 @@ def get_context_data(self, **kwargs):
"package_licenses": self.get_summary(package_licenses),
"package_types": self.get_summary(package_types),
"file_filter": file_filter,
"add_pipeline_form": AddPipelineForm(),
}
)
return context

def post(self, request, *args, **kwargs):
project = self.get_object()
form = AddPipelineForm(request.POST)
if form.is_valid():
pipeline = form.data["pipeline"]
run_pipeline = form.data.get("run_pipeline", False)
project.add_pipeline(pipeline, start_run=run_pipeline)
messages.success(request, f"Pipeline {pipeline} added.")
else:
messages.error(request, "Pipeline addition error.")

return redirect(project)


class ProjectDeleteView(ProjectViewMixin, generic.DeleteView):
success_url = reverse_lazy("project_list")
Expand All @@ -196,6 +213,18 @@ def get_context_data(self, **kwargs):
return context


def run_pipeline_view(request, uuid, run_uuid):
project = get_object_or_404(Project, uuid=uuid)
run = get_object_or_404(Run, uuid=run_uuid, project=project)

if run.task_start_date:
raise Http404("Pipeline already started.")

run.run_pipeline_task_async()
messages.success(request, f'Pipeline "{run.pipeline}" run started.')
return redirect(project)


def project_results_json_response(project, as_attachment=False):
"""
Return the results as JSON compatible with ScanCode data format.
Expand Down

0 comments on commit 97ed37d

Please sign in to comment.