From 01ea5143b12decae3daf8067bb2f38047bfe5697 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Michel=20Nirgal=20Vourg=C3=A8re?= Date: Mon, 8 Nov 2010 23:29:39 +0000 Subject: [PATCH] Added archive_date for jobs. Archive jobs after first download. Added options to view archived jobs. Changed user.info & user.error to use html rather that text. Added user feedback message when a job is complete. Miscalaneous improvement to jobs page. --- bin/djais/models.py | 16 ++++++++++++---- bin/djais/urls.py | 1 + bin/djais/views.py | 17 ++++++++++++++++- bin/jobrunner.py | 2 +- html_templates/base.html | 2 +- html_templates/jobs.html | 23 ++++++++++++++--------- html_templates/vessel.html | 2 +- structure.sql | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 80 insertions(+), 17 deletions(-) diff --git a/bin/djais/models.py b/bin/djais/models.py index ac4d461..40eff37 100644 --- a/bin/djais/models.py +++ b/bin/djais/models.py @@ -5,6 +5,7 @@ from datetime import datetime from random import SystemRandom from django.db import models from django.contrib.auth.models import get_hexdigest +from django.utils import html from ais.common import Nmea, mmsi_to_strmmsi, nice_timedelta_str @@ -44,7 +45,7 @@ class User(models.Model): salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5] hsh = get_hexdigest(algo, salt, raw_password) self.password_hash = '%s$%s$%s' % (algo, salt, hsh) - self.info('Password changed') + self.info('Password changed') # FIXME def check_password(self, raw_password): algo, salt, hsh = self.password_hash.split('$') @@ -76,10 +77,10 @@ class User(models.Model): return messages_dict def info(self, message): - UserMessage(user_id = self.id, category_id=u'info', txt=message).save() + UserMessage(user_id = self.id, category_id=u'info', txt=html.escape(message)).save() def error(self, message): - UserMessage(user_id = self.id, category_id=u'error', txt=message).save() + UserMessage(user_id = self.id, category_id=u'error', txt=html.escape(message)).save() def check_sandbox_access(self, source_user=None): SANDBOX_FLEET = 1 @@ -215,9 +216,16 @@ class Job(models.Model): extension = models.CharField(max_length=8) pid = models.IntegerField(blank=True, null=True) result = models.IntegerField(blank=True, null=True) + archive_time = models.DateTimeField(blank=True, null=True) + + def nice_command(self): + if self.command.startswith('python -m'): + return self.command[len('python -m '):] + else: + return self.command def queue_rank(self): - return Job.objects.filter(queue_time__lt=self.queue_time).filter(start_time__isnull=True).count() + return Job.objects.filter(queue_time__lt=self.queue_time).filter(start_time__isnull=True).count() + 1 def process_time(self): dt = self.finish_time - self.start_time return nice_timedelta_str(dt) diff --git a/bin/djais/urls.py b/bin/djais/urls.py index 92cf239..3f1d1aa 100644 --- a/bin/djais/urls.py +++ b/bin/djais/urls.py @@ -30,6 +30,7 @@ urlpatterns = patterns('', (r'^user/(?P[a-zA-Z0-9_]+)/change_password$', 'ais.djais.views.user_change_password'), (r'^user/(?P[a-zA-Z0-9_]+)/delete$', 'ais.djais.views.user_delete'), (r'^job/$', 'ais.djais.views.jobs_index'), + (r'^job/(?P[A-Z0-9]+)$', 'ais.djais.views.job_get'), (r'^source/$', 'ais.djais.views.sources_index'), (r'^source/stats$', 'ais.djais.views.sources_stats'), (r'^news/(?P\d*)$', 'ais.djais.views.news'), diff --git a/bin/djais/views.py b/bin/djais/views.py index 789de7b..20b4a7d 100644 --- a/bin/djais/views.py +++ b/bin/djais/views.py @@ -660,7 +660,22 @@ def fleet_lastpos(request, fleetname): @http_authenticate(auth, 'ais') def jobs_index(request): - return render_to_response('jobs.html', {}, RequestContext(request)) + show_archive = request.REQUEST.has_key('archive') + if show_archive: + jobs = request.user.job_set.all() + else: + jobs = request.user.job_set.filter(archive_time__isnull=True) + return render_to_response('jobs.html', {'jobs': jobs, 'archive': show_archive }, RequestContext(request)) + +@http_authenticate(auth, 'ais') +def job_get(request, jobid): + job = get_object_or_404(Job, id=jobid) + if job.user != request.user: + return HttpResponseForbidden('403 Forbidden') + if not job.archive_time: + job.archive_time = datetime.utcnow() + job.save() + return HttpResponseRedirect('/job_result/%s.%s' % (job.id, job.extension)) @http_authenticate(auth, 'ais') def users(request): diff --git a/bin/jobrunner.py b/bin/jobrunner.py index 108a0da..0d0b13b 100755 --- a/bin/jobrunner.py +++ b/bin/jobrunner.py @@ -54,7 +54,7 @@ def main(): dbcommit() logging.info('Job complete: result=%s', returncode) - sqlexec(u"INSERT INTO user_message (user_id, user_message_category_id, txt) VALUES(%(user_id)s, 'info', %(msg)s)", {'user_id':user_id, 'msg':'Your job %s is complete.' % jobid}) + sqlexec(u"INSERT INTO user_message (user_id, user_message_category_id, txt) VALUES(%(user_id)s, 'info', %(msg)s)", {'user_id':user_id, 'msg':('Your job %(jobid)s is complete.' % {'jobid': jobid}) }) dbcommit() if __name__ == '__main__': diff --git a/html_templates/base.html b/html_templates/base.html index caa6ee3..0141594 100644 --- a/html_templates/base.html +++ b/html_templates/base.html @@ -32,7 +32,7 @@
{% for message in user.get_messages %}
- {{ message.category.id }}: {{ message.txt }} + {{ message.category.id }}: {{ message.txt|safe }}
{% endfor %} {% block content %}{% endblock %} diff --git a/html_templates/jobs.html b/html_templates/jobs.html index ab031f0..8583541 100644 --- a/html_templates/jobs.html +++ b/html_templates/jobs.html @@ -9,28 +9,33 @@ {% block content %} -{% if not user.job_set.all %} -You don't have any job. +{% if not jobs %} +

