"pull-right" ], [ UI::h('a', [ 'href' => $this->getLink('listLastJobs'), 'class' => "btn btn-link", ], "Ostatnio uruchione"), UI::hButtonPost("Odśwież", [ 'class' => "btn btn-link", // 'form.class' => "pull-right", 'title' => "Wczytaj ponownie listę dostępnych funkcji", 'data' => [ 'forceUpdate' => '1', ] ]), ]); echo UI::h('h1', [], 'Druki'); UI::tryCatchView([ $this, 'listAntView' ]); UI::endContainer(); UI::dol(); } function listAntView() { $taskList = $this->getAntUrlActionList(); // $featureID = V::get('featureID', '', $_GET); $primaryKey = V::get('primaryKey', '', $_GET, 'word'); $typeName = V::get('typeName', '', $_GET, 'word'); if (empty($typeName)) throw new Exception("Missing typeName"); if (empty($primaryKey)) throw new Exception("Missing primaryKey"); $parsedInfo = Core_AclHelper::parseTypeName($typeName); DBG::log($parsedInfo, '', "Ant parseTypeName({$typeName})"); $acl = ACL::getAclByNamespace("{$parsedInfo['url']}/{$parsedInfo['name']}"); $pkField = $acl->getPrimaryKeyField(); echo UI::h('p', [ 'class' => "text-muted" ], [ "Druki dla rekordu '{$primaryKey}' w tabeli ", UI::h('a', [ 'href' => Router::getRoute('ViewTableAjax')->getLink('', [ 'namespace' => $acl->getNamespace() ]) ], $acl->getRawLabel()), ]); UI::inlineJS( __FILE__ . '.async.js', [ // p5UI_runAntAsyncJob 'RUN_ANT_JOB_URL' => $this->getLink('startAntJobAjax'), 'RUN_TEST_ANT_JOB_URL' => $this->getLink('startTestAntJobAjax'), ]); // echo UI::h('div', [ 'style' => "padding-bottom:8px; border-bottom:1px solid #eee;" ], [ // UI::h('select', [ 'class' => "form-control" ], array_map(function ($label, $path) { // return UI::h('option', [ 'value' => $path ], $label); // }, $taskList, array_keys($taskList))), // ]); UI::startTag('ul'); foreach ($taskList as $path => $label) { echo UI::h('li', [], [ UI::h('a', [ 'class' => 'btn btn-md btn-link', 'href' => $this->getLink('ant', [ 'path' => $path, 'typeName' => $typeName, 'primaryKey' => $primaryKey, 'primaryKeyField' => $pkField ]) ], "Uruchom '{$label}'") ]); $tmpls = $this->getAntUrlActionTemplates($path); if (!empty($tmpls)) { foreach ($tmpls as $tmpl => $labelTmpl) { echo UI::h('div', [ 'style' => "padding-left: 50px" ], [ UI::h('a', [ 'href' => $this->getLink('ant', [ 'path' => $path, 'template' => $tmpl, 'typeName' => $typeName, 'primaryKey' => $primaryKey, 'primaryKeyField' => $pkField ]), 'class' => 'btn btn-sm btn-link', ], ' ' . $labelTmpl), " ", UI::h('a', [ 'href' => $this->getLink('ant', [ 'path' => $path, 'template' => $tmpl, 'typeName' => $typeName, 'primaryKey' => $primaryKey, 'primaryKeyField' => $pkField ]), 'onclick' => 'return p5UI_runAntAsyncJob(event, this)', 'data-namespace' => $acl->getNamespace(), 'data-primaryKey' => $primaryKey, 'data-ant_path' => $path, 'data-ant_template' => $tmpl, 'class' => 'btn btn-xs btn-default', 'title' => "Uruchom asynchronicznie", ], "uruchom"), " ", // UI::h('a', [ // 'href' => $this->getLink('ant', [ // 'path' => $path, // 'template' => $tmpl, // 'typeName' => $typeName, // 'primaryKey' => $primaryKey, // 'primaryKeyField' => $pkField // ]), // 'onclick' => 'return p5UI_runAntAsyncJob(event, this, { TEST: 1 })', // 'data-namespace' => $acl->getNamespace(), // 'data-primaryKey' => $primaryKey, // 'data-ant_path' => $path, // 'data-ant_template' => $tmpl, // 'class' => 'btn btn-xs btn-link', // 'title' => "TEST Uruchom asynchronicznie", // ], "test"), ]); } } } UI::endTag('ul'); } function listLastJobsAction() { UI::layout([ get_called_class(), 'listLastJobsView' ]); } static function listLastJobsView() { echo UI::h('ol', [ 'class' => "breadcrumb" ], [ UI::h('li', [], [ UI::h('a', [ 'href' => self::link() ], [ UI::h('i', [ 'class' => "glyphicon glyphicon-home", 'style' => "margin-right:6px" ]), // TODO: mv to h('p5:icon', [ 'type' => "home" ]) " ", "Druki", ]), ]), UI::h('li', [], [ "Ostatnio uruchomione zadania", ]), ]); echo UI::h('h1', [], "Ostatnio uruchomione zadania"); $postTask = V::get('postTask', '', $_POST); if ('asyncJobStart' === $postTask) UI::tryCatchView([ get_called_class(), 'asyncJobStartPostTask' ], [ 'args' => $_POST ]); UI::table([ 'disable_lp' => true, 'rows' => array_map(function ($item) { return array_merge( [ '#' => '', 'Nr' => '', 'Status' => '', ], $item, [ '#' => self::jobListItem_Akcje($item), 'Nr' => $item['ID'], 'Status' => self::jobListItem_Status($item['A_STATUS'], $item), ] ); }, self::fetchUserLastAsyncJobs()), ]); throw new Exception("TODO: list last jobs"); } static function fetchUserLastAsyncJobs() { return DB::getPDO()->fetchAll(" select j.* from CRM_ASYNC_JOB_LOG j where j.USER = :user order by ID DESC ", [ ':user' => User::getLogin(), ]); } static function jobListItem_Akcje($item) { return UI::h('div', [ 'class' => "btn-group" ], [ UI::h('button', [ // 'type' => "button", 'class' => "btn btn-xs btn-default dropdown-toggle", 'data-toggle' => "dropdown", ], [ // UI::h('i', [ 'class' => "glyphicon glyphicon-hamburder" ]) 'Akcje ', UI::h('span', [ 'class' => "caret" ]), ]), UI::h('ul', [ 'class' => "dropdown-menu" ], [ UI::h('li', [], [ UI::h('a', [ 'href' => self::link('asyncJobDebug', [ 'id' => $item['ID'] ]), ], "Debug Info '{$item['ID']}'"), ]), UI::h('li', [], [ UI::hButtonPost("Uruchom zadanie '{$item['ID']}'", [ 'class' => "p5-hover", 'style' => "padding:3px 20px", // 'form.class' => "pull-right", // 'title' => "", 'data' => [ 'postTask' => 'asyncJobStart', 'id' => $item['ID'], ] ]), ]), //
]), ]); } static function jobListItem_Status($status, $item) { switch ($status) { case 'WAITING': return UI::h(null, null, [ "Oczekujący", ]); case 'NORMAL': return UI::h(null, null, [ "Uruchomiony", ]); case 'OFF_HARD': return UI::h(null, null, [ "Zakończony", ]); default: return UI::h(null, null, $status); } } static function asyncJobStartPostTask($args) { DBG::nicePrint($args, 'DBG: $args'); $idJob = V::get('id', 0, $args, 'int'); if ($idJob <= 0) throw new Exception("Missing id"); Lib::loadClass('Core_AsyncJobs'); Core_AsyncJobs::startAsyncJob($idJob); throw new Exception("TODO: asyncJobStartPostTask"); } function asyncJobDebugAction() { UI::layout([ $this, 'asyncJobDebugView' ]); } function asyncJobDebugView() { echo UI::h('ul', [ 'class' => "breadcrumb" ], [ UI::h('li', [], [ UI::h('a', [ 'href' => $this->getLink('listLastJobs') ], "Ostatnio uruchomione zadania"), ]), UI::h('li', [ 'class' => "active" ], [ "Zadanie - Debug", ]), ]); $idJob = V::get('id', 0, $_GET, 'int'); if ($idJob <= 0) throw new Exception("Missing job ID"); $item = DB::getPDO()->fetchFirst(" select j.ID -- , j.ID_FUNCTION -- , j.ID_SOURCE_JOB -- , j.P_ID , j.DATE -- 2020-02-26 -- , j.VERSION , j.JOB_NAME -- Ant|default_db/IN7_DZIENNIK_KORESP|default_db.in7_dziennik_koresp/test-async|test-loop , j.LOCK_VALUE -- 66263 -- , j.USER , j.A_STATUS , j.A_RECORD_CREATE_DATE , j.A_RECORD_CREATE_AUTHOR , j.A_RECORD_UPDATE_DATE , j.A_RECORD_UPDATE_AUTHOR from CRM_ASYNC_JOB_LOG j where j.USER = :user and j.ID = :id ", [ ':id' => $idJob, ':user' => User::getLogin(), ]); if (!$item) throw new Exception("Zadanie nie istnieje"); DBG::nicePrint($item, "Zadanie '{$idJob}'"); // TODO: files list in task folder Lib::loadClass('Core_AsyncJobsFiles'); $basePath = Core_AsyncJobsFiles::basePath($item['ID'], $item['DATE']); $propertyFile = Core_AsyncJobsFiles::propertyFile($item['ID'], $item['DATE']); $startScript = Core_AsyncJobsFiles::startScript($item['ID'], $item['DATE']); $outLog = Core_AsyncJobsFiles::outLog($item['ID'], $item['DATE']); $errorLog = Core_AsyncJobsFiles::errorLog($item['ID'], $item['DATE']); DBG::nicePrint([ 'basePath' => $basePath, 'propertyFile' => $propertyFile, 'startScript' => $startScript, 'outLog' => $outLog, 'errorLog' => $errorLog, ], "DBG:job files"); DBG::nicePrint(shell_exec("ls -l '{$basePath}'"), 'DBG: basePath'); DBG::nicePrint(shell_exec("cat '{$propertyFile}'"), 'DBG: propertyFile'); DBG::nicePrint(shell_exec("cat '{$startScript}'"), 'DBG: startScript'); DBG::nicePrint(shell_exec("cat '{$outLog}'"), 'DBG: outLog'); DBG::nicePrint(shell_exec("cat '{$errorLog}'"), 'DBG: errorLog'); throw new Exception("TODO: asyncJobDebug"); } public function outputAction() {// index.php?_route=UrlAction_Ant&_task=output & path={$path} & file={$file}"; $path = V::get('path', '', $_GET); if (!$path) throw new Exception("Missing Ant path!"); $file = V::get('file', '', $_GET); if (!$file) throw new Exception("Missing Ant file!"); // TODO: allow auth by token? throw new Exception("TODO: return output file '$file' from ant task '{$path}'"); } function startTestAntJobAjaxAction() { Response::sendTryCatchJson([ $this, 'startTestAntJobAjax' ], $args = 'JSON_FROM_REQUEST_BODY'); } function startTestAntJobAjax($args) { sleep(2); $ret = rand(0, 1); switch ($ret) { case 1: return [ 'type' => "success", 'msg' => "Dodano zadanie", 'body' => [ 'id_job' => 123, ], ]; // default: throw new Exception("TODO:startAntJobAjax"); default: return [ 'type' => "error", 'msg' => "Wystąpił błąd podczas dodawania zadania", ]; } } function startAntJobAjaxAction() { Response::sendTryCatchJson([ $this, 'startAntJobAjax' ], $args = 'JSON_FROM_REQUEST_BODY'); } function startAntJobAjax($args) { // $args = body: JSON.stringify({ // namespace: "default_db/IN7_DZIENNIK_KORESP" // primaryKey: "66263" // ant_path: "default_db.in7_dziennik_koresp/test-bash" // ant_template: "test-loop" // }) $namespace = V::get('namespace', '', $args); $primaryKey = V::get('primaryKey', '', $args); $ant_path = V::get('ant_path', '', $args); $ant_template = V::get('ant_template', '', $args); if (empty($namespace)) throw new Exception("Missing namespace"); if (empty($primaryKey)) throw new Exception("Missing primaryKey"); if (empty($ant_path)) throw new Exception("Missing ant_path"); if (empty($ant_template)) throw new Exception("Missing ant_template"); // TODO: convert antAction to async mode // - register async job or get jobID // - if exists: show last call info (result, when, etc.) + run again btn // - if not exists: create new folder with base files, create exec script, run this script in pm2 start // - parse result into AsyncJob/output and AsyncJob/output_type Lib::loadClass('Core_AsyncJobs'); $idJob = Core_AsyncJobs::registerNewAntTask([ 'namespace' => $namespace, 'primaryKey' => $primaryKey, 'ant_path' => $ant_path, 'ant_template' => $ant_template, ]); if (!$idJob) throw new Exception("Wystąpił błąd podczas dodawania zadania"); return [ 'type' => "success", 'msg' => "Dodano zadanie", '__DBG__args' => $args, ]; } public function antAction() { UI::gora(); UI::startContainer(); try { $path = V::get('path', '', $_GET); if (!$path) throw new Exception("Missing Ant path!"); $typeName = V::get('typeName', '', $_GET); if (!$typeName) throw new Exception("Missing typeName"); $primaryKey = V::get('primaryKey', '', $_GET); if (!$primaryKey) throw new Exception("Missing primaryKey"); $pkField = V::get('primaryKeyField', '', $_GET); if (!$pkField) throw new Exception("Missing primaryKeyField"); // list($nsPrefix, $objectName) = explode(':', $typeName);// TODO: get wfs prefix from typeName $parsedInfo = Core_AclHelper::parseTypeName($typeName); DBG::log($parsedInfo, '', "Ant parseTypeName({$typeName})"); $nsPrefix = $parsedInfo['prefix']; $objectName = $parsedInfo['name']; $template = V::get('template', '', $_GET); $confirmAntfile = V::get('confirmAntfile', '', $_GET); $confirmAntfileTarget = V::get('confirmAntfileTarget', '', $_GET); // TODO: validate missing ... DBG::log($_GET, 'array', '$_GET'); DBG::log([ 'msg'=>'$path', '$path'=>$path]); DBG::log([ 'msg'=>'$primaryKey', '$primaryKey'=>$primaryKey]); DBG::log([ 'msg'=>'$typeName', '$typeName'=>$typeName]); $taskList = $this->getAntUrlActionList(); if (!array_key_exists($path, $taskList)) throw new Exception("Ant path not exists! '{$path}'"); echo UI::h('h3', [], [ "Druk", '