This commit is contained in:
Eelco Dolstra 2008-11-13 14:54:50 +00:00
parent 46dc10847a
commit f6f5309a02
8 changed files with 185 additions and 19 deletions

View file

@ -49,13 +49,51 @@ sub index :Path :Args(0) {
} }
sub updateProject {
my ($c, $project) = @_;
my $projectName = $c->request->params->{name};
die "Invalid project name: $projectName" unless $projectName =~ /^[[:alpha:]]\w*$/;
my $displayName = $c->request->params->{displayname};
die "Invalid display name: $displayName" unless $displayName =~ /^\w.*\w$/;
$project->name($projectName);
$project->displayname($displayName);
$project->description($c->request->params->{description});
$project->update;
}
sub project :Local { sub project :Local {
my ( $self, $c, $projectName ) = @_; my ( $self, $c, $projectName, $subcommand ) = @_;
$c->stash->{template} = 'project.tt'; $c->stash->{template} = 'project.tt';
(my $project) = $c->model('DB::Projects')->search({ name => $projectName }); (my $project) = $c->model('DB::Projects')->search({ name => $projectName });
return error($c, "Project <tt>$projectName</tt> doesn't exist.") if !defined $project; return error($c, "Project <tt>$projectName</tt> doesn't exist.") if !defined $project;
my $isPosted = $c->request->method eq "POST";
$subcommand = "" unless defined $subcommand;
if ($subcommand eq "edit") {
$c->stash->{edit} = 1;
} elsif ($subcommand eq "submit" && $isPosted) {
$c->model('DB')->schema->txn_do(sub {
updateProject($c, $project);
});
return $c->res->redirect($c->uri_for("/project", $projectName));
} elsif ($subcommand eq "delete" && $isPosted) {
$c->model('DB')->schema->txn_do(sub {
$project->delete;
});
return $c->res->redirect($c->uri_for("/"));
} elsif ($subcommand eq "") {
} else {
return error($c, "Unknown subcommand $subcommand.");
}
$c->stash->{curProject} = $project; $c->stash->{curProject} = $project;
$c->stash->{finishedBuilds} = $c->model('DB::Builds')->search( $c->stash->{finishedBuilds} = $c->model('DB::Builds')->search(
@ -83,13 +121,43 @@ sub project :Local {
} }
sub createproject :Local {
my ( $self, $c, $subcommand ) = @_;
if (defined $subcommand && $subcommand eq "submit") {
eval {
my $projectName = $c->request->params->{name};
$c->model('DB')->schema->txn_do(sub {
# Note: $projectName is validated in updateProject,
# which will abort the transaction if the name isn't
# valid.
my $project = $c->model('DB::Projects')->create({name => $projectName, displayname => ""});
updateProject($c, $project);
});
return $c->res->redirect($c->uri_for("/project", $projectName));
};
if ($@) {
return error($c, $@);
}
}
$c->stash->{template} = 'project.tt';
$c->stash->{create} = 1;
$c->stash->{edit} = 1;
}
sub job :Local { sub job :Local {
my ( $self, $c, $project, $jobName ) = @_; my ( $self, $c, $projectName, $jobName ) = @_;
$c->stash->{template} = 'job.tt'; $c->stash->{template} = 'job.tt';
$c->stash->{projectName} = $project;
(my $project) = $c->model('DB::Projects')->search({ name => $projectName });
return error($c, "Project <tt>$projectName</tt> doesn't exist.") if !defined $project;
$c->stash->{curProject} = $project;
$c->stash->{jobName} = $jobName; $c->stash->{jobName} = $jobName;
$c->stash->{builds} = [$c->model('DB::Builds')->search( $c->stash->{builds} = [$c->model('DB::Builds')->search(
{finished => 1, project => $project, attrName => $jobName}, {finished => 1, project => $projectName, attrName => $jobName},
{order_by => "timestamp DESC"})]; {order_by => "timestamp DESC"})];
} }

View file

@ -1,7 +1,8 @@
[% WRAPPER layout.tt title="Hydra Overview" %] [% WRAPPER layout.tt title="Hydra Overview" %]
[% USE HTML %]
<h1>Error</h1> <h1>Error</h1>
<p>I'm very sorry, but an error occurred: <span class="error-msg">[% error %]</span></p> <p>I'm very sorry, but an error occurred: <span class="error-msg">[% HTML.escape(error) %]</span></p>
[% END %] [% END %]

View file

@ -38,6 +38,10 @@ td, th {
border: solid black 1px; border: solid black 1px;
} }
td {
vertical-align: top;
}
th { th {
background: #ffffc0; background: #ffffc0;
} }
@ -145,6 +149,7 @@ td.buildfarmMainColumn {
.error-msg { .error-msg {
color: red; color: red;
white-space: pre;
} }
pre.buildlog { pre.buildlog {
@ -321,3 +326,13 @@ h1 {
#footer { #footer {
font-size: 80%; font-size: 80%;
} }
/* Editing */
input.string {
font-family: sans-serif;
font-size: 100%;
background-color: #fffff0;
width: 30em;
}

View file

@ -1,6 +1,6 @@
[% WRAPPER layout.tt title="Hydra Overview" %] [% WRAPPER layout.tt title="Hydra Overview" %]
<h1>All builds for job <tt>[% projectName %]:[% jobName %]</tt></h1> <h1>All builds for job <tt>[% curProject.name %]:[% jobName %]</tt></h1>
<table class="tablesorter"> <table class="tablesorter">
<thead> <thead>

View file

@ -50,6 +50,7 @@
<div class="title"><a href="[% c.uri_for('/project' project.name) %]">[% project.displayname %]</a></div> <div class="title"><a href="[% c.uri_for('/project' project.name) %]">[% project.displayname %]</a></div>
[% IF curProject.name == project.name %] [% IF curProject.name == project.name %]
<ul class="subsubmenu"> <ul class="subsubmenu">
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'status') title = "Status" %] [% INCLUDE makeLink uri = c.uri_for('/project' project.name 'status') title = "Status" %]
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'all') title = "All builds" %] [% INCLUDE makeLink uri = c.uri_for('/project' project.name 'all') title = "All builds" %]
</ul> </ul>
@ -63,7 +64,7 @@
<div class="title">Admin</div> <div class="title">Admin</div>
<ul class="submenu"> <ul class="submenu">
[% INCLUDE makeLink uri = c.uri_for('/users') title = "Users" %] [% INCLUDE makeLink uri = c.uri_for('/users') title = "Users" %]
[% INCLUDE makeLink uri = c.uri_for('/create-project') title = "Create a project" %] [% INCLUDE makeLink uri = c.uri_for('/createproject') title = "Create a project" %]
</ul> </ul>
</li> </li>
</ul> </ul>