No results. {% endif %}

    -{% for job in user.job_set.all %} +{% for job in jobs %}
  • Job {{ job.id }}
    -Command:
    -{{ job.command }}
    +{{ job.nice_command }}
    {% if job.finish_time %} -Status: Complete in {{ job.process_time }}
    -Result: {% if job.result %}Error {{ job.result }}{% else %}Success
    download{% endif %}
    +Status: Completed at {{ job.finish_time|date:"Y-m-d H:i:s" }} UTC in {{ job.process_time }}
    +Result: {% if job.result %}Error {{ job.result }}{% else %}Success
    +download{% endif %}
    {% else %} {% if job.start_time %} - Status:Running since {{ job.start_time }}
    + Status:Running since {{ job.start_time }}.
    Pid: {{ job.pid }}
    {% else %} - Status: Queued since {{ job.queue_time }}
    + Status: Queued since {{ job.queue_time }}.
    Position in jobs queue: {{ job.queue_rank }}
    {% endif %} {% endif %} {% endfor %}
+{% if archive %} +Hide archived jobs +{% else %} +Show archived jobs +{% endif %} {% endblock %} diff --git a/html_templates/vessel.html b/html_templates/vessel.html index df76d77..6ec6454 100644 --- a/html_templates/vessel.html +++ b/html_templates/vessel.html @@ -58,7 +58,7 @@ One position every
-Queue request (experimental/work in progress...) +Queue request (experimental)
diff --git a/structure.sql b/structure.sql index c517e68..8801105 100644 --- a/structure.sql +++ b/structure.sql @@ -102,6 +102,24 @@ CREATE SEQUENCE fleet_vessel_id_seq ALTER SEQUENCE fleet_vessel_id_seq OWNED BY fleet_vessel.id; +-- +-- Name: job; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE job ( + id character(8) NOT NULL, + user_id integer, + queue_time timestamp without time zone DEFAULT now() NOT NULL, + start_time timestamp without time zone, + finish_time timestamp without time zone, + command text NOT NULL, + extension character varying(8) NOT NULL, + pid integer, + result integer, + archive_time timestamp without time zone +); + + -- -- Name: mi_mmsi_i_seq; Type: SEQUENCE; Schema: public; Owner: - -- @@ -391,6 +409,14 @@ ALTER TABLE ONLY fleet_vessel ADD CONSTRAINT fleet_vessel_pkey2 UNIQUE (mmsi, fleet_id); +-- +-- Name: job_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY job + ADD CONSTRAINT job_pkey PRIMARY KEY (id); + + -- -- Name: mi_source_name_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -510,6 +536,14 @@ ALTER TABLE ONLY fleet_vessel ADD CONSTRAINT fleet_vessel_mmsi_fkey FOREIGN KEY (mmsi) REFERENCES vessel(mmsi) ON UPDATE CASCADE ON DELETE CASCADE; +-- +-- Name: job_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY job + ADD CONSTRAINT job_user_id_fkey FOREIGN KEY (user_id) REFERENCES "user"(id) ON UPDATE CASCADE ON DELETE SET NULL; + + -- -- Name: user_father_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- -- 2.30.2