Commit a58aa0cb authored by Penom Nom's avatar Penom Nom

add dowload workflow

parent 2474ad4c
......@@ -406,6 +406,64 @@ class t3MySQLdb(object):
logging.getLogger("t3MySQLdb.select_run").debug("Returning [" + str([res[0], res[1], res[2], res[3], res[4], res[5], res[6]]) + "]")
return [res[0], res[1], res[2], res[3], res[4], res[5], res[6]]
def select_run_informations(self, run_id):
"""
Return run informations allong with project information
"""
parts = [
'SELECT',
'tx_nG6_project.uid AS project_id,',
'tx_nG6_project.name AS project_name,',
'tx_nG6_run.uid AS run_id,',
'tx_nG6_run.directory AS run_directory,',
'tx_nG6_run.description AS run_description, ',
'tx_nG6_run.species AS run_species, ',
'tx_nG6_run.name AS run_name, ',
'tx_nG6_run.data_nature AS run_data_nature, ',
'tx_nG6_run.sequencer AS run_sequencer, ',
'tx_nG6_run.type AS run_type, ',
'tx_nG6_run.full_seq_size, ',
'tx_nG6_run.hidden AS run_hidden, ',
'tx_nG6_run.nb_sequences, ',
'tx_nG6_run.storage_size, ',
'tx_nG6_run.date AS run_date',
'FROM',
'fe_rights ',
'INNER JOIN tx_nG6_project ON tx_nG6_project.uid=fe_rights.project_id ',
'INNER JOIN tx_nG6_project_run ON tx_nG6_project.uid=tx_nG6_project_run.project_id ',
'INNER JOIN tx_nG6_run ON tx_nG6_project_run.run_id=tx_nG6_run.uid ',
'WHERE',
'tx_nG6_run.uid=%s'%run_id,
'ORDER BY',
'tx_nG6_run.date DESC'
]
query = " ".join(parts)
conn = connect(self.host, self.user, self.passwd, self.db, cursorclass = cursors.DictCursor)
curs = conn.cursor()
curs.execute(query)
row = curs.fetchall()[0]
curs.close()
conn.close()
return {
'id' : row['run_id'],
'project_id' : row['project_id'],
'project_name' : row['project_name'],
'directory' : row['run_directory'],
'name' : row['run_name'],
'hidden' : row['run_hidden'],
'species' : row['run_species'],
'nb_sequences' : row['nb_sequences'],
'full_seq_size' : row['full_seq_size'],
'date' : row['run_date'],
'data_nature' : row['run_data_nature'],
'sequencer' : row['run_sequencer'],
'type' : row['run_type'],
'description' : row['run_description']
}
def select_run_directory(self, run_id):
"""
Return the run directory
......@@ -491,6 +549,72 @@ class t3MySQLdb(object):
conn.close()
return analysis_ids
def get_user_run_analysis(self, user_id, run_id, order_by = "", limit = ""):
if user_id :
where = 'fe_users.uid=' + str(user_id) + ' AND tx_nG6_run_analyze.run_id=' + str(run_id) + ' AND ((fe_rights.right_id<>2 AND tx_nG6_analyze.hidden=0) OR fe_rights.right_id=2)'
else :
where = 'tx_nG6_run_analyze.run_id=' + str(run_id) +' AND tx_nG6_project.public=0 AND tx_nG6_analyze.hidden=0'
parts = [
'SELECT' ,
'tx_nG6_analyze.uid AS analyze_id,',
'tx_nG6_analyze.directory AS analyze_directory,',
'tx_nG6_analyze.name AS analyze_name, ',
'tx_nG6_analyze.params AS analyze_params, ',
'tx_nG6_analyze.class AS analyze_class, ',
'tx_nG6_analyze.date AS analyze_date, ',
'tx_nG6_analyze.software AS analyze_software, ',
'tx_nG6_analyze.version AS analyze_version, ',
'tx_nG6_analyze.hidden AS analyze_hidden, ',
'tx_nG6_analyze.description AS analyze_description, ',
'tx_nG6_analyze.is_editable AS analyze_is_editable, ',
'tx_nG6_analyze.parent_uid AS analyze_parent_uid ',
'FROM',
'tx_nG6_analyze ',
'INNER JOIN tx_nG6_run_analyze ON tx_nG6_analyze.uid = tx_nG6_run_analyze.analyze_id ',
'INNER JOIN tx_nG6_run ON tx_nG6_run_analyze.run_id = tx_nG6_run.uid ',
'INNER JOIN tx_nG6_project_run ON tx_nG6_run.uid = tx_nG6_project_run.run_id ',
'INNER JOIN tx_nG6_project ON tx_nG6_project_run.project_id = tx_nG6_project.uid ',
'INNER JOIN fe_rights ON tx_nG6_project.uid=fe_rights.project_id ',
'INNER JOIN fe_users ON fe_rights.fe_user_id=fe_users.uid ',
'WHERE',
where
]
if order_by :
parts.extend(['ORDER BY', order_by])
if limit :
parts.extend(['LIMIT', limit])
query = " ".join(parts)
conn = connect(self.host, self.user, self.passwd, self.db, cursorclass = cursors.DictCursor)
curs = conn.cursor()
curs.execute(query)
results = {}
for row in curs.fetchall() :
analyze_id = str(row['analyze_id']);
if not results.has_key(analyze_id) :
results[analyze_id] = {
'directory' : row['analyze_directory'],
'name' : row['analyze_name'],
'params' : row['analyze_params'],
'class' : row['analyze_class'],
'id' : int(row['analyze_id']),
'hidden' : row['analyze_hidden'],
'software' : row['analyze_software'],
'version' : row['analyze_version'],
'date' : row['analyze_date'],
'description' : row['analyze_description'],
'is_editable' : row['analyze_is_editable'],
'parent_id' : row['analyze_parent_uid']
}
curs.close()
conn.close()
return results
def update_sample_info(self, id , sample_id = None, name = None, reads1 = None, reads2 = None,
description = None, type = None, insert_size = None, nb_sequences = None, species = None,
full_seq_size = None):
......@@ -790,3 +914,114 @@ class t3MySQLdb(object):
logging.getLogger("t3MySQLdb.select_analysis").debug("Returning [" + str([res[0], res[1], res[2], res[3], res[4], res[5]]) + "]")
return [res[0], res[1], res[2], res[3], res[4], res[5]]
def select_analysis_informations(self, analysis_id):
"""
Select all information on an analyse
@param analysis_id:
"""
parts = [
'SELECT',
'tx_nG6_project.uid AS project_id,',
'tx_nG6_project.name AS project_name,',
'tx_nG6_analyze.uid AS analyze_id,',
'tx_nG6_analyze.directory AS analyze_directory,',
'tx_nG6_analyze.name AS analyze_name, ',
'tx_nG6_analyze.params AS analyze_params, ',
'tx_nG6_analyze.software AS analyze_software, ',
'tx_nG6_analyze.class AS analyze_class, ',
'tx_nG6_analyze.date AS analyze_date, ',
'tx_nG6_analyze.description AS analyze_description, ',
'tx_nG6_analyze.version AS analyze_version, ',
'tx_nG6_analyze.is_editable AS analyze_is_editable, ',
'tx_nG6_analyze.storage_size AS analyze_storage_size, ',
'tx_nG6_analyze.parent_uid AS analyze_parent_uid ',
'FROM',
'tx_nG6_project ',
'INNER JOIN tx_nG6_project_analyze ON tx_nG6_project.uid = tx_nG6_project_analyze.project_id ',
'INNER JOIN tx_nG6_analyze ON tx_nG6_analyze.uid=tx_nG6_project_analyze.analyze_id ',
'WHERE',
'tx_nG6_analyze.uid='+str(analyse_id),
]
query = " ".join(parts)
conn = connect(self.host, self.user, self.passwd, self.db, cursorclass = cursors.DictCursor)
curs = conn.cursor()
curs.execute(query)
# project analysis, add project informations
if curs.rowcount > 0:
row = curs.fetchall()[0]
curs.close()
conn.close()
return {
'project_name' : row['project_name'],
'project_id' : row['project_id'],
'run_name' : None,
'run_id' : None,
'directory' : row['analyze_directory'],
'name' : row['analyze_name'],
'class' : row['analyze_class'],
'params' : row['analyze_params'],
'date' : row['analyze_date'],
'description' : row['analyze_description'],
'parent_id' : row['analyze_parent_uid'],
'software' : row['analyze_software'],
'version' : row['analyze_version'],
'is_editable' : row['analyze_is_editable']
}
else :
parts = [
'SELECT',
'tx_nG6_project.name AS project_name,',
'tx_nG6_project.uid AS project_id,',
'tx_nG6_run.uid AS run_id,',
'tx_nG6_run.name AS run_name,',
'tx_nG6_analyze.uid AS analyze_id,',
'tx_nG6_analyze.directory AS analyze_directory,',
'tx_nG6_analyze.name AS analyze_name, ',
'tx_nG6_analyze.params AS analyze_params, ',
'tx_nG6_analyze.class AS analyze_class, ',
'tx_nG6_analyze.date AS analyze_date, ',
'tx_nG6_analyze.software AS analyze_software, ',
'tx_nG6_analyze.version AS analyze_version, ',
'tx_nG6_analyze.description AS analyze_description,',
'tx_nG6_analyze.is_editable AS analyze_is_editable,',
'tx_nG6_analyze.storage_size AS analyze_storage_size, ',
'tx_nG6_analyze.parent_uid AS analyze_parent_uid ',
'FROM',
'tx_nG6_project ',
'INNER JOIN tx_nG6_project_run ON tx_nG6_project_run.project_id = tx_nG6_project.uid ',
'INNER JOIN tx_nG6_run ON tx_nG6_run.uid = tx_nG6_project_run.run_id ',
'INNER JOIN tx_nG6_run_analyze ON tx_nG6_run_analyze.run_id = tx_nG6_run.uid ',
'INNER JOIN tx_nG6_analyze ON tx_nG6_analyze.uid = tx_nG6_run_analyze.analyze_id ',
'WHERE',
'tx_nG6_analyze.uid=' + str(analyse_id),
'ORDERBY',
'tx_nG6_analyze.name'
]
query = " ".join(parts)
curs.execute(query)
row = curs.fetchall()[0]
curs.close()
conn.close()
return {
'project_name' : row['project_name'],
'project_id' : row['project_id'],
'run_name' : row['run_name'],
'run_id' : row['run_id'],
'directory' : row['analyze_directory'],
'name' : row['analyze_name'],
'params' : row['analyze_params'],
'class' : row['analyze_class'],
'date' : row['analyze_date'],
'description' : row['analyze_description'],
'software' : row['analyze_software'],
'parent_id' : row['analyze_parent_uid'],
'version' : row['analyze_version'],
'is_editable' : row['analyze_is_editable']
}
\ No newline at end of file
......@@ -82,32 +82,6 @@ class tx_nG6_eid {
// Return the html_tree
print $html_tree;
// If downloading data is requested
} else if ($type == 'download') {
$format = trim(t3lib_div::_GP('format'));
// If link in home directory
if ($format == 'home_link') {
$ids = trim(t3lib_div::_GP('ids'));
$data_folder = trim(t3lib_div::_GP('data_folder'));
$user_login = trim(t3lib_div::_GP('user_login'));
$user_pwd = trim(t3lib_div::_GP('user_pwd'));
$user_directory = trim(t3lib_div::_GP('user_directory'));
$retcode = $this->create_symbolic_links($user_id, $user_login, $user_pwd, $ids, $data_folder, $user_directory);
print $retcode;
// If a .tar.gz file
} else {
$ids = trim(t3lib_div::_GP('ids'));
$data_folder = trim(t3lib_div::_GP('data_folder'));
$tmp_folder = trim(t3lib_div::_GP('tmp_folder'));
$user_email = trim(t3lib_div::_GP('user_email'));
$title_email = trim(t3lib_div::_GP('title_email'));
$msg_email = trim(t3lib_div::_GP('msg_email'));
$archive_info = $this->create_archive_script($user_id, $ids, $data_folder, $tmp_folder, "tar.gz", $user_email, $title_email, $msg_email);
$process = new Process("tcsh ".$archive_info[0]);
print "pid=".$process->getPid()."&archive_path=".$archive_info[1];
}
// If asked to check a job status
} else if($type == 'check_status') {
$pid = trim(t3lib_div::_GP('pid'));
......@@ -837,162 +811,6 @@ class tx_nG6_eid {
}
}
/**
* Creates an archiving script to archive data from ids
*
* @param string $user_id the user id
* @param array $ids list of ids to download
* @param string $data_folder the data folder where are stored the data
* @param string $tmp_folder the output directory
* @param string $format the archiving format (tar.gz)
* @param string $user_email the user email
* @param string $title_email the email title to send
* @param string $msg_email the email message to send
* @return array (the path to the script, the url path to the final archive)
*/
private function create_archive_script($user_id, $ids, $data_folder, $tmp_folder, $format, $user_email, $title_email, $msg_email) {
// First get the archive name where will be stored the data
$random_key = tx_nG6_utils::create_random_key(10);
$archive_path = $tmp_folder."/ng6_".$random_key;
while( file_exists($archive_path) )
$archive_path = $tmp_folder."/ng6_".$random_key;
// Then get the directories structure
$directories = $this->get_directories_structure_and_content($user_id, $ids, $data_folder, $archive_path);
$archive_script_path = $tmp_folder."/ng6_".$random_key.".sh";
// And write down the script in charge to create the archive
$fp = fopen($archive_script_path, 'w');
foreach($directories[0] as $index => $src_directory) {
if (!file_exists( $directories[1][$index])) {
fwrite($fp, "mkdir -p ".$directories[1][$index]."\n");
}
// For each files in the source directory
foreach(scandir($src_directory) as $file) {
if (is_file($src_directory."/".$file) and $file != "analyse.xml" and $file != "index.html" and $file != "run.cfg") {
fwrite($fp, "cp ".$src_directory."/".$file." ".$directories[1][$index]."\n");
}
}
}
fwrite($fp, "cd ".$tmp_folder."\n");
fwrite($fp, "tar -czf ng6_".$random_key.".tar.gz ng6_".$random_key."\n");
fwrite($fp, "rm -rf ".$archive_path."\n");
fwrite($fp, 'echo "'.str_replace(array('SPAN_ARCHIVE_NAME'), array("ng6_".$random_key.".tar.gz"), $msg_email).'" | mail -s "'.$title_email.'" '.$user_email."\n");
fclose($fp);
return array($archive_script_path, "ng6_".$random_key.".tar.gz");
}
/**
* Creates symbolic links between ids from data_folder into user_directory
*
* @param string $user_id the user id
* @param string $user_login the user login to make ssh
* @param string $user_pwd the user pwd to make ssh
* @param array $ids list of ids to download
* @param string $data_folder the data folder where are stored the data
* @param string $user_directory the output directory
* @return 0=>everything ok, 1=>user rigth problem, 2=>wrong authentification, 3=>connection error
*/
private function create_symbolic_links($user_id, $user_login, $user_pwd, $ids, $data_folder, $user_directory) {
// First try to connect the specified user using ssh
$connection = ssh2_connect('127.0.0.1', 22);
if (!$connection) return 3;
if (!ssh2_auth_password($connection, $user_login, $user_pwd)) return 2;
// Then get the directories structure
$directories = $this->get_directories_structure_and_content($user_id, $ids, $data_folder, $user_directory);
// And process the directories structure
$creation = true;
foreach($directories[0] as $index => $src_directory) {
if (!file_exists("ssh2.sftp://".$connection.$directories[1][$index])) {
if (!mkdir("ssh2.sftp://".$connection.$directories[1][$index], 0755, true)) {
$creation = false;
break;
}
// For each files in the source directory
foreach(scandir($src_directory) as $file) {
if (is_file($src_directory."/".$file) and $file != "analyse.xml" and $file != "index.html" and $file != "run.cfg") {
if (!ssh2_exec($connection, 'ln -s '.$src_directory.'/'.$file.' '.$directories[1][$index].'/'.$file)) {
$creation = false;
break;
}
}
}
}
}
if (!$creation) return 1;
return 0;
}
/**
* Returns a table with the right directories structure considering ids
*
* @param string $user_id The user id
* @param array $ids List of ids to download
* @param string $data_folder The data folder where are stored the data
* @param string $output_folder The output directory
* @return array [0] => source_directories, [1] => dest_directories
*/
private function get_directories_structure_and_content($user_id, $ids, $data_folder, $output_folder) {
$src_directories = array();
$dest_directories = array();
$vals = preg_split("/;/", $ids);
// Characters to be replaced in the names of the run, the analyses ...
$char_to_replace = array(' ','/');
// For each project/run/analysis
foreach($vals as $val) {
if ($val != "undefined" && $val != "") {
$id = preg_split("/_/", $val);
if ($id[0] == "data") {
$run = tx_nG6_db::select_run($id[1]);
if (!in_array($data_folder.$run["directory"], $src_directories)) {
$src_directories[] = $data_folder.$run["directory"];
$ddest = $output_folder."/Project_".str_replace($char_to_replace, '_', $run["project_name"]);
$ddest .= '.'.$run["project_id"]."/Run_".str_replace($char_to_replace, '_', $run["name"]).".".$id[1]."/RawData";
$dest_directories[] = $ddest;
}
} else if ($id[0] == "run") {
$run = tx_nG6_db::select_run($id[1]);
if (!in_array($data_folder.$run["directory"], $src_directories)) {
$src_directories[] = $data_folder.$run["directory"];
$ddest = $output_folder."/Project_".str_replace($char_to_replace, '_', $run["project_name"]);
$ddest .= '.'.$run["project_id"]."/Run_".str_replace($char_to_replace, '_', $run["name"]).".".$id[1]."/RawData";
$dest_directories[] = $ddest;
}
foreach(tx_nG6_db::get_user_run_analysis($user_id, $id[1], 'tx_nG6_analyze.name') as $analyse_id => $analyse_values) {
$aid = preg_split("/_/", $analyse_id);
if (!in_array($data_folder.$analyse_values["directory"], $src_directories)) {
$src_directories[] = $data_folder.$analyse_values["directory"];
$ddest = $output_folder."/Project_".str_replace($char_to_replace, '_', $run["project_name"]);
$ddest .= '.'.$run["project_id"]."/Run_".str_replace($char_to_replace, '_', $run["name"]);
$ddest .= ".".$id[1]."/Analyse_".str_replace($char_to_replace, '_', $analyse_values["name"]).".".$aid[1];
$dest_directories[] = $ddest;
}
}
} else if ($id[0] == "analyse") {
$analyse = tx_nG6_db::select_analyse($id[1]);
if (!in_array($data_folder.$analyse["directory"], $src_directories)) {
$src_directories[] = $data_folder.$analyse["directory"];
// If it's a project analyse
if ($analyse["run_id"] == 'None') {
$ddest = $output_folder."/Project_".str_replace($char_to_replace, '_', $analyse["project_name"]);
$ddest .= ".".$analyse["project_id"]."/Project_analyses/".str_replace($char_to_replace, '_', $analyse["name"]).".".$id[1];
$dest_directories[] = $ddest;
} else {
$ddest = $output_folder."/Project_".str_replace($char_to_replace, '_', $analyse["project_name"]);
$ddest .= ".".$analyse["project_id"]."/Run_".str_replace($char_to_replace, '_', $analyse["run_name"]);
$ddest .= ".".$analyse["run_id"]."/Analyse_".str_replace($char_to_replace, '_', $analyse["name"]).".".$id[1];
$dest_directories[] = $ddest;
}
}
}
}
}
return array($src_directories, $dest_directories);
}
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/nG6/class.tx_nG6_eid.php']) {
......
......@@ -40,18 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</div>
<div id="setAndRunModalBody" class="modal-body"></div>
<div id="setAndRunModalFooter" class="modal-footer">
<!--
<div class="btn-group">
<button id="close" class="btn btn-default" data-dismiss="modal"><i class="glyphicon glyphicon-remove"></i> Close</button>
</div>
<div class="btn-group">
<button id="refresh_workflow_status" class="btn btn-default"><i class="glyphicon glyphicon-refresh"></i> Refresh</button>
</div>
<div class="btn-group">
<button id="reset_workflow" class="btn btn-default"><i class="glyphicon glyphicon-refresh"></i> Reset</button>
<button id="run_workflow" class="btn btn-primary"><i class="glyphicon glyphicon-cog"></i> Run</button>
</div>
-->
</div>
</div>
</div>
......
......@@ -82,9 +82,12 @@ class tx_nG6_pi5 extends tslib_pibase {
$smarty->assign('llang', $this->LOCAL_LANG['default']);
}
// get server url from pi1
$smarty->assign('server_url', $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_nG6_pi1.']['server_url']);
$smarty->assign('server_name', $this->conf["server_name"]);
$smarty->assign('data_folder', $this->conf["data"]);
$smarty->assign('temp_folder', $this->conf["temp"]);
$smarty->assign('user_login', $GLOBALS['TSFE']->fe_user->user['username']);
if ($this->conf["directory_prefix"]) {
$smarty->assign('directory_prefix', $this->conf["directory_prefix"]);
} else {
......
......@@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<input type="hidden" id="user_id" value="{$user_id}" />
<input type="hidden" id="tmp_url" value="{$tmp_url}" />
<input type="hidden" id="server_url" value="{$server_url}" />
<input type="hidden" id="user_login" value="{$user_login}" />
<div class="sub-content sc-top">
<div class="ng6-content-header-left download">
......@@ -38,25 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
Please select below the data you want to download...
</p>
</div>
<h5>Download format :</h5>
<div style="float:left">
<div class="radio">
<label class="radio" style="font-size:13px">
<input type="radio" name="format" value="tar.gz" >
.tar.gz
</label>
</div>
{* If the server is configured, provide the create link option *}
{if $server_name}
<div class="radio">
<label class="radio" style="font-size:13px">
<input type="radio" name="format" value="home_link" checked>
links on {$server_name}
</label>
</div>
{/if}
</div>
<div style="float:right;margin-top:10px">
<button id="download_btn" class="btn btn-default disabled" type="button">Download</button>
</div>
......@@ -85,10 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<h3 id="myModalLabel"></h3>
</div>
<div id="myModalBody" class="modal-body"></div>
<div class="modal-footer">
<button data-dismiss="modal" class="btn btn-default"><i class="glyphicon glyphicon-remove"></i> Close</button>
<button id="action" class="btn btn-primary"><i class="glyphicon glyphicon-arrow-down"></i> Download</button>
</div>
<div id="myModalFooter" class="modal-footer"></div>
</div>
</div>
</div>
......@@ -144,167 +144,166 @@ $(function () {
$("#download_btn").removeClass("disabled");
}
});
/**
* Function is_download_file_ready
* function that asks if the download file is read to be downloaded
*/
function is_download_file_ready (val) {
var elt = val.split('&');
var pid = elt[0].split('=')[1];
var archive_path = elt[1].split('=')[1];
$.ajax({
url: "index.php?eID=tx_nG6&type=check_status&pid=" + pid + "&archive_path=" + archive_path,
success: function(val, status, xhr) {
var elt = val.split('&');
var pid = elt[0].split('=')[1];
var archive_path = elt[1].split('=')[1];
if (pid == "0") {
// Close the waiting window
$("#myModal").hide();
// If the user waited until then, display the download window
location.href = $("#tmp_url").val() + "/" + archive_path;
} else {
setTimeout(function(){is_download_file_ready(val)},1000) ;
/**
*
* @param workflow_id
* @param callback
* @returns
*/
function get_worflow_status(workflow_id, callback){
$.ajax({
url : $("#server_url").val() + '/get_workflow_status?display=list&workflow_id=' + workflow_id,
dataType : 'jsonp',
success : function(data){
if (callback){
callback(data);
}
}
});
}
})
}
$("#download_btn").click(function() {
// If some data are selected
if (!$(this).hasClass("disabled")) {
// If the user asked to download its data as symbolic links
if ($("input[type=radio][name=format]:checked").val() == "home_link") {
// Build the user form
$("#myModalLabel").html("Create symbolic link <small>in a home directory</small>");
var home_link_html = "<div>This functionality is only available if you have an account on the <strong> " + $("#server_name").val() + " server</strong>.</div> <br/>";
home_link_html += "<div class='tx-nG6-pi5-symlink'>";
home_link_html += '<form id="download_form" class="form-horizontal">';
home_link_html += ' <fieldset>';
home_link_html += ' <div class="form-group">';
home_link_html += ' <label class="col-sm-offset-2 col-sm-2 control-label">Login</label>';
home_link_html += ' <div class="col-sm-8">';
home_link_html += ' <input class="form-control" type="text" id="user_login_val" name="user_login_val"/>';
home_link_html += ' </div>';
home_link_html += ' </div>';
home_link_html += ' <div class="form-group">';
home_link_html += ' <label class="col-sm-offset-2 col-sm-2 control-label">Password</label>';
home_link_html += ' <div class="col-sm-8">';
home_link_html += ' <input class="form-control" type="password" id="user_pwd_val" name="user_pwd_val"/>';
home_link_html += ' </div>';
home_link_html += ' </div>';
home_link_html += ' <div class="form-group">';
home_link_html += ' <label class="col-sm-offset-2 col-sm-2 control-label">Directory</label>';
home_link_html += ' <div class="col-sm-8">';
home_link_html += ' <input class="form-control" type="text" value="' + $("#directory_prefix").val() + '" id="user_directory_val" name="user_directory_val"/>';
home_link_html += ' </div>';
home_link_html += ' </div>';
home_link_html += ' </fieldset>';
home_link_html += '</form>';
home_link_html += '</div>';
$("#myModalBody").html(home_link_html);
$("#myModalBody").css('height', '200px');
$("#action").show();
$("#action").removeClass("disabled");
$("#myModal").modal('show');
$("#download_form").validate({
rules: {
"user_login_val": { required: true },