View file

@ -1,9 +1,46 @@
[% WRAPPER layout.tt title="Hydra Overview" %] [% WRAPPER layout.tt title="Hydra Overview" %]
[% USE HTML %]
<h1>Project <tt>[% curProject.name %]</tt></h1>
<p><strong>Description:</strong> [% curProject.description %]</p> [% BLOCK maybeEditString %]
[% IF edit %]
<input type='text' class='string' [% HTML.attributes(name => param, value => value) %] />
[% ELSE %]
[% HTML.escape(value) %]
[% END %]
[% END %]
[% IF edit %]
<form action="[% IF create %][% c.uri_for('/createproject/submit') %][% ELSE %][% c.uri_for('/project' curProject.name 'submit') %][% END %]" method="post">
[% END %]
[% IF create %]
<h1>New Project</h1>
[% ELSE %]
<h1>Project <tt>[% curProject.name %]</tt></h1>
[% END %]
<h2>General information</h2>
<table>
[% IF edit %]
<tr>
<th>Identifier:</th>
<td><tt>[% INCLUDE maybeEditString param="name" value=curProject.name %]</tt></td>
</tr>
[% END %]
<tr>
<th>Display name:</th>
<td>[% INCLUDE maybeEditString param="displayname" value=curProject.displayname %]</td>
</tr>
<tr>
<th>Description:</th>
<td>[% INCLUDE maybeEditString param="description" value=curProject.description %]</td>
</tr>
</table>
<h2>Definition</h2> <h2>Definition</h2>
@ -17,13 +54,19 @@
<h4>Information</h4> <h4>Information</h4>
<table> <table>
[% IF edit %]
<tr>
<th>Identifier:</th>
<td><tt>[% INCLUDE maybeEditString value=jobset.name %]</tt></td>
</tr>
[% END %]
<tr> <tr>
<th>Description:</th> <th>Description:</th>
<td>[% jobset.description %]</td> <td>[% INCLUDE maybeEditString value=jobset.description %]</td>
</tr> </tr>
<tr> <tr>
<th>Nix expression:</th> <th>Nix expression:</th>
<td><tt>[% jobset.nixexprpath %]</tt> in input <tt>[% jobset.nixexprinput %]</tt></td> <td><tt>[% INCLUDE maybeEditString value=jobset.nixexprpath %]</tt> in input <tt>[% INCLUDE maybeEditString value=jobset.nixexprinput %]</tt></td>
</tr> </tr>
</table> </table>
@ -36,14 +79,33 @@
<tbody> <tbody>
[% FOREACH input IN jobset.jobsetinputs -%] [% FOREACH input IN jobset.jobsetinputs -%]
<tr> <tr>
<td><tt>[% input.name %]</tt></td> <td><tt>[% INCLUDE maybeEditString value=input.name %]</tt></td>
<td><tt>[% input.type %]</tt></td> <td><tt>
[% IF edit %]
<select>
<option>svn</option>
<option>cvs</option>
<option>uri</option>
<option>string</option>
<option>path</option>
</select>
[% ELSE %]
[% input.type %]
[% END %]
</tt></td>
<td> <td>
[% FOREACH alt IN input.jobsetinputalts -%] [% FOREACH alt IN input.jobsetinputalts -%]
[% IF input.type == "string" %] [% IF input.type == "string" %]
<tt>"[% alt.value %]"</tt> <tt>
[% IF edit %]
<input type='text' class='string' value='[% alt.value %]' />
<br />
[% ELSE %] [% ELSE %]
<tt>[% alt.uri %]</tt> "[% alt.value %]"
[% END %]
</tt>
[% ELSE %]
<tt>[% INCLUDE maybeEditString value=alt.uri %]</tt>
[% END %] [% END %]
[% END %] [% END %]
</td> </td>
@ -61,6 +123,9 @@
[% END %] [% END %]
[% IF !edit %]
<h2>Jobs</h2> <h2>Jobs</h2>
[% IF jobNames.size > 0 %] [% IF jobNames.size > 0 %]
@ -108,4 +173,20 @@
</table> </table>
[% END %]
[% IF edit %]
<p><input type="submit" value="Apply" /></p>
</form>
<form action="[% c.uri_for('/project' curProject.name 'delete') %]" method="post">
<p><input type="submit" value="Delete this project" /></p>
</form>
[% END %]
[% END %] [% END %]

