Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/fulltextsearch.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2018-08-18 23:43:23 +0300
committerMaxence Lange <maxence@artificial-owl.com>2018-08-18 23:43:23 +0300
commitb8c2bf10fc68d3b5e15985a04891c836a6c4e0bd (patch)
tree81e38c3b45ca8310c81d20a566ba557d1b77cab3 /lib
parent6de2f3692ff7fdff9938a75da72d3e1dc2869aff (diff)
new UI for live
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Command/Live.php389
1 files changed, 381 insertions, 8 deletions
diff --git a/lib/Command/Live.php b/lib/Command/Live.php
index 70a1037..266eec1 100644
--- a/lib/Command/Live.php
+++ b/lib/Command/Live.php
@@ -31,6 +31,8 @@ use OCA\FullTextSearch\Exceptions\InterruptException;
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
use OCA\FullTextSearch\Model\ExtendedBase;
use OCA\FullTextSearch\Model\Runner;
+use OCA\FullTextSearch\Model\Index as ModelIndex;
+use OCA\FullTextSearch\Service\CliService;
use OCA\FullTextSearch\Service\ConfigService;
use OCA\FullTextSearch\Service\IndexService;
use OCA\FullTextSearch\Service\MiscService;
@@ -38,6 +40,7 @@ use OCA\FullTextSearch\Service\PlatformService;
use OCA\FullTextSearch\Service\ProviderService;
use OCA\FullTextSearch\Service\RunningService;
use OCP\IUserManager;
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -46,6 +49,43 @@ class Live extends ExtendedBase {
const CYCLE_DELAY = 10;
+ const PANEL_RUN = 'run';
+ const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%';
+
+ const PANEL_INDEX = 'indexing';
+ const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────';
+ const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: <info>%providerName:-20s%</info> Account: <info>%userId%</info>';
+ const PANEL_INDEX_LINE_ACTION = '│ Action: <info>%action%</info>';
+ const PANEL_INDEX_LINE_DOCUMENT = '│ Document: <info>%documentId%</info>';
+ const PANEL_INDEX_LINE_INFO = '│ Info: <info>%info%</info>';
+ const PANEL_INDEX_LINE_TITLE = '│ Title: <info>%title%</info>';
+ const PANEL_INDEX_LINE_CONTENT = '│ Content size: <info>%content%</info>';
+ const PANEL_INDEX_LINE_RESULT = '│ Result: %resultColored%';
+ const PANEL_INDEX_LINE_FOOTER = '└──';
+
+ const PANEL_STATUS = 'status';
+ const PANEL_STATUS_LINE_HEADER = '┌─ Status ────';
+ const PANEL_STATUS_LINE_DOCUMENTS = '│ Progress: %documentLeft:6s%/%documentTotal% %progressStatus%';
+// const PANEL_STATUS_LINE_DOCUMENTS_LEFT = '│ Document left:';
+ const PANEL_STATUS_LINE_ERRORS = '│ Error: <comment>%errorCurrent:6s%</comment>/<comment>%errorTotal%</comment>';
+ const PANEL_STATUS_LINE_ERROR_MESSAGE = '│ Message: <comment>%errorMessage%</comment>';
+ const PANEL_STATUS_LINE_ERROR_EXCEPTION = '│ Exception: <comment>%errorException%</comment>';
+ const PANEL_STATUS_LINE_ERROR_INDEX = '│ Index: <comment>%errorIndex%</comment>';
+
+
+ const PANEL_STATUS_LINE_FOOTER = '└──';
+
+ const PANEL_LINE_EMPTY = '│ ';
+
+ const PANEL_COMMANDS_ROOT = 'root';
+ const PANEL_COMMANDS_ROOT_LINE = '## <char>q</char>:quit ## <char>p</char>:pause ';
+ const PANEL_COMMANDS_PAUSED = 'paused';
+ const PANEL_COMMANDS_PAUSED_LINE = '## <char>q</char>:quit ## <char>u</char>:unpause ## <char>n</char>:next step';
+ const PANEL_COMMANDS_DONE = 'done';
+ const PANEL_COMMANDS_DONE_LINE = '## <char>q</char>:quit';
+ const PANEL_COMMANDS_ERRORS = 'errors';
+ const PANEL_COMMANDS_ERRORS_LINE = '## <char>f</char>:first error ## <char>h</char>/<char>j</char>:prec/next error ## <char>d</char>:delete error ## <char>l</char>:last error';
+
/** @var IUserManager */
private $userManager;
@@ -53,6 +93,12 @@ class Live extends ExtendedBase {
/** @var ConfigService */
private $configService;
+ /** @var CliService */
+ private $cliService;
+
+ /** @var RunningService */
+ private $runningService;
+
/** @var IndexService */
private $indexService;
@@ -65,10 +111,16 @@ class Live extends ExtendedBase {
/** @var MiscService */
private $miscService;
-
/** @var Runner */
private $runner;
+
+ /** @var array */
+ private $errors = [];
+
+ /** @var bool */
+ private $navigateLastError = true;
+
/**
* Index constructor.
*
@@ -82,7 +134,7 @@ class Live extends ExtendedBase {
*/
public function __construct(
IUserManager $userManager, RunningService $runningService, ConfigService $configService,
- IndexService $indexService, PlatformService $platformService,
+ CliService $cliService, IndexService $indexService, PlatformService $platformService,
ProviderService $providerService, MiscService $miscService
) {
parent::__construct();
@@ -90,6 +142,8 @@ class Live extends ExtendedBase {
$this->runner = new Runner($runningService, 'commandLive');
$this->configService = $configService;
+ $this->cliService = $cliService;
+ $this->runningService = $runningService;
$this->indexService = $indexService;
$this->platformService = $platformService;
$this->providerService = $providerService;
@@ -120,19 +174,43 @@ class Live extends ExtendedBase {
throw new Exception('This feature is only available on Nextcloud 14 or newer');
}
+ /** do not get stuck while waiting interactive input */
+ readline_callback_handler_install(
+ '', function() {
+ }
+ );
+ stream_set_blocking(STDIN, false);
+
+ $outputStyle = new OutputFormatterStyle('white', 'black', ['bold']);
+ $output->getFormatter()
+ ->setStyle('char', $outputStyle);
+
+ $this->runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']);
+ $this->runner->onKeyPress([$this, 'onKeyPressed']);
+ $this->runner->onNewAction([$this, 'onNewAction']);
+ $this->runner->onNewIndexError([$this, 'onNewIndexError']);
+
+ $this->indexService->setRunner($this->runner);
+ $this->cliService->setRunner($this->runner);
+
+ $this->generatePanels();
+
+
try {
$this->runner->sourceIsCommandLine($this, $output);
$this->runner->start();
- $this->runner->output('live.');
+
+ $this->cliService->runDisplay($output);
+ $this->generateIndexErrors();
+ $this->displayError();
+
+ $this->liveCycle();
} catch (Exception $e) {
$this->runner->exception($e->getMessage(), true);
throw $e;
}
- $this->indexService->setRunner($this->runner);
-
- $this->liveCycle();
$this->runner->stop();
}
@@ -165,9 +243,9 @@ class Live extends ExtendedBase {
}
}
- $this->runner->updateAction('waiting');
+ $this->runner->updateAction('waiting', true);
- sleep(self::CYCLE_DELAY);
+ usleep(300000);
}
$this->runner->stop();
@@ -175,6 +253,301 @@ class Live extends ExtendedBase {
}
+ /**
+ * @param $key
+ */
+ public function onKeyPressed($key) {
+ $key = strtolower($key);
+ if ($key === 'q') {
+ try {
+ $this->runner->stop();
+ } catch (TickDoesNotExistException $e) {
+ /** we do nohtin' */
+ }
+ exit();
+ }
+
+ $current = $this->cliService->currentPanel('commands');
+ if ($current === self::PANEL_COMMANDS_ROOT && $key === 'p') {
+ $this->cliService->switchPanel('commands', self::PANEL_COMMANDS_PAUSED);
+ $this->runner->pause(true);
+ }
+ if ($current === self::PANEL_COMMANDS_PAUSED && $key === 'u') {
+ $this->cliService->switchPanel('commands', self::PANEL_COMMANDS_ROOT);
+ $this->runner->pause(false);
+ }
+
+ if ($key === 'f') {
+ $this->displayError(-99);
+ }
+ if ($key === 'h') {
+ $this->displayError(-1);
+ }
+ if ($key === 'j') {
+ $this->displayError(1);
+ }
+ if ($key === 'l') {
+ $this->displayError(99);
+ }
+ if ($key === 'd') {
+ $this->deleteError();
+ }
+ }
+
+
+ /**
+ * @param array $error
+ */
+ public function onNewIndexError($error) {
+ $this->errors[] = $error;
+ $this->displayError();
+ }
+
+
+ /**
+ *
+ */
+ private function generatePanels() {
+
+ $this->cliService->createPanel(
+ self::PANEL_RUN,
+ [
+ self::PANEL_RUN_LINE_MEMORY
+ ]
+ );
+ $this->cliService->createPanel(
+ self::PANEL_INDEX, [
+ self::PANEL_INDEX_LINE_HEADER,
+ self::PANEL_INDEX_LINE_ACCOUNT,
+ self::PANEL_INDEX_LINE_ACTION,
+ self::PANEL_INDEX_LINE_DOCUMENT,
+ self::PANEL_INDEX_LINE_INFO,
+ self::PANEL_INDEX_LINE_TITLE,
+ self::PANEL_INDEX_LINE_CONTENT,
+ self::PANEL_INDEX_LINE_RESULT,
+ self::PANEL_INDEX_LINE_FOOTER,
+ ]
+ );
+
+ $this->cliService->createPanel(
+ self::PANEL_STATUS, [
+ self::PANEL_STATUS_LINE_HEADER,
+ self::PANEL_STATUS_LINE_DOCUMENTS,
+ self::PANEL_STATUS_LINE_ERRORS,
+ self::PANEL_STATUS_LINE_ERROR_MESSAGE,
+ self::PANEL_STATUS_LINE_ERROR_EXCEPTION,
+ self::PANEL_STATUS_LINE_ERROR_INDEX,
+ self::PANEL_STATUS_LINE_FOOTER,
+ ]
+ );
+
+ $this->cliService->createPanel(
+ self::PANEL_COMMANDS_ROOT, [
+ self::PANEL_COMMANDS_ROOT_LINE
+ ]
+ );
+
+ $this->cliService->createPanel(
+ self::PANEL_COMMANDS_PAUSED, [
+ self::PANEL_COMMANDS_PAUSED_LINE
+ ]
+ );
+
+ $this->cliService->createPanel(
+ self::PANEL_COMMANDS_ERRORS, [
+ self::PANEL_COMMANDS_ERRORS_LINE
+ ]
+ );
+
+ $this->cliService->initDisplay();
+ $this->cliService->displayPanel('run', self::PANEL_RUN);
+ $this->cliService->displayPanel('topPanel', self::PANEL_INDEX);
+ $this->cliService->displayPanel('bottomPanel', self::PANEL_STATUS);
+
+ $this->cliService->displayPanel('errors', self::PANEL_COMMANDS_ERRORS);
+
+ if ($this->runner->isPaused()) {
+ $this->cliService->displayPanel('commands', self::PANEL_COMMANDS_PAUSED);
+ } else {
+ $this->cliService->displayPanel('commands', self::PANEL_COMMANDS_ROOT);
+ }
+
+ $this->runner->setInfoArray(
+ [
+ 'userId' => '',
+ 'providerName' => '',
+ '_memory' => '',
+ 'documentId' => '',
+ 'action' => '',
+ 'info' => '',
+ 'title' => '',
+ '_paused' => '',
+ 'content' => '',
+ 'resultColored' => '',
+ 'documentLeft' => '',
+ 'documentTotal' => '',
+ 'progressStatus' => '',
+ 'errorCurrent' => '0',
+ 'errorTotal' => '0',
+ 'errorMessage' => '',
+ 'errorException' => '',
+ 'errorIndex' => ''
+ ]
+ );
+ }
+
+
+ /**
+ *
+ */
+ private function generateIndexErrors() {
+ $indexes = $this->indexService->getErrorIndexes();
+
+ foreach ($indexes as $index) {
+ foreach ($index->getErrors() as $error) {
+ $this->errors[] = [
+ 'index' => $index,
+ 'message' => $error['message'],
+ 'exception' => $error['exception'],
+ 'severity' => $error['sev']
+ ];
+ }
+
+ }
+
+
+ }
+
+
+ /**
+ * @param int $pos
+ */
+ private function displayError($pos = 0) {
+ $total = sizeof($this->errors);
+
+ if ($total === 0) {
+ $this->runner->setInfoArray(
+ [
+ 'errorCurrent' => 0,
+ 'errorTotal' => 0,
+ ]
+ );
+
+ return;
+ }
+
+ $current = key($this->errors) + 1;
+ $error = $this->getNavigationError($pos, ($current === 1), ($current === $total));
+ $current = key($this->errors) + 1;
+
+ if ($error === false) {
+ return;
+ }
+
+ /** @var ModelIndex $index */
+ $index = $error['index'];
+ $errorIndex = '';
+ if ($index !== null) {
+ $errorIndex = $index->getProviderId() . ':' . $index->getDocumentId();
+ }
+
+ $this->runner->setInfoArray(
+ [
+ 'errorCurrent' => $current,
+ 'errorTotal' => $total,
+ 'errorMessage' => MiscService::get('message', $error, ''),
+ 'errorException' => MiscService::get('exception', $error, ''),
+ 'errorIndex' => $errorIndex
+ ]
+ );
+ }
+
+
+ /**
+ * @param int $pos
+ * @param bool $isFirst
+ * @param bool $isLast
+ *
+ * @return bool|array
+ */
+ private function getNavigationError($pos, $isFirst, $isLast) {
+
+ if ($pos === 0) {
+ if ($this->navigateLastError === true) {
+ return end($this->errors);
+ } else {
+ return current($this->errors);
+ }
+ }
+
+ $this->navigateLastError = false;
+ if ($pos === -99) {
+ return reset($this->errors);
+ }
+
+ if ($pos === -1 && !$isFirst) {
+ return prev($this->errors);
+ }
+
+ if ($pos === 1 && !$isLast) {
+ return next($this->errors);
+ }
+
+ if ($pos === 99) {
+ $this->navigateLastError = true;
+
+ return end($this->errors);
+ }
+
+ return false;
+ }
+
+
+ /**
+ *
+ */
+ private function deleteError() {
+ $current = current($this->errors);
+ if ($current === false) {
+ return;
+ }
+
+ $this->runner->setInfoArray(
+ [
+ 'errorMessage' => '',
+ 'errorException' => '',
+ 'errorIndex' => ''
+ ]
+ );
+
+ $pos = key($this->errors);
+
+ /** @var ModelIndex $index */
+ $index = $current['index'];
+ $this->indexService->resetErrorFromIndex($index);
+
+ $errors = [];
+ foreach ($this->errors as $error) {
+ /** @var ModelIndex $errorIndex */
+ $errorIndex = $error['index'];
+ if ($index->getProviderId() === $errorIndex->getProviderId()
+ && $index->getDocumentId() === $errorIndex->getDocumentId()) {
+ continue;
+ }
+
+ $errors[] = $error;
+ }
+
+ $this->errors = $errors;
+ while (key($this->errors) < $pos) {
+ if (next($this->errors) === false) {
+ end($this->errors);
+ break;
+ }
+ }
+
+ $this->displayError();
+ }
}