начало добавления реестра магазинов
This commit is contained in:
parent
ecb2c7d32d
commit
fd27d88b6c
|
@ -7,15 +7,12 @@ namespace mirzaev\ebala\controllers;
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\ebala\controllers\core,
|
use mirzaev\ebala\controllers\core,
|
||||||
mirzaev\ebala\controllers\traits\errors,
|
mirzaev\ebala\controllers\traits\errors,
|
||||||
mirzaev\ebala\models\market as model,
|
mirzaev\ebala\models\registry,
|
||||||
|
mirzaev\ebala\models\market as model;
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
// Библиотека для ArangoDB
|
||||||
use ArangoDBClient\Document as _document;
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
// System libraries
|
|
||||||
use datetime,
|
|
||||||
exception;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Контроллер магазина
|
* Контроллер магазина
|
||||||
*
|
*
|
||||||
|
@ -129,7 +126,7 @@ final class market extends core
|
||||||
if (!empty($statuses_merged)) $filters .= empty($filters) ? $statuses_merged : " && ($statuses_merged)";
|
if (!empty($statuses_merged)) $filters .= empty($filters) ? $statuses_merged : " && ($statuses_merged)";
|
||||||
|
|
||||||
// Инициализация данных для генерации HTML-документа с таблицей
|
// Инициализация данных для генерации HTML-документа с таблицей
|
||||||
$this->view->rows = model::list(before: empty($filters) ? null : "FILTER ($filters)", page: (int) $this->session->buffer[$_SERVER['INTERFACE']]['markets']['page']);
|
$this->view->rows = registry::markets(before: empty($filters) ? null : "FILTER ($filters)", page: (int) $this->session->buffer[$_SERVER['INTERFACE']]['markets']['page']);
|
||||||
|
|
||||||
// Запись в cookie (только таким методом можно записать "hostonly: true")
|
// Запись в cookie (только таким методом можно записать "hostonly: true")
|
||||||
setcookie(
|
setcookie(
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\ebala\controllers;
|
||||||
|
|
||||||
|
// Файлы проекта
|
||||||
|
use mirzaev\ebala\controllers\core,
|
||||||
|
mirzaev\ebala\controllers\traits\errors,
|
||||||
|
mirzaev\ebala\models\operator as model;
|
||||||
|
|
||||||
|
// Библиотека для ArangoDB
|
||||||
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Контроллер оператора
|
||||||
|
*
|
||||||
|
* @package mirzaev\ebala\controllers
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class operator extends core
|
||||||
|
{
|
||||||
|
use errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Главная страница
|
||||||
|
*
|
||||||
|
* @param array $parameters Параметры запроса
|
||||||
|
*/
|
||||||
|
public function index(array $parameters = []): ?string
|
||||||
|
{
|
||||||
|
// Авторизация
|
||||||
|
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
|
||||||
|
// Авторизован аккаунт оператора или администратора
|
||||||
|
|
||||||
|
foreach (['confirmed', 'waiting', 'published', 'unpublished', 'problematic', 'hided', 'completed'] as $name) {
|
||||||
|
// Перебор фильтров статусов
|
||||||
|
|
||||||
|
// Инициализация значения (приоритет у cookie)
|
||||||
|
$value = $_COOKIE["operators_filter_$name"] ?? $this->session->buffer[$_SERVER['INTERFACE']]['operators']['filters'][$name] ?? 0;
|
||||||
|
|
||||||
|
// Инициализировано значение?
|
||||||
|
if ($value === null || $value === 0) continue;
|
||||||
|
|
||||||
|
// Генерация класса для HTML-элемента по его состоянию (0 - ОТСУТСТВУЕТ, 1 - И, 2 - ИЛИ)
|
||||||
|
$this->view->{$name} = match ($value) {
|
||||||
|
'0', 0 => 'earth',
|
||||||
|
'1', 1 => 'sand',
|
||||||
|
'2', 2 => 'river',
|
||||||
|
default => 'earth'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Генерация представлениямя
|
||||||
|
$main = $this->view->render(DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'operators.html');
|
||||||
|
} else $main = $this->authorization();
|
||||||
|
|
||||||
|
// Возврат (успех)
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', ['main' => $main]);
|
||||||
|
else if ($_SERVER['REQUEST_METHOD'] === 'POST') return $main;
|
||||||
|
|
||||||
|
// Возврат (провал)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прочитать
|
||||||
|
*
|
||||||
|
* @param array $parameters Параметры запроса
|
||||||
|
*/
|
||||||
|
public function read(array $parameters = []): ?string
|
||||||
|
{
|
||||||
|
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
|
||||||
|
// Авторизован аккаунт оператора или администратора
|
||||||
|
|
||||||
|
// Реинициализация актуальной страницы
|
||||||
|
if (isset($parameters['page'])) $this->session->write(['operators' => ['page' => $parameters['page']]]);
|
||||||
|
else if (empty($this->session->buffer[$_SERVER['INTERFACE']]['operators']['page'])) $this->session->write(['operators' => ['page' => 1]]);
|
||||||
|
|
||||||
|
// Инициализация буфера AQL-выражения для инъекции фильтра по интервалу
|
||||||
|
$polysemantic = '';
|
||||||
|
|
||||||
|
// Инициализация допустимых статусов
|
||||||
|
$statuses = ['active', 'inactive', 'fined', 'decent', 'hided', 'fired'];
|
||||||
|
|
||||||
|
// Инициализация буфера AQL-выражения для инъекции фильтра по статусам (И)
|
||||||
|
$statuses_and = '';
|
||||||
|
|
||||||
|
foreach ($statuses as $name) {
|
||||||
|
// Перебор фильтров статусов (И)
|
||||||
|
|
||||||
|
// Инициализация значения (приоритет у cookie) (отсутствие значения или значение 0 вызывают continue)
|
||||||
|
if (empty($value = $_COOKIE["operators_filter_$name"] ?? $this->session->buffer[$_SERVER['INTERFACE']]['operators']['filters'][$name] ?? 0)) continue;
|
||||||
|
|
||||||
|
// Генерация AQL-выражения для инъекции в строку запроса
|
||||||
|
if ($value === '1') $statuses_and .= " && operator.$name == true";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очистка от бинарных операторов сравнения с только одним операндом (крайние)
|
||||||
|
$statuses_and = trim(trim(trim($statuses_and), '&&'));
|
||||||
|
|
||||||
|
// Инициализация буфера AQL-выражения для инъекции фильтра по статусам (ИЛИ)
|
||||||
|
$statuses_or = '';
|
||||||
|
|
||||||
|
foreach ($statuses as $name) {
|
||||||
|
// Перебор фильтров статусов (ИЛИ)
|
||||||
|
|
||||||
|
// Инициализация значения (приоритет у cookie) (отсутствие значения или значение 0 вызывают continue)
|
||||||
|
if (empty($value = $_COOKIE["operators_filter_$name"] ?? $this->session->buffer[$_SERVER['INTERFACE']]['operators']['filters'][$name] ?? 0)) continue;
|
||||||
|
|
||||||
|
// Генерация AQL-выражения для инъекции в строку запроса
|
||||||
|
if ($value === '2') $statuses_or .= " || operator.$name == true";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очистка от бинарных операторов сравнения с только одним операндом (крайние)
|
||||||
|
$statuses_or = trim(trim(trim($statuses_or), '||'));
|
||||||
|
|
||||||
|
// Инициализация буфера с объёдинёнными буферами c AQL-выражениям "И" и "ИЛИ"
|
||||||
|
$statuses_merged = (empty($statuses_and) ? '' : "($statuses_and)") . (empty($statuses_or) ? '' : (empty($statuses_and) ? '' : ' || ') . "($statuses_or)");
|
||||||
|
|
||||||
|
// Инициализация общего буфера с AQL-выражениями
|
||||||
|
$filters = '';
|
||||||
|
|
||||||
|
// Объединение фильров в единую строку с AQL-выражениями для инъекции
|
||||||
|
if (!empty($statuses_merged)) $filters .= empty($filters) ? $statuses_merged : " && ($statuses_merged)";
|
||||||
|
|
||||||
|
// Инициализация данных для генерации HTML-документа с таблицей
|
||||||
|
$this->view->rows = model::list(before: empty($filters) ? null : "FILTER ($filters)", page: (int) $this->session->buffer[$_SERVER['INTERFACE']]['operators']['page']);
|
||||||
|
|
||||||
|
// Запись в cookie (только таким методом можно записать "hostonly: true")
|
||||||
|
setcookie(
|
||||||
|
'operators_page',
|
||||||
|
(string) $this->session->buffer[$_SERVER['INTERFACE']]['operators']['page'],
|
||||||
|
[
|
||||||
|
'expires' => strtotime('+1 hour'),
|
||||||
|
'path' => '/',
|
||||||
|
'secure' => true,
|
||||||
|
'httponly' => false,
|
||||||
|
'samesite' => 'strict'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы
|
||||||
|
$this->view->page = $parameters['page'];
|
||||||
|
|
||||||
|
// Инициализация блока
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'operators.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возврат (провал)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прочитать данные магазинов для <datalist>
|
||||||
|
*
|
||||||
|
* @param array $parameters Параметры запроса
|
||||||
|
*/
|
||||||
|
public function datalist(array $parameters = []): ?string
|
||||||
|
{
|
||||||
|
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'operator')) {
|
||||||
|
// Авторизован аккаунт оператора или магазина
|
||||||
|
|
||||||
|
// Инициализация данных магазинов
|
||||||
|
$this->view->operators = model::read(filter: 'd.status == "active"', amount: 10000, return: '{ id: d.id, director: d.director }');
|
||||||
|
|
||||||
|
// Универсализация
|
||||||
|
if ($this->view->operators instanceof _document) $this->view->operators = [$this->view->operators];
|
||||||
|
|
||||||
|
// Возврат (успех)
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'operators.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возврат (провал)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ namespace mirzaev\ebala\controllers;
|
||||||
// Файлы проекта
|
// Файлы проекта
|
||||||
use mirzaev\ebala\controllers\core,
|
use mirzaev\ebala\controllers\core,
|
||||||
mirzaev\ebala\controllers\traits\errors,
|
mirzaev\ebala\controllers\traits\errors,
|
||||||
|
mirzaev\ebala\models\registry,
|
||||||
mirzaev\ebala\models\worker as model;
|
mirzaev\ebala\models\worker as model;
|
||||||
|
|
||||||
// Библиотека для ArangoDB
|
// Библиотека для ArangoDB
|
||||||
|
@ -142,7 +143,7 @@ final class worker extends core
|
||||||
if (!empty($polysemantic)) $filters .= empty($filters) ? $polysemantic : " && $polysemantic";
|
if (!empty($polysemantic)) $filters .= empty($filters) ? $polysemantic : " && $polysemantic";
|
||||||
|
|
||||||
// Инициализация данных для генерации HTML-документа с таблицей
|
// Инициализация данных для генерации HTML-документа с таблицей
|
||||||
$this->view->rows = model::list(before: empty($filters) ? null : "FILTER ($filters)", page: (int) $this->session->buffer[$_SERVER['INTERFACE']]['workers']['page']);
|
$this->view->rows = registry::workers(before: empty($filters) ? null : "FILTER ($filters)", page: (int) $this->session->buffer[$_SERVER['INTERFACE']]['workers']['page']);
|
||||||
|
|
||||||
// Запись в cookie (только таким методом можно записать "hostonly: true")
|
// Запись в cookie (только таким методом можно записать "hostonly: true")
|
||||||
setcookie(
|
setcookie(
|
||||||
|
|
|
@ -32,8 +32,7 @@ final class market extends core
|
||||||
*
|
*
|
||||||
* @todo Исправить "markets" на "market"
|
* @todo Исправить "markets" на "market"
|
||||||
*/
|
*/
|
||||||
/* final public const COLLECTION = 'market'; */
|
final public const COLLECTION = 'market';
|
||||||
final public const COLLECTION = 'markets';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Инстанция документа в базе данных
|
* Инстанция документа в базе данных
|
||||||
|
@ -64,61 +63,6 @@ final class market extends core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read markets from ArangoDB
|
|
||||||
*
|
|
||||||
* @param ?string $before Injection of AQL-code before search of market and market
|
|
||||||
* @param int $amount Amount of markets
|
|
||||||
* @param int $page Offset by amount
|
|
||||||
* @param array $errors Errors registry
|
|
||||||
*
|
|
||||||
* @return array Instances from ArangoDB
|
|
||||||
*/
|
|
||||||
public static function list(
|
|
||||||
?string $before = '',
|
|
||||||
int $amount = 100,
|
|
||||||
int $page = 1,
|
|
||||||
string $sort = 'market.created DESC',
|
|
||||||
array &$errors = []
|
|
||||||
): array {
|
|
||||||
try {
|
|
||||||
if (collection::init(static::$arangodb->session, self::COLLECTION)) {
|
|
||||||
// Инициализирована коллекция
|
|
||||||
|
|
||||||
// Search the session data in ArangoDB
|
|
||||||
$markets = collection::search(static::$arangodb->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR market IN %s
|
|
||||||
FILTER market.status != 'deleted'
|
|
||||||
%s
|
|
||||||
SORT %s
|
|
||||||
LIMIT %d, %d
|
|
||||||
RETURN {market}
|
|
||||||
AQL,
|
|
||||||
self::COLLECTION,
|
|
||||||
$before,
|
|
||||||
$sort,
|
|
||||||
--$page <= 0 ? 0 : $amount * $page,
|
|
||||||
$amount
|
|
||||||
));
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return empty($markets) ? [] : (is_array($markets) ? $markets : [$markets]);
|
|
||||||
} else throw new exception('Не удалось инициализировать коллекции');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Write to the errors registry
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit (fail)
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Найти связанный аккаунт
|
* Найти связанный аккаунт
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\ebala\models;
|
||||||
|
|
||||||
|
// Project files
|
||||||
|
use mirzaev\ebala\models\traits\instance,
|
||||||
|
mirzaev\ebala\models\traits\status,
|
||||||
|
mirzaev\ebala\models\account,
|
||||||
|
mirzaev\ebala\models\worker,
|
||||||
|
mirzaev\ebala\models\market;
|
||||||
|
|
||||||
|
// Фреймворк ArangoDB
|
||||||
|
use mirzaev\arangodb\collection;
|
||||||
|
|
||||||
|
// Библиотека для ArangoDB
|
||||||
|
use ArangoDBClient\Document as _document;
|
||||||
|
|
||||||
|
// Встроенные библиотеки
|
||||||
|
use exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модель реестра
|
||||||
|
*
|
||||||
|
* Генерирует HTML-документы из данных аккаунтов (accounts), магазинов (markets) и сотрудников (workers)
|
||||||
|
*
|
||||||
|
* @package mirzaev\ebala\models
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class registry extends core
|
||||||
|
{
|
||||||
|
use instance, status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate workers list
|
||||||
|
*
|
||||||
|
* @param ?string $before Injection of AQL-code before search
|
||||||
|
* @param int $amount Amount of workers
|
||||||
|
* @param int $page Offset by amount
|
||||||
|
* @param array $errors Errors registry
|
||||||
|
*
|
||||||
|
* @return array Instances from ArangoDB
|
||||||
|
*/
|
||||||
|
public static function workers(
|
||||||
|
?string $before = '',
|
||||||
|
int $amount = 100,
|
||||||
|
int $page = 1,
|
||||||
|
string $sort = 'worker.created DESC',
|
||||||
|
array &$errors = []
|
||||||
|
): array {
|
||||||
|
try {
|
||||||
|
if (collection::init(static::$arangodb->session, account::COLLECTION) && collection::init(static::$arangodb->session, worker::COLLECTION)) {
|
||||||
|
// Инициализированы коллекции
|
||||||
|
|
||||||
|
// Search the session data in ArangoDB
|
||||||
|
$workers = collection::search(static::$arangodb->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR account IN %s
|
||||||
|
FILTER account.status != 'deleted'
|
||||||
|
%s
|
||||||
|
LET worker = (FOR worker IN OUTBOUND account._id account_edge_worker FILTER worker.status != 'deleted' LIMIT 1 SORT worker.created DESC RETURN worker)[0]
|
||||||
|
FILTER worker != null
|
||||||
|
SORT %s
|
||||||
|
LIMIT %d, %d
|
||||||
|
RETURN {account, worker}
|
||||||
|
AQL,
|
||||||
|
account::COLLECTION,
|
||||||
|
$before,
|
||||||
|
$sort,
|
||||||
|
--$page <= 0 ? 0 : $amount * $page,
|
||||||
|
$amount
|
||||||
|
));
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return empty($workers) ? [] : (is_array($workers) ? $workers : [$workers]);
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекции');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Write to the errors registry
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (fail)
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate markets list
|
||||||
|
*
|
||||||
|
* @param ?string $before Injection of AQL-code before search
|
||||||
|
* @param int $amount Amount of markets
|
||||||
|
* @param int $page Offset by amount
|
||||||
|
* @param array $errors Errors registry
|
||||||
|
*
|
||||||
|
* @return array Instances from ArangoDB
|
||||||
|
*/
|
||||||
|
public static function markets(
|
||||||
|
?string $before = '',
|
||||||
|
int $amount = 100,
|
||||||
|
int $page = 1,
|
||||||
|
string $sort = 'market.created DESC',
|
||||||
|
array &$errors = []
|
||||||
|
): array {
|
||||||
|
try {
|
||||||
|
if (collection::init(static::$arangodb->session, account::COLLECTION) && collection::init(static::$arangodb->session, market::COLLECTION)) {
|
||||||
|
// Инициализированы коллекции
|
||||||
|
|
||||||
|
// Search the session data in ArangoDB
|
||||||
|
$markets = collection::search(static::$arangodb->session, sprintf(
|
||||||
|
<<<AQL
|
||||||
|
FOR account IN %s
|
||||||
|
FILTER account.status != 'deleted'
|
||||||
|
%s
|
||||||
|
LET market = (FOR market IN OUTBOUND account._id account_edge_market FILTER market.status != 'deleted' LIMIT 1 SORT market.created DESC RETURN market)[0]
|
||||||
|
FILTER market != null
|
||||||
|
SORT %s
|
||||||
|
LIMIT %d, %d
|
||||||
|
RETURN {account, market}
|
||||||
|
AQL,
|
||||||
|
account::COLLECTION,
|
||||||
|
$before,
|
||||||
|
$sort,
|
||||||
|
--$page <= 0 ? 0 : $amount * $page,
|
||||||
|
$amount
|
||||||
|
));
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return empty($markets) ? [] : (is_array($markets) ? $markets : [$markets]);
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекции');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Write to the errors registry
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (fail)
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -149,7 +149,7 @@ final class task extends core
|
||||||
self::COLLECTION,
|
self::COLLECTION,
|
||||||
$before,
|
$before,
|
||||||
'worker',
|
'worker',
|
||||||
'markets',
|
'market',
|
||||||
$after,
|
$after,
|
||||||
$sort,
|
$sort,
|
||||||
--$page <= 0 ? 0 : $amount * $page,
|
--$page <= 0 ? 0 : $amount * $page,
|
||||||
|
|
|
@ -61,62 +61,6 @@ final class worker extends core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read workers from ArangoDB
|
|
||||||
*
|
|
||||||
* @param ?string $before Injection of AQL-code before search of worker and market
|
|
||||||
* @param int $amount Amount of workers
|
|
||||||
* @param int $page Offset by amount
|
|
||||||
* @param array $errors Errors registry
|
|
||||||
*
|
|
||||||
* @return array Instances from ArangoDB
|
|
||||||
*/
|
|
||||||
public static function list(
|
|
||||||
?string $before = '',
|
|
||||||
int $amount = 100,
|
|
||||||
int $page = 1,
|
|
||||||
string $sort = 'worker.created DESC',
|
|
||||||
array &$errors = []
|
|
||||||
): array {
|
|
||||||
try {
|
|
||||||
if (collection::init(static::$arangodb->session, self::COLLECTION)) {
|
|
||||||
// Инициализирована коллекция
|
|
||||||
|
|
||||||
// Search the session data in ArangoDB
|
|
||||||
$workers = collection::search(static::$arangodb->session, sprintf(
|
|
||||||
<<<AQL
|
|
||||||
FOR worker IN %s
|
|
||||||
FILTER worker.status != 'deleted'
|
|
||||||
%s
|
|
||||||
SORT %s
|
|
||||||
LIMIT %d, %d
|
|
||||||
RETURN {worker}
|
|
||||||
AQL,
|
|
||||||
self::COLLECTION,
|
|
||||||
$before,
|
|
||||||
$sort,
|
|
||||||
--$page <= 0 ? 0 : $amount * $page,
|
|
||||||
$amount
|
|
||||||
));
|
|
||||||
|
|
||||||
// Exit (success)
|
|
||||||
return empty($workers) ? [] : (is_array($workers) ? $workers : [$workers]);
|
|
||||||
} else throw new exception('Не удалось инициализировать коллекции');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Write to the errors registry
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit (fail)
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Записать
|
* Записать
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,6 +50,10 @@ section.panel.list > form.row.menu.stretched > label > input[type="search"] {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section.panel.list > form.row.menu.stretched > label > button {
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
section.panel.list > form.row.menu > label > input {
|
section.panel.list > form.row.menu > label > input {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
section#markets.panel.list
|
||||||
|
> div.row:nth-of-type(1)
|
||||||
|
> span[data-column="end"]
|
||||||
|
> i.home {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list
|
||||||
|
> div.row
|
||||||
|
> span:is(
|
||||||
|
[data-column="id"],
|
||||||
|
[data-column="director"],
|
||||||
|
[data-column="address"],
|
||||||
|
[data-column="type"],
|
||||||
|
[data-column="commentary"],
|
||||||
|
[data-column="status"],
|
||||||
|
) {
|
||||||
|
min-width: 220px;
|
||||||
|
width: 220px;
|
||||||
|
display: ruby;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="id"] {
|
||||||
|
min-width: 67px;
|
||||||
|
width: 67px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row:nth-of-type(1) > span[data-column="id"] {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="director"] {
|
||||||
|
min-width: 400px;
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="address"] {
|
||||||
|
min-width: 450px;
|
||||||
|
width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row:not(:nth-of-type(1)) > span[data-column="type"] {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="type"] {
|
||||||
|
min-width: 80px;
|
||||||
|
width: 80px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="commentary"] {
|
||||||
|
min-width: unset;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#markets.panel.list > div.row > span[data-column="status"] {
|
||||||
|
min-width: 100px;
|
||||||
|
width: 100px;
|
||||||
|
font-size: small;
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
section#operators.panel.list
|
||||||
|
> div.row:nth-of-type(1)
|
||||||
|
> span[data-column="end"]
|
||||||
|
> i.home {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list
|
||||||
|
> div.row
|
||||||
|
> span:is(
|
||||||
|
[data-column="id"],
|
||||||
|
[data-column="name"],
|
||||||
|
[data-column="birth"],
|
||||||
|
[data-column="number"],
|
||||||
|
[data-column="passport"],
|
||||||
|
[data-column="department"],
|
||||||
|
[data-column="city"],
|
||||||
|
[data-column="address"],
|
||||||
|
[data-column="requisites"],
|
||||||
|
[data-column="tax"],
|
||||||
|
[data-column="commentary"],
|
||||||
|
[data-column="status"],
|
||||||
|
) {
|
||||||
|
min-width: 220px;
|
||||||
|
width: 220px;
|
||||||
|
display: ruby;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="id"] {
|
||||||
|
min-width: 67px;
|
||||||
|
width: 67px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row:nth-of-type(1) > span[data-column="id"] {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="name"] {
|
||||||
|
min-width: 200px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="birth"] {
|
||||||
|
min-width: 80px;
|
||||||
|
width: 80px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="number"] {
|
||||||
|
min-width: 120px;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="passport"] {
|
||||||
|
min-width: 150px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="city"] {
|
||||||
|
min-width: 90px;
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="address"] {
|
||||||
|
min-width: 180px;
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="requisites"] {
|
||||||
|
min-width: 180px;
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="tax"] {
|
||||||
|
min-width: 55px;
|
||||||
|
width: 55px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="commentary"] {
|
||||||
|
min-width: unset;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#operators.panel.list > div.row > span[data-column="status"] {
|
||||||
|
min-width: 100px;
|
||||||
|
width: 100px;
|
||||||
|
font-size: small;
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -40,8 +40,8 @@ section#workers.panel.list > div.row:nth-of-type(1) > span[data-column="id"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
section#workers.panel.list > div.row > span[data-column="name"] {
|
section#workers.panel.list > div.row > span[data-column="name"] {
|
||||||
min-width: 200px;
|
min-width: 180px;
|
||||||
width: 200px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
section#workers.panel.list > div.row > span[data-column="birth"] {
|
section#workers.panel.list > div.row > span[data-column="birth"] {
|
||||||
|
@ -91,3 +91,7 @@ section#workers.panel.list > div.row > span[data-column="status"] {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section#workers.panel.list > div.row:not(:nth-of-type(1)) > span[data-column="status"] {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
|
@ -35,10 +35,16 @@ $router = new router;
|
||||||
// Запись маршрутов
|
// Запись маршрутов
|
||||||
$router->write('/', 'index', 'index', 'GET');
|
$router->write('/', 'index', 'index', 'GET');
|
||||||
$router->write('/', 'index', 'index', 'POST');
|
$router->write('/', 'index', 'index', 'POST');
|
||||||
|
$router->write('/worker/$worker/read', 'task', 'worker', 'POST');
|
||||||
$router->write('/workers', 'worker', 'index', 'GET');
|
$router->write('/workers', 'worker', 'index', 'GET');
|
||||||
$router->write('/workers', 'worker', 'index', 'POST');
|
$router->write('/workers', 'worker', 'index', 'POST');
|
||||||
|
$router->write('/workers/read', 'worker', 'read', 'POST');
|
||||||
|
$router->write('/workers/list', 'worker', 'datalist', 'POST');
|
||||||
|
$router->write('/market/$market/read', 'task', 'market', 'POST');
|
||||||
$router->write('/markets', 'market', 'index', 'GET');
|
$router->write('/markets', 'market', 'index', 'GET');
|
||||||
$router->write('/markets', 'market', 'index', 'POST');
|
$router->write('/markets', 'market', 'index', 'POST');
|
||||||
|
$router->write('/markets/read', 'market', 'read', 'POST');
|
||||||
|
$router->write('/markets/list', 'market', 'datalist', 'POST');
|
||||||
$router->write('/operators', 'operator', 'index', 'GET');
|
$router->write('/operators', 'operator', 'index', 'GET');
|
||||||
$router->write('/operators', 'operator', 'index', 'POST');
|
$router->write('/operators', 'operator', 'index', 'POST');
|
||||||
$router->write('/administrators', 'administrators', 'index', 'GET');
|
$router->write('/administrators', 'administrators', 'index', 'GET');
|
||||||
|
@ -70,11 +76,6 @@ $router->write('/task/$task/description', 'task', 'description', 'POST');
|
||||||
$router->write('/task/$task/commentary', 'task', 'commentary', 'POST');
|
$router->write('/task/$task/commentary', 'task', 'commentary', 'POST');
|
||||||
$router->write('/task/$task/worker/update', 'task', 'update', 'POST');
|
$router->write('/task/$task/worker/update', 'task', 'update', 'POST');
|
||||||
$router->write('/task/$task/market/update', 'task', 'update', 'POST');
|
$router->write('/task/$task/market/update', 'task', 'update', 'POST');
|
||||||
$router->write('/worker/$worker/read', 'task', 'worker', 'POST');
|
|
||||||
$router->write('/workers/read', 'worker', 'read', 'POST');
|
|
||||||
$router->write('/workers/list', 'worker', 'datalist', 'POST');
|
|
||||||
$router->write('/market/$market/read', 'task', 'market', 'POST');
|
|
||||||
$router->write('/markets/list', 'market', 'datalist', 'POST');
|
|
||||||
$router->write('/elements/menu', 'index', 'menu', 'POST');
|
$router->write('/elements/menu', 'index', 'menu', 'POST');
|
||||||
|
|
||||||
// Инициализация ядра
|
// Инициализация ядра
|
||||||
|
|
|
@ -77,6 +77,13 @@ if (typeof window.loader !== "function") {
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
// Write path in history
|
||||||
|
history.pushState(this.storage, "/administrators", "/administrators");
|
||||||
|
|
||||||
|
// Write path to the current directory buffer
|
||||||
|
core.page = 'administrators';
|
||||||
|
|
||||||
|
// Write content in document
|
||||||
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -95,6 +102,13 @@ if (typeof window.loader !== "function") {
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
// Write path in history
|
||||||
|
history.pushState(this.storage, "/operators", "/operators");
|
||||||
|
|
||||||
|
// Write path to the current directory buffer
|
||||||
|
core.page = 'operators';
|
||||||
|
|
||||||
|
// Write content in document
|
||||||
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -112,6 +126,13 @@ if (typeof window.loader !== "function") {
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
// Write path in history
|
||||||
|
history.pushState(this.storage, "/markets", "/markets");
|
||||||
|
|
||||||
|
// Write path to the current directory buffer
|
||||||
|
core.page = 'markets';
|
||||||
|
|
||||||
|
// Write content in document
|
||||||
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -176,6 +197,13 @@ if (typeof window.loader !== "function") {
|
||||||
})
|
})
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
// Write path in history
|
||||||
|
history.pushState(this.storage, "/account", "/account");
|
||||||
|
|
||||||
|
// Write path to the current directory buffer
|
||||||
|
core.page = 'account';
|
||||||
|
|
||||||
|
// Write content in document
|
||||||
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
document.body.getElementsByTagName("main")[0].innerHTML = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,7 @@ and key != 'transfer_to_sheets') -%}
|
||||||
data.value|date('Y.m.d h:i:s') }}</span>
|
data.value|date('Y.m.d h:i:s') }}</span>
|
||||||
{% elseif key == 'hiring' or key == 'birth' %}
|
{% elseif key == 'hiring' or key == 'birth' %}
|
||||||
<span id="{{ worker.id.value }}_{{ key }}"><b>{{ data.label }}:</b>{{ data.value|date('Y.m.d') }}</span>
|
<span id="{{ worker.id.value }}_{{ key }}"><b>{{ data.label }}:</b>{{ data.value|date('Y.m.d') }}</span>
|
||||||
{% elseif key == 'phone' or key == 'number' %}
|
{% elseif key == 'number' %}
|
||||||
<span id="{{ worker.id.value }}_number"><b>{{ data.label }}:</b><a href="tel:{{ data.value }}" title="Позвонить">{{
|
<span id="{{ worker.id.value }}_number"><b>{{ data.label }}:</b><a href="tel:{{ data.value }}" title="Позвонить">{{
|
||||||
data.value }}</a></span>
|
data.value }}</a></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% if page != null %}<!-- PAGE #{{ page }} -->{% endif %}
|
||||||
|
{% for row in rows %}
|
||||||
|
<div id="{{ row.market._key }}" class="row {{ row.market.status }}">
|
||||||
|
<span data-column="id" title="{{ row.market.id }}" onclick="markets.market.popup(this.parentElement)">{{
|
||||||
|
row.market.id }}</span>
|
||||||
|
<span data-column="director" title="{{ row.market.director }}" onclick="markets.market.popup(this.parentElement)">{{
|
||||||
|
row.market.director }}</span>
|
||||||
|
<span data-column="address" title="{{ row.market.city }} {{ row.market.district }} {{ row.market.address }}"
|
||||||
|
onclick="markets.market.popup(this.parentElement)">{{ row.market.city }} {{ row.market.district }} {{
|
||||||
|
row.market.address }}</span>
|
||||||
|
<span data-column="type" onclick="markets.market.popup(this.parentElement)">{{ row.market.type }}</span>
|
||||||
|
<span data-column="commentary" title="{{ row.market.commentary }}"
|
||||||
|
onclick="markets.commentary.popup(this.parentElement)">{{ row.market.commentary }}</span>
|
||||||
|
<span data-column="status" title="Непрочитанные сообщения" onclick="markets.status(this.parentElement)">{{
|
||||||
|
row.market.status }}</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{% if page != null %}<!-- PAGE #{{ page }} -->{% endif %}
|
||||||
|
{% for row in rows %}
|
||||||
|
<div id="{{ row.operator._key }}" class="row {{ row.operator.status }}">
|
||||||
|
<span data-column="id" title="{{ row.operator.id }}" onclick="operators.operator.popup(this.parentElement)">{{
|
||||||
|
row.operator.id }}</span>
|
||||||
|
<span data-column="name" title="{{ row.operator.name }}" onclick="operators.operator.popup(this.parentElement)">{{
|
||||||
|
row.operator.name }}</span>
|
||||||
|
<span data-column="birth" onclick="operators.operator.popup(this.parentElement)">{{ row.operator.birth }}</span>
|
||||||
|
<span data-column="number" onclick="operators.operator.popup(this.parentElement)">{{ row.operator.number }}</span>
|
||||||
|
<span data-column="passport" title="{{ row.operator.passport }} {{ row.operator.department }} {{ row.operator.issued }}"
|
||||||
|
onclick="operators.operator.popup(this.parentElement)">{{ row.operator.passport }} {{ row.operator.department }} {{
|
||||||
|
row.operator.issued }}</span>
|
||||||
|
<span data-column="address" title="{{ row.operator.city }} {{ row.operator.district }} {{ row.operator.address }}"
|
||||||
|
onclick="operators.operator.popup(this.parentElement)">{{ row.operator.city }} {{ row.operator.district }} {{
|
||||||
|
row.operator.address }}</span>
|
||||||
|
<span data-column="tax" onclick="operators.operator.popup(this.parentElement)">{{ row.operator.tax }}</span>
|
||||||
|
<span data-column="requisites" onclick="operators.operator.popup(this.parentElement)">{{ row.operator.requisites }} {{
|
||||||
|
row.operator.payment }}</span>
|
||||||
|
<span data-column="commentary" title="{{ row.operator.commentary }}"
|
||||||
|
onclick="operators.commentary.popup(this.parentElement)">{{ row.operator.commentary }}</span>
|
||||||
|
<span data-column="status" title="Непрочитанные сообщения" onclick="operators.status(this.parentElement)">{{
|
||||||
|
row.operator.status }}</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
|
@ -3,10 +3,9 @@
|
||||||
<div id="{{ row.worker._key }}" class="row {{ row.worker.status }}">
|
<div id="{{ row.worker._key }}" class="row {{ row.worker.status }}">
|
||||||
<span data-column="id" title="{{ row.worker.id }}" onclick="workers.worker.popup(this.parentElement)">{{
|
<span data-column="id" title="{{ row.worker.id }}" onclick="workers.worker.popup(this.parentElement)">{{
|
||||||
row.worker.id }}</span>
|
row.worker.id }}</span>
|
||||||
<span data-column="name" title="{{ row.worker.name }}" onclick="workers.worker.popup(this.parentElement)">{{
|
<span data-column="name" title="{% if row.worker.name.first is not empty %}{{ row.worker.name.first }}{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last }}{% endif %}" onclick="workers.worker.popup(this.parentElement)">{% if row.worker.name.first is not empty %}{{ row.worker.name.first|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}</span>
|
||||||
row.worker.name }}</span>
|
|
||||||
<span data-column="birth" onclick="workers.worker.popup(this.parentElement)">{{ row.worker.birth }}</span>
|
<span data-column="birth" onclick="workers.worker.popup(this.parentElement)">{{ row.worker.birth }}</span>
|
||||||
<span data-column="number" onclick="workers.worker.popup(this.parentElement)">{{ row.worker.number }}</span>
|
<span data-column="worker" onclick="workers.worker.popup(this.parentElement)"><a href="tel:{{ row.worker.number }}" title="Позвонить">{{ row.worker.number }}</a></span>
|
||||||
<span data-column="passport" title="{{ row.worker.passport }} {{ row.worker.department }} {{ row.worker.issued }}"
|
<span data-column="passport" title="{{ row.worker.passport }} {{ row.worker.department }} {{ row.worker.issued }}"
|
||||||
onclick="workers.worker.popup(this.parentElement)">{{ row.worker.passport }} {{ row.worker.department }} {{
|
onclick="workers.worker.popup(this.parentElement)">{{ row.worker.passport }} {{ row.worker.department }} {{
|
||||||
row.worker.issued }}</span>
|
row.worker.issued }}</span>
|
||||||
|
@ -18,7 +17,7 @@
|
||||||
row.worker.payment }}</span>
|
row.worker.payment }}</span>
|
||||||
<span data-column="commentary" title="{{ row.worker.commentary }}"
|
<span data-column="commentary" title="{{ row.worker.commentary }}"
|
||||||
onclick="workers.commentary.popup(this.parentElement)">{{ row.worker.commentary }}</span>
|
onclick="workers.commentary.popup(this.parentElement)">{{ row.worker.commentary }}</span>
|
||||||
<span data-column="status" title="Непрочитанные сообщения" onclick="workers.status(this.parentElement)">{{
|
<span data-column="status" onclick="workers.status(this.parentElement)">{{
|
||||||
row.worker.status ?? 'active' }}</span>
|
row.worker.status }}</span>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -23,53 +23,27 @@
|
||||||
</form>
|
</form>
|
||||||
<form id="filters" class="row menu stretched" onsubmit="return false">
|
<form id="filters" class="row menu stretched" onsubmit="return false">
|
||||||
<label for="filters">
|
<label for="filters">
|
||||||
<div class="range small">
|
|
||||||
<input id="ratings" class="sand" type="range" value="0" min="0" max="5" step="1"
|
|
||||||
oninput="this.nextElementSibling.innerText = this.value; this.nextElementSibling.style.setProperty('--left', (((this.value / 5) * 116) + 12) + 'px');"
|
|
||||||
onchange="markets.filter('rating', this.value); markets.reinit();" title="Минимальный рейтинг" />
|
|
||||||
<i style="--left: 0;" class="value unselectable">0</i>
|
|
||||||
<script>
|
|
||||||
// Initialization of input-event
|
|
||||||
document.getElementById('ratings').oninput();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
<button class="{{ active ?? 'earth' }}" onclick="markets.filter('active', null, this); markets.reinit()" {% if
|
<button class="{{ active ?? 'earth' }}" onclick="markets.filter('active', null, this); markets.reinit()" {% if
|
||||||
active=='sand' %}title="... и активные" {% elseif active=='river' %}title="... или активные" {% endif
|
active=='sand' %}title="... и активные" {% elseif active=='river' %}title="... или активные" {% endif
|
||||||
%}>Активный</button>
|
%}>Активный</button>
|
||||||
<button class="{{ inactive ?? 'earth' }}" onclick="markets.filter('inactive', null, this); markets.reinit()" {% if
|
<button class="{{ inactive ?? 'earth' }}" onclick="markets.filter('inactive', null, this); markets.reinit()" {% if
|
||||||
inactive=='sand' %}title="... и неактивные" {% elseif inactive=='river' %}title="... или неактивные" {% endif
|
inactive=='sand' %}title="... и неактивные" {% elseif inactive=='river' %}title="... или неактивные" {% endif
|
||||||
%}>Неактивный</button>
|
%}>Неактивный</button>
|
||||||
<button class="{{ fined ?? 'earth' }}" onclick="markets.filter('fined', null, this); markets.reinit()" {% if
|
|
||||||
fined=='sand' %}title="... и имеющие штрафы" {% elseif fined=='river' %}title="... или имеющие штрафы" {% endif
|
|
||||||
%}>Штраф</button>
|
|
||||||
<button class="{{ decent ?? 'earth' }}" onclick="markets.filter('decent', null, this); markets.reinit()" {% if
|
|
||||||
decent=='sand' %}title="... и не имеющие штрафы" {% elseif decent=='river' %}title="... или не имеющие штрафы"
|
|
||||||
{% endif %}>Нет штрафов</button>
|
|
||||||
<button class="{{ hided ?? 'earth' }}" onclick="markets.filter('hided', null, this); markets.reinit()" {% if
|
|
||||||
hided=='sand' %}title="... и скрытые" {% elseif hided=='river' %}title="... или скрытые" {% endif
|
|
||||||
%}>Скрыт</button>
|
|
||||||
<button class="{{ fired ?? 'earth' }}" onclick="markets.filter('fired', null, this); markets.reinit()" {% if
|
|
||||||
fired=='sand' %}title="... и уволенные" {% elseif fired=='river' %}title="... или уволенные" {% endif
|
|
||||||
%}>Уволен</button>
|
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
<form class="row menu wide stretched" onsubmit="return false">
|
<form class="row menu wide stretched" onsubmit="return false">
|
||||||
<label class="solid">
|
<label class="solid">
|
||||||
<i class="icon search"></i>
|
<i class="icon search"></i>
|
||||||
<input class="clue merged right" type="search" name="search" id="search"
|
<input class="clue merged right" type="search" name="search" id="search"
|
||||||
placeholder="Глобальный поиск по сотрудникам" />
|
placeholder="Глобальный поиск по магазинам" />
|
||||||
<button class="sea merged left" onclick="markets.search(this.previousSiblingElement, this)">Поиск</button>
|
<button class="sea merged left" onclick="markets.search(this.previousSiblingElement, this)">Поиск</button>
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
<div id="title" class="row unselectable">
|
<div id="title" class="row unselectable">
|
||||||
<span data-column="id" class="button" title="Идентификатор"><i class="icon bold user"></i></span>
|
<span data-column="id" class="button" title="Идентификатор"><i class="icon bold user"></i></span>
|
||||||
<span data-column="name" class="button">ФИО</span>
|
<span data-column="director" class="button">Директор</span>
|
||||||
<span data-column="birth" class="button">Дата</span>
|
|
||||||
<span data-column="number" class="button">Номер</span>
|
|
||||||
<span data-column="passport" class="button">Паспорт</span>
|
|
||||||
<span data-column="address" class="button">Адрес</span>
|
<span data-column="address" class="button">Адрес</span>
|
||||||
<span data-column="tax" class="button">ИНН</span>
|
<span data-column="type" class="button">Тип</span>
|
||||||
<span data-column="requisites" class="button">Реквизиты</span>
|
|
||||||
<span data-column="commentary" class="button">Комментарий</span>
|
<span data-column="commentary" class="button">Комментарий</span>
|
||||||
<span data-column="status" class="button">Статус</span>
|
<span data-column="status" class="button">Статус</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,7 +53,7 @@
|
||||||
// Не выполнялся скрипт
|
// Не выполнялся скрипт
|
||||||
|
|
||||||
document.addEventListener('markets.initialized', (e) => {
|
document.addEventListener('markets.initialized', (e) => {
|
||||||
// Инициализированы сотрудники
|
// Инициализированы магазины
|
||||||
|
|
||||||
// Инициализация допустимой страницы для выполнения
|
// Инициализация допустимой страницы для выполнения
|
||||||
e.detail.markets.page = 'markets';
|
e.detail.markets.page = 'markets';
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
{% extends('index.html') %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/list.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/pages/operators.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/user.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/user_add.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/work_alt.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/home.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/timer.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/shopping_cart.css">
|
||||||
|
<link type="text/css" rel="stylesheet" data-reinitializer-once="true" href="/css/icons/search.css">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<section id="operators" class="panel medium list">
|
||||||
|
<form id="actions" class="row menu separated" onsubmit="return false">
|
||||||
|
<label for="actions">
|
||||||
|
{% if account.type == 'administrator' or account.type == 'operator' or account.type == 'operator' %}
|
||||||
|
<button class="grass" onclick="operators.create()">Создать</button>
|
||||||
|
{% endif %}
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
<form id="filters" class="row menu stretched" onsubmit="return false">
|
||||||
|
<label for="filters">
|
||||||
|
<button class="{{ active ?? 'earth' }}" onclick="operators.filter('active', null, this); operators.reinit()" {% if
|
||||||
|
active=='sand' %}title="... и активные" {% elseif active=='river' %}title="... или активные" {% endif
|
||||||
|
%}>Активный</button>
|
||||||
|
<button class="{{ inactive ?? 'earth' }}" onclick="operators.filter('inactive', null, this); operators.reinit()" {% if
|
||||||
|
inactive=='sand' %}title="... и неактивные" {% elseif inactive=='river' %}title="... или неактивные" {% endif
|
||||||
|
%}>Неактивный</button>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
<form class="row menu wide stretched" onsubmit="return false">
|
||||||
|
<label class="solid">
|
||||||
|
<i class="icon search"></i>
|
||||||
|
<input class="clue merged right" type="search" name="search" id="search"
|
||||||
|
placeholder="Глобальный поиск по операторам" />
|
||||||
|
<button class="sea merged left" onclick="operators.search(this.previousSiblingElement, this)">Поиск</button>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
<div id="title" class="row unselectable">
|
||||||
|
<span data-column="id" class="button" title="Идентификатор"><i class="icon bold user"></i></span>
|
||||||
|
<span data-column="name" class="button">ФИО</span>
|
||||||
|
<span data-column="number" class="button">Адрес</span>
|
||||||
|
<span data-column="mail" class="button">Тип</span>
|
||||||
|
<span data-column="commentary" class="button">Комментарий</span>
|
||||||
|
<span data-column="status" class="button">Статус</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<script data-reinitializer-once="true">
|
||||||
|
if (typeof window.operators_main_initialized === 'undefined') {
|
||||||
|
// Не выполнялся скрипт
|
||||||
|
|
||||||
|
document.addEventListener('operators.initialized', (e) => {
|
||||||
|
// Инициализированы операторы
|
||||||
|
|
||||||
|
// Инициализация допустимой страницы для выполнения
|
||||||
|
e.detail.operators.page = 'operators';
|
||||||
|
|
||||||
|
// Инициализация страниц
|
||||||
|
e.detail.operators.init();
|
||||||
|
|
||||||
|
// Блокировка от повторного выполнения
|
||||||
|
window.operators_main_initialized = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script data-reinitializer-once="true">
|
||||||
|
if (typeof window.operators_scroll_initialized === 'undefined') {
|
||||||
|
// Не выполнялся скрипт
|
||||||
|
|
||||||
|
window.onscroll = function(e) {
|
||||||
|
// Инициализация чтения новых задач при достижения конца страницы
|
||||||
|
|
||||||
|
if (core.page === 'operators') {
|
||||||
|
// Инициализирована требуемая для выполнения страница
|
||||||
|
|
||||||
|
if ((window.innerHeight + Math.round(window.scrollY)) >= document.body.offsetHeight) operators.read();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Блокировка от повторного выполнения
|
||||||
|
window.operators_scroll_initialized = true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
<script type="text/javascript" data-reinitializer-once="true" src="/js/imask-7.1.0-alpha.js" defer></script>
|
||||||
|
<script type="text/javascript" src="/js/operators.js" defer></script>
|
||||||
|
{% endblock %}
|
Reference in New Issue