View file

@ -174,7 +174,7 @@ create table JobsetInputs (
project text not null, project text not null,
jobset text not null, jobset text not null,
name text not null, name text not null,
type text not null, -- "svn", "cvs", "path", "file", "string" type text not null, -- "svn", "cvs", "path", "uri", "string"
primary key (project, jobset, name), primary key (project, jobset, name),
foreign key (project, jobset) references Jobsets(project, name) on delete cascade -- ignored by sqlite foreign key (project, jobset) references Jobsets(project, name) on delete cascade -- ignored by sqlite
); );

View file

@ -1,5 +1,5 @@
insert into projects(name, displayName, description) values('patchelf', 'PatchELF', 'A tool for modifying ELF binaries'); insert into projects(name, displayName, description) values('patchelf', 'PatchELF', 'A tool for modifying ELF binaries');
insert into jobSets(project, name, description, nixExprInput, nixExprPath) values('patchelf', 'trunk', 'PatchELF', 'patchelfSrc', 'release.nix'); insert into jobSets(project, name, description, nixExprInput, nixExprPath) values('patchelf', 'trunk', 'PatchELF trunk', 'patchelfSrc', 'release.nix');
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'patchelfSrc', 'path'); insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'patchelfSrc', 'path');
insert into jobSetInputAlts(project, jobset, input, altnr, uri) values('patchelf', 'trunk', 'patchelfSrc', 0, '/home/eelco/Dev/patchelf-wc'); insert into jobSetInputAlts(project, jobset, input, altnr, uri) values('patchelf', 'trunk', 'patchelfSrc', 0, '/home/eelco/Dev/patchelf-wc');
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'nixpkgs', 'path'); insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'nixpkgs', 'path');