Implement detail page for experiments
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
* Copyright (c) 2011 Karsten Heiken, Eike Foken
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,7 @@ class Experiments extends CI_Controller {
|
|||||||
$this->load->model('parameter');
|
$this->load->model('parameter');
|
||||||
$this->load->model('program');
|
$this->load->model('program');
|
||||||
$this->load->model('experiment');
|
$this->load->model('experiment');
|
||||||
|
$this->load->model('job');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,6 +132,64 @@ class Experiments extends CI_Controller {
|
|||||||
|
|
||||||
$this->load->view('experiments/new', $data);
|
$this->load->view('experiments/new', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies an experiment.
|
||||||
|
*
|
||||||
|
* @param string $experimentId
|
||||||
|
*/
|
||||||
|
public function copy($experimentId = '') {
|
||||||
|
$experiment = $this->experiment->getByID($experimentId);
|
||||||
|
if (isset($experiment['project_id'])) {
|
||||||
|
redirect('experiments/create/' . $experiment['project_id'] . '/' . $experimentId);
|
||||||
|
} else {
|
||||||
|
show_404();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows detailed informations about a specific experiment.
|
||||||
|
*
|
||||||
|
* @param string $experimentId
|
||||||
|
*/
|
||||||
|
public function detail($experimentId = '') {
|
||||||
|
$experiment = $this->experiment->getByID($experimentId);
|
||||||
|
if (empty($experimentId) || !isset($experiment['id'])){
|
||||||
|
show_404();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->load->helper('typography');
|
||||||
|
|
||||||
|
$data['experiment'] = $experiment;
|
||||||
|
$data['job'] = $this->job->getByExperimentId($experiment['id']);
|
||||||
|
$data['project'] = $this->project->getById($experiment['project_id']);
|
||||||
|
|
||||||
|
$this->load->view('experiments/detail', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows users to delete an experiment.
|
||||||
|
*
|
||||||
|
* @param string $experimentId
|
||||||
|
*/
|
||||||
|
public function delete($experimentId = '') {
|
||||||
|
// TODO: Check user rights
|
||||||
|
|
||||||
|
$experiment = $this->experiment->getByID($experimentId);
|
||||||
|
if (empty($experimentId) || !isset($experiment['id'])){
|
||||||
|
show_404();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->load->helper('file');
|
||||||
|
|
||||||
|
$experimentPath = FCPATH . 'uploads/' . $experiment['project_id'] . '/' . $experiment['id'] . '/';
|
||||||
|
if (delete_files($experimentPath, true)) {
|
||||||
|
rmdir($experimentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->experiment->delete($experimentId);
|
||||||
|
redirect('projects/detail/' . $experiment['project_id'], 303);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of file experiments.php */
|
/* End of file experiments.php */
|
||||||
|
|||||||
@@ -112,5 +112,37 @@ if ( ! function_exists('prettyTime'))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses any english textual datetime description into a relative date string.
|
||||||
|
*
|
||||||
|
* @author Eike Foken <kontakt@eikefoken.de>
|
||||||
|
* @param string $date
|
||||||
|
* @param boolean $show_seconds
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
if (!function_exists('relative_time')) {
|
||||||
|
function relative_time($date, $show_seconds = false) {
|
||||||
|
$diff = time() - strtotime($date);
|
||||||
|
|
||||||
|
if ($diff < 120 && !$show_seconds) {
|
||||||
|
$output = _('just now');
|
||||||
|
} else if ($diff < 60 && $show_seconds) {
|
||||||
|
$output = sprintf(ngettext('%d second ago', '%d seconds ago', $diff), $diff);
|
||||||
|
} else if (($diff = round($diff / 60)) < 60) {
|
||||||
|
$output = sprintf(ngettext('%d minute ago', '%d minutes ago', $diff), $diff);
|
||||||
|
} else if (($diff = round($diff / 60)) < 24) {
|
||||||
|
$output = sprintf(ngettext('%d hour ago', '%d hours ago', $diff), $diff);
|
||||||
|
} else if (($diff = round($diff / 24)) < 7) {
|
||||||
|
$output = sprintf(ngettext('%d day ago', '%d days ago', $diff), $diff);
|
||||||
|
} else if (($diff = round($diff / 7)) < 4) {
|
||||||
|
$output = sprintf(ngettext('%d week ago', '%d weeks ago', $diff), $diff);
|
||||||
|
} else {
|
||||||
|
$output = _('on') . ' ' . strftime('%B %Y', strtotime($date));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* End of file MY_date_helper.php */
|
/* End of file MY_date_helper.php */
|
||||||
/* Location: ./application/helpers/MY_date_helper.php */
|
/* Location: ./application/helpers/MY_date_helper.php */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
* Copyright (c) 2011 Karsten Heiken, Eike Foken
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -25,14 +25,15 @@
|
|||||||
* Experiments are used to store different variations of the same project.
|
* Experiments are used to store different variations of the same project.
|
||||||
*
|
*
|
||||||
* @author Karsten Heiken <karsten@disposed.de>
|
* @author Karsten Heiken <karsten@disposed.de>
|
||||||
|
* @author Eike Foken <kontakt@eikefoken.de>
|
||||||
*/
|
*/
|
||||||
class Experiment extends CI_Model {
|
class Experiment extends CI_Model {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new experiment.
|
* Creates a new experiment.
|
||||||
*
|
*
|
||||||
* @param array $data The data of the new experiment
|
* @param array $data The data of the new experiment
|
||||||
* @return boolean Was the insert successful?
|
* @return boolean Returns TRUE if the insert was successful.
|
||||||
*/
|
*/
|
||||||
public function create($data) {
|
public function create($data) {
|
||||||
if (!isset($data['project_id'])) {
|
if (!isset($data['project_id'])) {
|
||||||
@@ -51,13 +52,26 @@ class Experiment extends CI_Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a experiment.
|
* Updates an experiment.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @param string $experimentId
|
||||||
|
* @return boolean Returns TRUE if the update was successful.
|
||||||
|
*/
|
||||||
|
public function update($data, $experimentId) {
|
||||||
|
$this->db->update('experiments', $data, array('id' => $experimentId));
|
||||||
|
return $this->db->affected_rows() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an experiment.
|
||||||
*
|
*
|
||||||
* @param string $experimentId The experiments ID to delete
|
* @param string $experimentId The experiments ID to delete
|
||||||
* @return boolean Was the deletion successful?
|
* @return boolean Returns TRUE if the deletion was successful.
|
||||||
*/
|
*/
|
||||||
public function delete($experimentId) {
|
public function delete($experimentId) {
|
||||||
return $this->db->delete('experiments', array('id' => $experimentId));
|
$this->db->delete('experiments', array('id' => $experimentId));
|
||||||
|
return $this->db->affected_rows() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,14 +113,15 @@ class Experiment extends CI_Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an experiment by ID.
|
* Gets an experiment by ID (kept for backwards compatibility).
|
||||||
*
|
*
|
||||||
|
* @deprecated 14-09-2011
|
||||||
|
* @see Experiment::getById()
|
||||||
* @param string $experimentId The experiment to get
|
* @param string $experimentId The experiment to get
|
||||||
* @return array The experiment
|
* @return array The experiment
|
||||||
*/
|
*/
|
||||||
public function get($experimentId) {
|
public function get($experimentId) {
|
||||||
$query = $this->db->get_where('experiments', array('id' => $experimentId));
|
return $this->getById($experimentId);
|
||||||
return $query->row_array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,3 +158,6 @@ class Experiment extends CI_Model {
|
|||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* End of file group.php */
|
||||||
|
/* Location: ./application/controllers/group.php */
|
||||||
|
|||||||
@@ -66,6 +66,22 @@ class Job extends CI_Model {
|
|||||||
return $this->db->where('id', $job_id)->update('jobs', $data);
|
return $this->db->where('id', $job_id)->update('jobs', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a specific job.
|
||||||
|
*
|
||||||
|
* @param string $experimentId
|
||||||
|
* @return array The job data
|
||||||
|
*/
|
||||||
|
public function getByExperimentId($experimentId) {
|
||||||
|
$this->db->select('jobs.*, users.username, users.firstname, users.lastname');
|
||||||
|
$this->db->join('users', 'jobs.started_by = users.id', 'left');
|
||||||
|
$this->db->where('experiment_id', $experimentId);
|
||||||
|
|
||||||
|
$query = $this->db->get('jobs');
|
||||||
|
|
||||||
|
return $query->row_array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of recent jobs.
|
* Gets a list of recent jobs.
|
||||||
*
|
*
|
||||||
|
|||||||
70
application/views/experiments/detail.php
Normal file
70
application/views/experiments/detail.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php $this->load->view('header');?>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<div class="title">
|
||||||
|
<h2><?=anchor('projects', _('Projects'));?> » <?=anchor('projects/detail/' . $project['id'], $project['name']);?> » <?=$experiment['name'];?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h3><?=_('Description');?></h3>
|
||||||
|
<div class="editInPlace"><?=auto_typography($experiment['description']);?></div>
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<h3>Actions</h3>
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
if (isset($job['id'])):
|
||||||
|
?>
|
||||||
|
<a class="button disabled job_start"><?=_('Start job');?></a>
|
||||||
|
<?php
|
||||||
|
else:
|
||||||
|
?>
|
||||||
|
<a href="<?=site_url('jobs/start/' . $experiment['id']);?>" class="button job_start"><?=_('Start job');?></a>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
<a href="<?=site_url('experiments/copy/' . $experiment['id']);?>" class="button left copy"><?=_('Copy experiment');?>
|
||||||
|
</a><a href="javascript:deleteConfirm('<?=site_url('experiments/delete/' . $experiment['id']);?>');" class="button right delete"><?=_('Delete experiment');?></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if (isset($job['id'])):
|
||||||
|
?>
|
||||||
|
<div class="box">
|
||||||
|
<h3><?=_('Job details');?></h3>
|
||||||
|
<p>
|
||||||
|
<strong><?=_('Date started');?>:</strong> <?=relative_time($job['started_at']);?><br />
|
||||||
|
<strong><?=_('Starter');?>:</strong> <?=anchor('users/profile/' . urldecode($job['username']), $job['firstname'] . ' ' . $job['lastname']);?><br />
|
||||||
|
<strong><?=_('Server');?>:</strong> <?=(!empty($job['server'])) ? anchor('admin/servers/detail/' . urldecode($job['server']), $job['server']) : _('Not yet picked');?>
|
||||||
|
|
||||||
|
<div class="progress_bar" style="width: 300px;">
|
||||||
|
<strong><?=$job['progress']?>%</strong>
|
||||||
|
<span style="width: <?=$job['progress']?>%;"> </span>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<?php
|
||||||
|
if ($job['finished_at'] != '0000-00-00 00:00:00'):
|
||||||
|
?>
|
||||||
|
<p><a href="<?=site_url('results/show/' . $experiment['id']);?>" class="button results"><?=_('Show results');?></a></p>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$('.editInPlace').editInPlace({
|
||||||
|
url: BASE_URL + 'ajax/update_experiment/' + '<?=$experiment['id']?>',
|
||||||
|
saving_image: SITE_URL + 'assets/images/ajax-loader.gif',
|
||||||
|
update_value: 'description',
|
||||||
|
value_required: true
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php $this->load->view('footer');?>
|
||||||
@@ -392,6 +392,23 @@ a.button.locked {
|
|||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.button.disabled {
|
||||||
|
color: #6e6e6e;
|
||||||
|
background-color: #fff;
|
||||||
|
/*border: 1px solid rgba(0, 0, 0, 0.05);*/
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.4;
|
||||||
|
filter: alpha(opacity=40);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button.disabled:hover, a.button.disabled:active {
|
||||||
|
color: inherit;
|
||||||
|
border: 1px solid #dcdcdc;
|
||||||
|
-moz-box-shadow: inherit;
|
||||||
|
-webkit-box-shadow: inherit;
|
||||||
|
box-shadow: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
a.button:hover {
|
a.button:hover {
|
||||||
color: #333;
|
color: #333;
|
||||||
border-color: #999;
|
border-color: #999;
|
||||||
@@ -485,6 +502,21 @@ a.cancel {
|
|||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.copy {
|
||||||
|
background: url(../images/icons/document-copy.png) 10px center no-repeat #f3f3f3;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.job_start {
|
||||||
|
background: url(../images/icons/server--arrow.png) 10px center no-repeat #f3f3f3;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.results {
|
||||||
|
background: url(../images/icons/blue-folder-open-document-text.png) 10px center no-repeat #f3f3f3;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
a.up {
|
a.up {
|
||||||
background: url(../images/button-sprite.png) 13px -131px no-repeat #f3f3f3;
|
background: url(../images/button-sprite.png) 13px -131px no-repeat #f3f3f3;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
@@ -595,6 +627,119 @@ html ul.tabs li.active a:hover {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Progress bar */
|
||||||
|
|
||||||
|
div.progress_bar {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
padding: 1px;
|
||||||
|
width: 250px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
background: #fff;
|
||||||
|
-webkit-border-radius: 2px;
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.progress_bar > span {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #5b86ac;
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
from(#5b86ac),
|
||||||
|
to(#6891b7)
|
||||||
|
);
|
||||||
|
background-image: -moz-linear-gradient(
|
||||||
|
center bottom,
|
||||||
|
#5b86ac,
|
||||||
|
#6891b7
|
||||||
|
);
|
||||||
|
background-image: -ms-linear-gradient(
|
||||||
|
center bottom,
|
||||||
|
#5b86ac,
|
||||||
|
#6891b7
|
||||||
|
);
|
||||||
|
background-image: -o-linear-gradient(
|
||||||
|
center bottom,
|
||||||
|
#5b86ac,
|
||||||
|
#6891b7
|
||||||
|
);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.progress_bar > span:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
0 0,
|
||||||
|
100% 100%,
|
||||||
|
color-stop(.25, rgba(255, 255, 255, .08)),
|
||||||
|
color-stop(.25, transparent),
|
||||||
|
color-stop(.5, transparent),
|
||||||
|
color-stop(.5, rgba(255, 255, 255, .08)),
|
||||||
|
color-stop(.75, rgba(255, 255, 255, .08)),
|
||||||
|
color-stop(.75, transparent),
|
||||||
|
to(transparent)
|
||||||
|
);
|
||||||
|
background-image: -moz-linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
rgba(255, 255, 255, .08) 25%,
|
||||||
|
transparent 25%,
|
||||||
|
transparent 50%,
|
||||||
|
rgba(255, 255, 255, .08) 50%,
|
||||||
|
rgba(255, 255, 255, .08) 75%,
|
||||||
|
transparent 75%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
background-image: -ms-linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
rgba(255, 255, 255, .08) 25%,
|
||||||
|
transparent 25%,
|
||||||
|
transparent 50%,
|
||||||
|
rgba(255, 255, 255, .08) 50%,
|
||||||
|
rgba(255, 255, 255, .08) 75%,
|
||||||
|
transparent 75%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
background-image: -o-linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
rgba(255, 255, 255, .08) 25%,
|
||||||
|
transparent 25%,
|
||||||
|
transparent 50%,
|
||||||
|
rgba(255, 255, 255, .08) 50%,
|
||||||
|
rgba(255, 255, 255, .08) 75%,
|
||||||
|
transparent 75%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
z-index: 1;
|
||||||
|
-webkit-background-size: 50px 50px;
|
||||||
|
-moz-background-size: 50px 50px;
|
||||||
|
-webkit-animation: move 2s linear infinite;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.progress_bar strong {
|
||||||
|
color: #111;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
line-height: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* JTip styles */
|
/* JTip styles */
|
||||||
|
|
||||||
.form_info a,
|
.form_info a,
|
||||||
|
|||||||
Reference in New Issue
Block a user