Rename 'trial' to 'experiment'
This commit is contained in:
@@ -1,62 +1,72 @@
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Default group, use name
|
||||
* Default group (use name).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
$config['default_group'] = 'users';
|
||||
|
||||
/**
|
||||
* Default administrators group, use name
|
||||
* Default administrators group (use name).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
$config['admin_group'] = 'admins';
|
||||
|
||||
/**
|
||||
* Minimum required length of passwords.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
$config['min_password_length'] = 8;
|
||||
|
||||
/**
|
||||
* Maximum allowed length of passwords.
|
||||
**/
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
$config['max_password_length'] = 40;
|
||||
|
||||
/**
|
||||
* Allow users to be remembered and enable auto-login.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
$config['remember_users'] = true;
|
||||
|
||||
/**
|
||||
* How long to remember the user.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
$config['user_expire'] = 86500;
|
||||
$config['user_expire'] = 86400;
|
||||
|
||||
/**
|
||||
* Extend the users cookies everytime they auto-login.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
$config['user_extend_on_login'] = false;
|
||||
|
||||
/**
|
||||
* Type of emails to send (HTML or text).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
$config['email_type'] = 'html';
|
||||
|
||||
/**
|
||||
* Folder where e-mail templates are stored.
|
||||
* Folder where email templates are stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
$config['email_templates'] = 'auth/email/';
|
||||
|
||||
/**
|
||||
* Forgot password e-mail template.
|
||||
*/
|
||||
$config['email_forgot_password'] = 'forgot_password.php';
|
||||
|
||||
/**
|
||||
* Forgot password complete e-mail template.
|
||||
*/
|
||||
$config['email_forgot_password_complete'] = 'new_password.php';
|
||||
|
||||
/**
|
||||
* Salt length.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
$config['salt_length'] = 40;
|
||||
|
||||
@@ -64,6 +74,8 @@ $config['salt_length'] = 40;
|
||||
* Should the salt be stored in the database?
|
||||
*
|
||||
* Warning: This will change your password encryption algorithm.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
$config['store_salt'] = true;
|
||||
|
||||
|
||||
@@ -239,10 +239,10 @@ $config['projects/create'] = array(
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
$config['trials/create'] = array(
|
||||
$config['experiments/create'] = array(
|
||||
array(
|
||||
'field' => 'name',
|
||||
'label' => _('Trial name'),
|
||||
'label' => _('Name'),
|
||||
'rules' => 'required|min_length[3]|max_length[60]|trim',
|
||||
),
|
||||
array(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -33,12 +32,12 @@ class Dashboard extends CI_Controller {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->load->model('job');
|
||||
$this->load->model('project');
|
||||
$this->load->model('user');
|
||||
}
|
||||
|
||||
public function index() {
|
||||
$this->session->unset_userdata('active_project');
|
||||
$this->load->view('dashboard');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file dashboard.php */
|
||||
/* Location: ./application/controllers/dashboard.php */
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Trials 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 Eike Foken <kontakts@eikefoken.de>
|
||||
*/
|
||||
class Trials extends CI_Controller {
|
||||
class Experiments extends CI_Controller {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -37,17 +37,16 @@ class Trials extends CI_Controller {
|
||||
$this->load->library('form_validation');
|
||||
$this->load->model('parameter');
|
||||
$this->load->model('program');
|
||||
$this->load->model('project');
|
||||
$this->load->model('trial');
|
||||
$this->load->model('experiment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows users to create new trials.
|
||||
* Allows users to create new experiments.
|
||||
*
|
||||
* @param string $projectId
|
||||
*/
|
||||
public function create($projectId = '', $copyId = '') {
|
||||
// TODO: Handle copying of trials
|
||||
// TODO: Handle copying of experiments
|
||||
|
||||
$project = $this->project->getByID($projectId);
|
||||
|
||||
@@ -64,15 +63,15 @@ class Trials extends CI_Controller {
|
||||
|
||||
if (is_null($project['default_model'])) {
|
||||
$this->load->config('form_validation');
|
||||
foreach ($this->config->item('trials/create') as $rule) { // restore old rules
|
||||
foreach ($this->config->item('experiments/create') as $rule) { // restore old rules
|
||||
$this->form_validation->set_rules($rule['field'], $rule['label'], $rule['rules']);
|
||||
}
|
||||
|
||||
$this->form_validation->set_rules('3dmodel', _('3d model'), 'file_required|file_allowed_type[obj]');
|
||||
$this->form_validation->set_rules('3dmodel', _('3D model'), 'file_required|file_allowed_type[obj]');
|
||||
}
|
||||
|
||||
// run form validation
|
||||
if ($this->form_validation->run('trials/create') === true) {
|
||||
if ($this->form_validation->run('experiments/create') === true) {
|
||||
$data = array(
|
||||
'name' => $this->input->post('name'),
|
||||
'description' => $this->input->post('description'),
|
||||
@@ -81,15 +80,15 @@ class Trials extends CI_Controller {
|
||||
'creator_id' => $this->session->userdata('user_id'),
|
||||
);
|
||||
|
||||
$data['trial_id'] = $this->trial->create($data);
|
||||
$data['experiment_id'] = $this->experiment->create($data);
|
||||
|
||||
if (isset($data['trial_id'])) {
|
||||
if (isset($data['experiment_id'])) {
|
||||
$this->load->helper('directory');
|
||||
$trialPath = FCPATH . 'uploads/' . $projectId . '/' . $data['trial_id'] . '/';
|
||||
mkdirs($trialPath);
|
||||
$experimentPath = FCPATH . 'uploads/' . $projectId . '/' . $data['experiment_id'] . '/';
|
||||
mkdirs($experimentPath);
|
||||
|
||||
$config = array(
|
||||
'upload_path' => $trialPath,
|
||||
'upload_path' => $experimentPath,
|
||||
'allowed_types' => '*',
|
||||
'overwrite' => true,
|
||||
'file_name' => 'default',
|
||||
@@ -109,18 +108,19 @@ class Trials extends CI_Controller {
|
||||
if (preg_match('/^param-[0-9a-z]+/', $key) && !empty($value)) {
|
||||
$param['parameter_id'] = substr($key, 6, 16);
|
||||
$param['value'] = $this->input->post($key);
|
||||
$this->trial->addParameter($param, $data['trial_id']);
|
||||
$this->experiment->addParameter($param, $data['experiment_id']);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't start jobs automatically
|
||||
$program = $this->program->getById($data['program_id']);
|
||||
$this->load->library('program_runner', array('program_driver' => $program['driver']));
|
||||
$this->program_runner->createJob($data['trial_id']);
|
||||
$this->program_runner->createJob($data['experiment_id']);
|
||||
|
||||
//redirect('/experiments/detail/' . $data['experiment_id'], 303);
|
||||
redirect('/projects/detail/' . $projectId, 303);
|
||||
} else {
|
||||
$this->messages->add(_('The trial could not be created.'), 'error');
|
||||
$this->messages->add(_('The experiment could not be created.'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ class Trials extends CI_Controller {
|
||||
$data['programs'] = $programs;
|
||||
$data['project'] = $project;
|
||||
|
||||
$this->load->view('trial/new', $data);
|
||||
$this->load->view('experiments/new', $data);
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file trials.php */
|
||||
/* Location: ./application/controllers/trials.php */
|
||||
/* End of file experiments.php */
|
||||
/* Location: ./application/controllers/experiments.php */
|
||||
@@ -34,8 +34,7 @@ class Projects extends CI_Controller {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->load->library('form_validation');
|
||||
$this->load->model('project');
|
||||
$this->load->model('trial');
|
||||
$this->load->model('experiment');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +122,7 @@ class Projects extends CI_Controller {
|
||||
}
|
||||
|
||||
$data['project'] = $project;
|
||||
$data['trials'] = $this->trial->getByProjectId($id);
|
||||
$data['experiments'] = $this->experiment->getByProjectId($id);
|
||||
$data['jobs'] = $this->job->getRecent($id);
|
||||
|
||||
$this->load->view('projects/detail', $data);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -40,7 +39,6 @@ class Results extends CI_Controller {
|
||||
}
|
||||
|
||||
public function index() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,17 +46,15 @@ class Results extends CI_Controller {
|
||||
*
|
||||
* @param string $prj_id the project for which to get the results
|
||||
*/
|
||||
public function project($prj_id) {
|
||||
|
||||
public function project($projectId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of a given trial.
|
||||
* Get the results of a given experiment.
|
||||
*
|
||||
* @param string $trial_id the trial for which to get the results
|
||||
* @param string $experimentId The experiment for which to get the results
|
||||
*/
|
||||
public function trial($trial_id) {
|
||||
|
||||
public function experiment($experimentId) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +62,9 @@ class Results extends CI_Controller {
|
||||
*
|
||||
* @param string $job_id the job for which to get the results
|
||||
*/
|
||||
public function job($job_id) {
|
||||
|
||||
public function job($jobId) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file results.php */
|
||||
/* Location: ./application/controllers/results.php */
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -79,7 +78,7 @@ class Xmlrpc extends CI_Controller {
|
||||
'success' => array('true', 'string'),
|
||||
'new_job' => array('true', 'string'),
|
||||
'job_id' => array($job->id, 'string'),
|
||||
'trial_id' => array($job->trial_id, 'string'),
|
||||
'experiment_id' => array($job->experiment_id, 'string'),
|
||||
), 'struct');
|
||||
} else {
|
||||
$response = array(array(
|
||||
|
||||
@@ -16,25 +16,25 @@ class Job {
|
||||
|
||||
// load models
|
||||
$this->CI->load->model('program');
|
||||
$this->CI->load->model('trial');
|
||||
$this->CI->load->model('experiment');
|
||||
|
||||
log_message('debug', "Trial Class Initialized");
|
||||
log_message('debug', "Job Class Initialized");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $trialId
|
||||
* @param string $experimentId
|
||||
* @return boolean Returns TRUE on success.
|
||||
*/
|
||||
public function createConfigs($trialId) {
|
||||
$trial = $this->CI->trial->getById($trialId);
|
||||
$path = FCPATH . 'uploads/' . $trial['project_id'] . '/' . $trial['id'] . '/';
|
||||
public function createConfigs($experimentId) {
|
||||
$experiment = $this->CI->experiment->getById($experimentId);
|
||||
$path = FCPATH . 'uploads/' . $experiment['project_id'] . '/' . $experiment['id'] . '/';
|
||||
|
||||
$program = $this->CI->program->getById($trial['program_id']);
|
||||
$program = $this->CI->program->getById($experiment['program_id']);
|
||||
|
||||
$handler = fopen($path . 'trial.conf', "w");
|
||||
$handler = fopen($path . 'default.calc', "w");
|
||||
|
||||
$parameters = $this->CI->trial->getParameters($trialId);
|
||||
$parameters = $this->CI->experiment->getParameters($experimentId);
|
||||
foreach ($parameters as $param) {
|
||||
$line = str_replace("{type}", $param['type'], $program['input_line']);
|
||||
$line = str_replace("{param}", $param['name'], $line);
|
||||
|
||||
@@ -31,14 +31,14 @@ class Program_runner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a job from the specified trial.
|
||||
* Creates a job from the specified experiment.
|
||||
*
|
||||
* @param string $trialId
|
||||
* @param string $experimentId
|
||||
*/
|
||||
public function createJob($trialId) {
|
||||
if ($this->driver->_createJob($trialId)) {
|
||||
public function createJob($experimentId) {
|
||||
if ($this->driver->_createJob($experimentId)) {
|
||||
$this->CI->load->model('job');
|
||||
$this->CI->job->create(array('trial_id' => $trialId, 'started_by' => $this->CI->session->userdata('user_id')));
|
||||
$this->CI->job->create(array('experiment_id' => $experimentId, 'started_by' => $this->CI->session->userdata('user_id')));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,17 @@ class Scatt extends Program_runner {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param unknown_type $trialId
|
||||
* @param unknown_type $experimentId
|
||||
*/
|
||||
public function _createJob($trialId) {
|
||||
public function _createJob($experimentId) {
|
||||
$this->CI->load->library('parser');
|
||||
|
||||
$trial = $this->CI->trial->getById($trialId);
|
||||
$experiment = $this->CI->experiment->getById($experimentId);
|
||||
|
||||
$path = FCPATH . 'uploads/' . $trial['project_id'] . '/' . $trial['id'] . '/';
|
||||
$path = FCPATH . 'uploads/' . $experiment['project_id'] . '/' . $experiment['id'] . '/';
|
||||
$handler = fopen($path . 'default.calc', "w");
|
||||
|
||||
$data['parameters'] = $this->CI->trial->getParameters($trialId);
|
||||
$data['parameters'] = $this->CI->experiment->getParameters($experimentId);
|
||||
|
||||
@fwrite($handler, $this->CI->parser->parse_string($this->program['config_template'], $data, true));
|
||||
@fclose($handler);
|
||||
|
||||
145
application/models/experiment.php
Normal file
145
application/models/experiment.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Experiments are used to store different variations of the same project.
|
||||
*
|
||||
* @author Karsten Heiken <karsten@disposed.de>
|
||||
*/
|
||||
class Experiment extends CI_Model {
|
||||
|
||||
/**
|
||||
* Create a new experiment.
|
||||
*
|
||||
* @param array $data The data of the new experiment
|
||||
* @return boolean Was the insert successful?
|
||||
*/
|
||||
public function create($data) {
|
||||
if (!isset($data['project_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do { // generate unique hash
|
||||
$data['id'] = random_hash();
|
||||
} while ($this->db->where('id', $data['id'])->from('experiments')->count_all_results() > 0);
|
||||
|
||||
if ($this->db->insert('experiments', $data)) {
|
||||
return $data['id'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a experiment.
|
||||
*
|
||||
* @param string $experimentId The experiments ID to delete
|
||||
* @return boolean Was the deletion successful?
|
||||
*/
|
||||
public function delete($experimentId) {
|
||||
return $this->db->delete('experiments', array('id' => $experimentId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter for a specific experiment.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $experimentId
|
||||
* @return boolean Returns TRUE if the parameter was added successfully.
|
||||
*/
|
||||
public function addParameter($data, $experimentId) {
|
||||
if (!isset($data['parameter_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$experiment = $this->get($experimentId);
|
||||
$parameter = $this->db->get_where('parameters', array('id' => $data['parameter_id']))->row_array();
|
||||
|
||||
if (isset($experiment['id']) && $experiment['program_id'] == $parameter['program_id']) {
|
||||
$data['experiment_id'] = $experimentId;
|
||||
$this->db->insert('experiments_parameters', $data);
|
||||
}
|
||||
return $this->db->affected_rows() == 1 ? $experimentId : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parameters for the specified experiment.
|
||||
*
|
||||
* @param string $experimentId
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters($experimentId) {
|
||||
$this->db->select('experiments_parameters.*, parameters.name AS `name`, parameters.type AS `type`');
|
||||
$this->db->join('parameters', 'experiments_parameters.parameter_id = parameters.id', 'left');
|
||||
$this->db->where('experiment_id', $experimentId);
|
||||
|
||||
$query = $this->db->get('experiments_parameters');
|
||||
|
||||
return $query->num_rows() > 0 ? $query->result_array() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an experiment by ID.
|
||||
*
|
||||
* @param string $experimentId The experiment to get
|
||||
* @return array The experiment
|
||||
*/
|
||||
public function get($experimentId) {
|
||||
$query = $this->db->get_where('experiments', array('id' => $experimentId));
|
||||
return $query->row_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an experiment by ID.
|
||||
*
|
||||
* @param string $experimentId The experiment to get
|
||||
* @return array The experiment
|
||||
*/
|
||||
public function getById($experimentId) {
|
||||
return $this->db->get_where('experiments', array('id' => $experimentId))->row_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a experiment by its project ID.
|
||||
*
|
||||
* @param string $projectId
|
||||
* @return array
|
||||
*/
|
||||
public function getByProjectId($projectId) {
|
||||
$query = $this->db->get_where('experiments', array('project_id' => $projectId));
|
||||
return $query->result_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a specific experiment and return a list of possible results.
|
||||
*
|
||||
* @param string $needle The needle to look for in the haystack.
|
||||
*/
|
||||
public function search($project, $needle) {
|
||||
$query = $this->db->where('project_id', $project)
|
||||
->like('name', $needle)->get('experiments');
|
||||
$results = $query->result_array();
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php defined('BASEPATH') || exit("No direct script access allowed");
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Eike Foken <kontakt@eikefoken.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Group model.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -74,8 +73,8 @@ class Job extends CI_Model {
|
||||
* @return array
|
||||
*/
|
||||
public function getRecent($projectId = '') {
|
||||
$this->db->select('jobs.*, trials.project_id, trials.name');
|
||||
$this->db->join('trials', 'jobs.trial_id = trials.id', 'left');
|
||||
$this->db->select('jobs.*, experiments.project_id, experiments.name');
|
||||
$this->db->join('experiments', 'jobs.experiment_id = experiments.id', 'left');
|
||||
//$this->db->where('finished_at', 0);
|
||||
|
||||
if (!empty($projectId)) {
|
||||
@@ -112,3 +111,6 @@ class Job extends CI_Model {
|
||||
return $this->db->count_all_results() > 0 ? $query->row() : FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file job.php */
|
||||
/* Location: ./application/controllers/job.php */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Eike Foken <kontakt@eikefoken.de>
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
/**
|
||||
* Model for parameters.
|
||||
*
|
||||
* Each program has many parameters used for configuration of trials.
|
||||
* Each program has many parameters used for configuration of experiments.
|
||||
*
|
||||
* @author Eike Foken <kontakt@eikefoken.de>
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Programs are used to do the actual calculation of a trial.
|
||||
* Programs are used to do the actual calculation of a experiment.
|
||||
*
|
||||
* @author Karsten Heiken <karsten@disposed.de>
|
||||
* @author Eike Foken <kontakt@eikefoken.de>
|
||||
@@ -135,3 +135,6 @@ class Program extends CI_Model {
|
||||
return $query->result_array();
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file program.php */
|
||||
/* Location: ./application/models/program.php */
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -28,10 +27,10 @@
|
||||
* @author Karsten Heiken <karsten@disposed.de>
|
||||
*/
|
||||
class Project extends CI_Model {
|
||||
|
||||
|
||||
/**
|
||||
* Add a short and medium length description to one project.
|
||||
*
|
||||
*
|
||||
* @param mixed $project
|
||||
*/
|
||||
private function _addShortName($project) {
|
||||
@@ -39,10 +38,10 @@ class Project extends CI_Model {
|
||||
$project['mediumname'] = character_limiter($project['name'], 35);
|
||||
return $project;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a short and medium length description to an array of projects.
|
||||
*
|
||||
*
|
||||
* @param mixed $project
|
||||
*/
|
||||
private function _addShortNames($project) {
|
||||
@@ -205,4 +204,7 @@ class Project extends CI_Model {
|
||||
return $this->db->delete('projects', array('id' => $projectId));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file project.php */
|
||||
/* Location: ./application/models/project.php */
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
@@ -85,11 +84,22 @@ class Server extends CI_Model {
|
||||
get_where('servers', 'workload <= 2')->row_array();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $secret
|
||||
*/
|
||||
public function getBySecret($secret) {
|
||||
return $this->db->get_where('servers', array('secret' => $secret))->row();
|
||||
}
|
||||
|
||||
public function getById($server_id) {
|
||||
return $this->db->get_where('servers', array('id' => $server_id))->row();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $serverId
|
||||
*/
|
||||
public function getById($serverId) {
|
||||
return $this->db->get_where('servers', array('id' => $serverId))->row();
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file server.php */
|
||||
/* Location: ./application/models/server.php */
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 Karsten Heiken <karsten@disposed.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Trials are used to store different variations of the same project.
|
||||
*
|
||||
* @author Karsten Heiken <karsten@disposed.de>
|
||||
*/
|
||||
class Trial extends CI_Model {
|
||||
|
||||
/**
|
||||
* Create a new trial.
|
||||
*
|
||||
* @param array $data the data of the new trial
|
||||
* @return bool was the insert successful
|
||||
*/
|
||||
public function create($data) {
|
||||
if (!isset($data['project_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
do { // generate unique hash
|
||||
$data['id'] = random_hash();
|
||||
} while ($this->db->where('id', $data['id'])->from('trials')->count_all_results() > 0);
|
||||
|
||||
if ($this->db->insert('trials', $data)) {
|
||||
return $data['id'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a trial.
|
||||
* @param string the trial id to delete
|
||||
* @return bool was the deletion successful
|
||||
*/
|
||||
public function delete($trial_id) {
|
||||
return $this->db->delete('trials', array('id' => $trial_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter for a specific trial.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $trialId
|
||||
* @return boolean Returns TRUE if the parameter was added successfully.
|
||||
*/
|
||||
public function addParameter($data, $trialId) {
|
||||
if (!isset($data['parameter_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$trial = $this->get($trialId);
|
||||
$parameter = $this->db->get_where('parameters', array('id' => $data['parameter_id']))->row_array();
|
||||
|
||||
if (isset($trial['id']) && $trial['program_id'] == $parameter['program_id']) {
|
||||
$data['trial_id'] = $trialId;
|
||||
$this->db->insert('trials_parameters', $data);
|
||||
}
|
||||
return $this->db->affected_rows() == 1 ? $trialId : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parameters for the specified trial.
|
||||
*
|
||||
* @param string $trialId
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters($trialId) {
|
||||
$this->db->select('trials_parameters.*, parameters.name AS `name`, parameters.type AS `type`');
|
||||
$this->db->join('parameters', 'trials_parameters.parameter_id = parameters.id', 'left');
|
||||
$this->db->where('trial_id', $trialId);
|
||||
|
||||
$query = $this->db->get('trials_parameters');
|
||||
|
||||
return $query->num_rows() > 0 ? $query->result_array() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a trial by id.
|
||||
*
|
||||
* @param string $trial_id The trial to get.
|
||||
* @return array The trial
|
||||
*/
|
||||
public function get($trial_id) {
|
||||
$query = $this->db->get_where('trials', array('id' => $trial_id));
|
||||
|
||||
return $query->row_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a trial by ID.
|
||||
*
|
||||
* @param string $trialId The trial to get
|
||||
* @return array The trial
|
||||
*/
|
||||
public function getById($trialId) {
|
||||
return $this->db->get_where('trials', array('id' => $trialId))->row_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a trial by its project id.
|
||||
*
|
||||
* @param type $trial_id The trials to get.
|
||||
* @return array The trial
|
||||
*/
|
||||
public function getByProjectId($project_id) {
|
||||
$query = $this->db->get_where('trials', array('project_id' => $project_id));
|
||||
|
||||
return $query->result_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a specific trial and return a list of possible results.
|
||||
*
|
||||
* @param string $needle The needle to look for in the haystack.
|
||||
*/
|
||||
public function search($project, $needle) {
|
||||
$query = $this->db->where('project_id', $project)
|
||||
->like('name', $needle)->get('trials');
|
||||
$results = $query->result_array();
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,25 @@
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/*
|
||||
* Copyright (c) 2011 Eike Foken <kontakt@eikefoken.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* User model.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php $this->load->view('header'); ?>
|
||||
<?php $this->load->view('header');?>
|
||||
|
||||
<div id="content">
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3><?=_('Calculations');?></h3>
|
||||
<h3><?=_('Experiments');?></h3>
|
||||
<p>
|
||||
<a class="button left big" href="#"><?=_('Newest results');?></a><a class="button middle big" href="#"><?=_('Running calculations');?></a>
|
||||
<a class="button left big" href="#"><?=_('Newest results');?></a><a class="button middle big" href="#"><?=_('Running jobs');?></a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
@@ -27,4 +27,4 @@
|
||||
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('footer'); ?>
|
||||
<?php $this->load->view('footer');?>
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<div id="content">
|
||||
|
||||
<div class="title">
|
||||
<h2><?=_('Create a new trial');?></h2>
|
||||
<h2><?=_('Create a new experiment');?></h2>
|
||||
</div>
|
||||
|
||||
<form name="newTrial" method="post" action="<?=site_url('trials/create/' . $project['id']);?>" enctype="multipart/form-data">
|
||||
<form name="newExperiment" method="post" action="<?=site_url('experiments/create/' . $project['id']);?>" enctype="multipart/form-data">
|
||||
<div class="box">
|
||||
|
||||
<h3><?=_('Required information');?></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<?=form_label(_('Trial name'), 'name');?>
|
||||
<?=form_label(_('Name'), 'name');?>
|
||||
<span class="req">*</span>
|
||||
<div>
|
||||
<input type="text" name="name" id="name" class="short text" value="<?=set_value('name');?>" />
|
||||
@@ -22,7 +22,7 @@
|
||||
<li>
|
||||
<?=form_label(_('Description'), 'description');?>
|
||||
<span class="req">*</span><br />
|
||||
<label class="note"><?=_('A description is useful if you want to share this trial with co-workers.');?></label>
|
||||
<label class="note"><?=_('A description is useful if you want to share this experiment with co-workers.');?></label>
|
||||
<div>
|
||||
<textarea name="description" id="description" rows="6" cols="60" class="textarea"><?=set_value('description');?></textarea>
|
||||
<?=form_error('description');?>
|
||||
@@ -35,7 +35,7 @@
|
||||
?>
|
||||
<div class="notice">
|
||||
<strong><?=_('There is a default model set for this project.');?></strong><br />
|
||||
<?=_('If you want to use a different model for this trial, you can upload it here.');?>
|
||||
<?=_('If you want to use a different model for this experiment, you can upload it here.');?>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
@@ -56,7 +56,7 @@
|
||||
?>
|
||||
<div class="notice">
|
||||
<strong><?=_('There is a default configuration set for this project.');?></strong><br />
|
||||
<?=_('This form contains the default values. You can adjust them for this trial.');?><br />
|
||||
<?=_('This form contains the default values. You can adjust them for this experiment.');?><br />
|
||||
<?=_('The default configuration will not be modified.');?>
|
||||
</div>
|
||||
<?php
|
||||
@@ -121,7 +121,7 @@
|
||||
endforeach;
|
||||
?>
|
||||
<p>
|
||||
<a class="button save-big big" href="javascript:void(0);" onclick="$('form[name=newTrial]').submit();"><?=_('Save');?></a>
|
||||
<a class="button save-big big" href="javascript:void(0);" onclick="$('form[name=newExperiment]').submit();"><?=_('Save');?></a>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
@@ -37,15 +37,15 @@
|
||||
// get the active project, if there is one
|
||||
if ($this->input->get('active_project'))
|
||||
$active_project = $this->project->getById($this->input->get('active_project'));
|
||||
else
|
||||
else
|
||||
$active_project = false;
|
||||
|
||||
|
||||
$projects = $this->project->getAll();
|
||||
|
||||
|
||||
if(!$active_project):
|
||||
?>
|
||||
<option disabled="disabled" selected="selected"><strong><?=_('Select a project');?></strong></option>
|
||||
<?php
|
||||
<?php
|
||||
endif;
|
||||
foreach ($projects as $project):
|
||||
?>
|
||||
@@ -75,7 +75,7 @@
|
||||
<a href="javascript:void(0);" onclick="$(this).parent().toggleClass('active').find('ul').toggle();"><?=_('Project');?> <?=$active_project['shortname'];?></a>
|
||||
<ul>
|
||||
<li><a href="<?=site_url('projects/detail/' . $active_project['id']);?>" title="<?=_('Show overview');?>"><?=_('Overview');?></a></li>
|
||||
<li><a href="<?=site_url('trials/create/' . $active_project['id']);?>" title="<?=sprintf(_('Create a new trial for the project "%s"'), $active_project['name']);?>"><?=_('New trial');?></a></li>
|
||||
<li><a href="<?=site_url('experiments/create/' . $active_project['id']);?>" title="<?=sprintf(_('Create a new experiment for the project "%s"'), $active_project['name']);?>"><?=_('New experiment');?></a></li>
|
||||
<li><a href="<?=site_url('results/project/' . $active_project['id']);?>" title="<?=sprintf(_('Show results for the project "%s"'), $active_project['name']);?>"><?=_('Show results');?></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -34,28 +34,28 @@
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
<h3><?=_('Trials');?></h3>
|
||||
<h3><?=_('Experiments');?></h3>
|
||||
<table class="tableList">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><?=_('Trial');?></th>
|
||||
<th scope="col"><?=_('Name');?></th>
|
||||
<th scope="col"><?=_('Jobs');?></th>
|
||||
<th scope="col"><?=_('Actions');?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if (count($trials) > 0):
|
||||
foreach ($trials as $trial):
|
||||
if (count($experiments) > 0):
|
||||
foreach ($experiments as $experiment):
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="<?=site_url('trials/' . $trial['id']);?>" title="<?=sprintf(_("Show trial '%s'"), $trial['name']);?>"><?=$trial['name'];?></a></td>
|
||||
<td><a href="<?=site_url('experiments/' . $experiment['id']);?>" title="<?=sprintf(_('Show experiment "%s"'), $experiment['name']);?>"><?=$experiment['name'];?></a></td>
|
||||
<td><span class="active"><?=_('Completed');?></span></td>
|
||||
<td>
|
||||
<a href="<?=site_url('trials/results/' . $trial['id']);?>" title="<?=sprintf(_('Show results for the trial "%s"'), $trial['name']);?>"><?=_('Show results');?></a> |
|
||||
<a href="<?=site_url('trials/create/' . $project['id'] . '/' . $trial['id']);?>" title="<?=sprintf(_('Copy trial "%s"'), $trial['name']);?>"><?=_('Copy');?></a> |
|
||||
<a href="<?=site_url('trials/edit/' . $trial['id']);?>" title="<?=sprintf(_('Edit trial "%s"'), $trial['name']);?>"><?=_('Edit');?></a> |
|
||||
<a href="<?=site_url('trials/delete/' . $trial['id']);?>" title="<?=sprintf(_('Delete trial "%s"'), $trial['name']);?>"><?=_('Delete');?></a>
|
||||
<a href="<?=site_url('experiments/results/' . $experiment['id']);?>" title="<?=sprintf(_('Show results for this experiment'), $experiment['name']);?>"><?=_('Show results');?></a> |
|
||||
<a href="<?=site_url('experiments/create/' . $project['id'] . '/' . $experiment['id']);?>" title="<?=sprintf(_('Copy experiment "%s"'), $experiment['name']);?>"><?=_('Copy');?></a> |
|
||||
<a href="<?=site_url('experiments/edit/' . $experiment['id']);?>" title="<?=sprintf(_('Edit this experiment'), $experiment['name']);?>"><?=_('Edit');?></a> |
|
||||
<a href="<?=site_url('experiments/delete/' . $experiment['id']);?>" title="<?=sprintf(_('Delete experiment'), $experiment['name']);?>"><?=_('Delete');?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
@@ -63,7 +63,7 @@
|
||||
else:
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="3"><?=_('No trials available.');?></td>
|
||||
<td colspan="3"><?=_('No experiments available.');?></td>
|
||||
</tr>
|
||||
<?php
|
||||
endif;
|
||||
@@ -71,7 +71,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><a class="button add" href="<?=site_url('trials/create/' . $project['id']);?>"><?=_('Create a new trial');?></a>
|
||||
<p><a class="button add" href="<?=site_url('experiments/create/' . $project['id']);?>"><?=_('Create experiment');?></a>
|
||||
</div>
|
||||
|
||||
<div class="title">
|
||||
@@ -82,7 +82,7 @@
|
||||
<table class="tableList">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"><?=_('Trial');?></th>
|
||||
<th scope="col"><?=_('Experiment');?></th>
|
||||
<th scope="col"><?=_('Started');?></th>
|
||||
<th scope="col"><?=_('Finished');?></th>
|
||||
<th scope="col"><?=_('Actions');?></th>
|
||||
@@ -98,8 +98,8 @@
|
||||
<td><?=$job['started_at'];?></td>
|
||||
<td><?=$job['finished_at'] != '0000-00-00 00:00:00' ? $job['finished_at'] : _('Currently running');?></td>
|
||||
<td>
|
||||
<a href="<?=site_url('trials/results/' . $job['id']);?>" title="<?= sprintf(_('Show results for the trial "%s"'), $job['name']);?>"><?=_('Show results');?></a> |
|
||||
<a href="<?=site_url('trials/edit/' . $job['id']);?>" title="<?= sprintf(_('Edit trial "%s"'), $job['name']);?>"><?=_('Edit');?></td>
|
||||
<a href="<?=site_url('experiments/results/' . $job['id']);?>" title="<?= sprintf(_('Show results for this experiment'), $job['name']);?>"><?=_('Show results');?></a> |
|
||||
<a href="<?=site_url('experiments/edit/' . $job['id']);?>" title="<?= sprintf(_('Edit this experiment'), $job['name']);?>"><?=_('Edit');?></td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<input type="file" name="defaultmodel" id="defaultmodel" class="file" />
|
||||
<?=form_error('defaultmodel');?>
|
||||
</div>
|
||||
<label class="note"><?=_('Upload a 3D model that is used as a default for new trials.<br/>This model can be changed for every trial.');?></label>
|
||||
<label class="note"><?=_('Upload a 3D model that is used as a default for new experiments.<br/>This model can be changed for every experiment.');?></label>
|
||||
</li>
|
||||
<li>
|
||||
<?=form_label(_('Default configuration'), 'defaultconfig');?>
|
||||
@@ -42,7 +42,7 @@
|
||||
<input type="file" name="defaultconfig" id="defaultconfig" class="file" />
|
||||
<?=form_error('defaultconfig');?>
|
||||
</div>
|
||||
<label class="note"><?=_('Upload a configuration that is used as a default for new trials.<br/>This configuration can be changed for every trial.');?></label>
|
||||
<label class="note"><?=_('Upload a configuration that is used as a default for new experiments.<br/>This configuration can be changed for every experiment.');?></label>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" onclick="document.forms.createproject.submit()" class="button"><?=_('Save');?></a>
|
||||
|
||||
Reference in New Issue
Block a user