fix #64, fix #87, fix #72, fix #86, fix #77, fix #71, fix #91, fix #88

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2024-03-19 00:45:47 +07:00
parent 4c6e5cdd1d
commit 26eced8fed
22 changed files with 1508 additions and 379 deletions

View File

@ -268,4 +268,106 @@ final class account extends core
// Возврат (провал) // Возврат (провал)
return null; return null;
} }
/**
* Пометить заблокированным
*
* @param array $parameters Параметры запроса
*/
public function ban(array $parameters = []): ?string
{
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных аккаунта
$account = model::read('d._key == "' . $parameters['id'] . '"');
if (!empty($account)) {
// Найден аккаунт
// Блокирование
$account->active = false;
$account->banned = true;
if (_core::update($account)) {
// Записаны данные аккаунта
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode([
'banned' => true,
'errors' => self::parse_only_text($this->errors)
]);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Не удалось найти аккаунт');
}
// Возврат (провал)
return null;
}
/**
* Снять пометку заблокированного (разблокировать)
*
* @param array $parameters Параметры запроса
*/
public function unban(array $parameters = []): ?string
{
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных аккаунта
$account = model::read('d._key == "' . $parameters['id'] . '"');
if (!empty($account)) {
// Найден аккаунт
// Блокирование
$account->active = true;
$account->banned = false;
if (_core::update($account)) {
// Записаны данные аккаунта
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode([
'unbanned' => true,
'errors' => self::parse_only_text($this->errors)
]);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Не удалось найти аккаунт');
}
// Возврат (провал)
return null;
}
} }

View File

@ -14,6 +14,9 @@ use mirzaev\ebala\views\templater,
// Фреймворк PHP // Фреймворк PHP
use mirzaev\minimal\controller; use mirzaev\minimal\controller;
// Встроенные библиотеки
use exception;
/** /**
* Ядро контроллеров * Ядро контроллеров
* *

View File

@ -31,6 +31,11 @@ final class task extends core
{ {
use errors; use errors;
/**
* Типы работ
*/
final public const WORKS = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
/** /**
* Создать * Создать
* *
@ -477,7 +482,7 @@ final class task extends core
]; ];
if ($account->type === 'worker') { if ($account->type === 'worker') {
// Оператор или администратор // Сотрудник
foreach ($link->task['chats']['worker'] ?? [] as $message) { foreach ($link->task['chats']['worker'] ?? [] as $message) {
// Перебор сообщений из чата: СОТРУДНИК <-> ОПЕРАТОР // Перебор сообщений из чата: СОТРУДНИК <-> ОПЕРАТОР
@ -486,7 +491,7 @@ final class task extends core
if (!array_key_exists((string) $account->getKey(), $message['readed'] ?? [])) ++$generated['chat']['unreaded']; if (!array_key_exists((string) $account->getKey(), $message['readed'] ?? [])) ++$generated['chat']['unreaded'];
} }
} else if ($account->type === 'market') { } else if ($account->type === 'market') {
// Оператор или администратор // Магазин
foreach ($link->task['chats']['market'] ?? [] as $message) { foreach ($link->task['chats']['market'] ?? [] as $message) {
// Перебор сообщений из чата: МАГАЗИН <-> ОПЕРАТОР // Перебор сообщений из чата: МАГАЗИН <-> ОПЕРАТОР
@ -1767,7 +1772,10 @@ final class task extends core
public function works(array $parameters = []): void public function works(array $parameters = []): void
{ {
try { try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) { if (!empty($parameters['task'])) {
// Запрошены данные работ по заявке
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market' || $this->account->type === 'worker')) {
// Авторизован аккаунт администратора, оператора или магазина // Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных // Инициализация данных
@ -1776,8 +1784,16 @@ final class task extends core
if ($this->view->task instanceof _document) { if ($this->view->task instanceof _document) {
// Найдена заявка // Найдена заявка
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $this->view->task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этой заявки');
// Заявка не принадлежит запросившему сотруднику?
if ($this->account->type === 'worker' and $this->view->task->worker !== account::worker($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этой заявки');
// Инициализация списка работ // Инициализация списка работ
$this->view->works = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал']; $this->view->works = static::WORKS;
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора // Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
foreach ($this->view->works as $work) if ($this->view->task->work === $work) $this->view->exist = true; foreach ($this->view->works as $work) if ($this->view->task->work === $work) $this->view->exist = true;
@ -1806,6 +1822,85 @@ final class task extends core
flush(); flush();
} else throw new exception('Не найдена заявка'); } else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы'); } else throw new exception('Вы не авторизованы');
} else if (!empty($parameters['worker'])) {
// Запрошены данные работ по сотруднику
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'worker')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$this->view->worker = worker::read('d.id == "' . $parameters['worker'] . '"');
if ($this->view->worker instanceof _document) {
// Найден сотрудник
// Сотрудник не принадлежит запросившему аккаунту?
if ($this->account->type === 'worker' and $this->view->worker->id !== account::worker($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этого сотрудника');
// Инициализация списка работ
$this->view->works = static::WORKS;
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
foreach ($this->view->works as $work) if ($this->view->worker->work === $work) $this->view->exist = true;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'works' => $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'works.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найден сотрудник');
} else throw new exception('Вы не авторизованы');
} else {
// Запрошен список работ
if ($this->account->status()) {
// Авторизован аккаунт
// Инициализация списка работ
$this->view->works = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'works' => $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'works.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Вы не авторизованы');
}
} catch (exception $e) { } catch (exception $e) {
// Запись в реестр ошибок // Запись в реестр ошибок
$this->errors[] = [ $this->errors[] = [

View File

@ -29,6 +29,11 @@ final class worker extends core
{ {
use errors; use errors;
/**
* Типы работ
*/
final public const WORKS = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
/** /**
* Главная страница * Главная страница
* *
@ -261,6 +266,7 @@ final class worker extends core
if (!empty($parameters['requisites']) && $parameters['worker_requisites'][-1] === '.') $parameters['worker_requisites'] .= '.'; if (!empty($parameters['requisites']) && $parameters['worker_requisites'][-1] === '.') $parameters['worker_requisites'] .= '.';
if (!empty($parameters['worker_birth'])) $parameters['worker_birth'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_birth'])->getTimestamp(); if (!empty($parameters['worker_birth'])) $parameters['worker_birth'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_birth'])->getTimestamp();
if (!empty($parameters['worker_issued'])) $parameters['worker_issued'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_issued'])->getTimestamp(); if (!empty($parameters['worker_issued'])) $parameters['worker_issued'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_issued'])->getTimestamp();
if (!empty($parameters['work'])) $parameters['work'] = in_array($parameters['work'], static::WORKS) ? $parameters['work'] : static::WORKS[0];
if (!empty($parameters['worker_hiring'])) $parameters['worker_hiring'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_hiring'])->getTimestamp(); if (!empty($parameters['worker_hiring'])) $parameters['worker_hiring'] = DateTime::createFromFormat('Y-m-d', $parameters['worker_hiring'])->getTimestamp();
// Создание аккаунта // Создание аккаунта
@ -353,6 +359,7 @@ final class worker extends core
'city' => $parameters['worker_city'], 'city' => $parameters['worker_city'],
'district' => $parameters['worker_district'], 'district' => $parameters['worker_district'],
'address' => $parameters['worker_address'], 'address' => $parameters['worker_address'],
'work' => $parameters['worker_work'],
'hiring' => $parameters['worker_hiring'], 'hiring' => $parameters['worker_hiring'],
'rating' => 3 'rating' => 3
], ],
@ -389,7 +396,7 @@ final class worker extends core
// Авторизован аккаунт администратора или оператора // Авторизован аккаунт администратора или оператора
// Инициализация данных сотрудника // Инициализация данных сотрудника
$worker = model::read('d.id == "' . $parameters['id'] . '"', return: '{ name: d.name, number: d.number, mail: d.mail, birth: d.birth, passport: d.passport, issued: d.issued, department: d.department, requisites: d.requisites, payment: d.payment, tax: d.tax, city: d.city, district: d.district, address: d.address, hiring: d.hiring}')->getAll(); $worker = model::read('d.id == "' . $parameters['id'] . '"', return: '{ name: d.name, number: d.number, mail: d.mail, birth: d.birth, passport: d.passport, issued: d.issued, department: d.department, requisites: d.requisites, payment: d.payment, tax: d.tax, city: d.city, district: d.district, address: d.address, worl: d.work, hiring: d.hiring}')->getAll();
if (!empty($worker)) { if (!empty($worker)) {
// Найдены данные сотрудника // Найдены данные сотрудника
@ -437,6 +444,7 @@ final class worker extends core
// Универсализация // Универсализация
if (!empty($parameters['birth'])) $parameters['birth'] = DateTime::createFromFormat('Y-m-d', $parameters['birth'])->getTimestamp(); if (!empty($parameters['birth'])) $parameters['birth'] = DateTime::createFromFormat('Y-m-d', $parameters['birth'])->getTimestamp();
if (!empty($parameters['issued'])) $parameters['issued'] = DateTime::createFromFormat('Y-m-d', $parameters['issued'])->getTimestamp(); if (!empty($parameters['issued'])) $parameters['issued'] = DateTime::createFromFormat('Y-m-d', $parameters['issued'])->getTimestamp();
if (!empty($parameters['work'])) $parameters['work'] = in_array($parameters['work'], static::WORKS) ? $parameters['work'] : static::WORKS[0];
if (!empty($parameters['hiring'])) $parameters['hiring'] = DateTime::createFromFormat('Y-m-d', $parameters['hiring'])->getTimestamp(); if (!empty($parameters['hiring'])) $parameters['hiring'] = DateTime::createFromFormat('Y-m-d', $parameters['hiring'])->getTimestamp();
// Инициализация параметров (перезапись переданными значениями) // Инициализация параметров (перезапись переданными значениями)
@ -458,6 +466,7 @@ final class worker extends core
if ($parameters['city'] !== $worker->city) $worker->city = $parameters['city']; if ($parameters['city'] !== $worker->city) $worker->city = $parameters['city'];
if ($parameters['district'] !== $worker->district) $worker->district = $parameters['district']; if ($parameters['district'] !== $worker->district) $worker->district = $parameters['district'];
if ($parameters['address'] !== $worker->address) $worker->address = $parameters['address']; if ($parameters['address'] !== $worker->address) $worker->address = $parameters['address'];
if ($parameters['work'] !== $worker->work) $worker->work = $parameters['work'];
if ($parameters['hiring'] !== $worker->hiring) $worker->hiring = $parameters['hiring']; if ($parameters['hiring'] !== $worker->hiring) $worker->hiring = $parameters['hiring'];
if (_core::update($worker)) { if (_core::update($worker)) {
@ -513,6 +522,114 @@ final class worker extends core
return null; return null;
} }
/**
* Пометить уволенным
*
* @param array $parameters Параметры запроса
*/
public function fire(array $parameters = []): ?string
{
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных сотрудника
$worker = model::read('d.id == "' . $parameters['id'] . '"');
if (!empty($worker)) {
// Найден сотрудник
// Увольнение
$worker->active = false;
$worker->fired = true;
if (_core::update($worker)) {
// Записаны данные сотрудника
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Инициализация буфера ответа
$return = [
'fired' => true,
'errors' => self::parse_only_text($this->errors)
];
// Генерация ответа
echo json_encode($return);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Не удалось найти аккаунт');
}
// Возврат (провал)
return null;
}
/**
* Снять пометку уволенного (нанять)
*
* @param array $parameters Параметры запроса
*/
public function hire(array $parameters = []): ?string
{
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных сотрудника
$worker = model::read('d.id == "' . $parameters['id'] . '"');
if (!empty($worker)) {
// Найден сотрудник
// Увольнение
$worker->active = true;
$worker->fired = false;
if (_core::update($worker)) {
// Записаны данные сотрудника
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Инициализация буфера ответа
$return = [
'hired' => true,
'errors' => self::parse_only_text($this->errors)
];
// Генерация ответа
echo json_encode($return);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Не удалось найти аккаунт');
}
// Возврат (провал)
return null;
}
/** /**
* Прочитать данные сотрудников для <datalist> * Прочитать данные сотрудников для <datalist>
* *

View File

@ -42,7 +42,7 @@ final class account extends core
* Конструктор * Конструктор
* *
* @param ?session $session Инстанция сессии * @param ?session $session Инстанция сессии
* @param ?string $authenticate Аутентифицировать аккаунт? Если да, то какой категории? ([worker|operator|market] из $_SERVER['INTERFACE']) * @param ?string $authenticate Аутентифицировать аккаунт? Если да, то какой категории? ([worker|market|operator|administrator] из $_SERVER['INTERFACE'])
* @param array &$errors Реестр ошибок * @param array &$errors Реестр ошибок
* *
* @return static Инстанция аккаунта * @return static Инстанция аккаунта
@ -62,12 +62,19 @@ final class account extends core
// Связь сессии с аккаунтом // Связь сессии с аккаунтом
session::connect($session->getId(), $this->document->getId(), $errors); session::connect($session->getId(), $this->document->getId(), $errors);
// Блокировка доступа
if ($account?->active !== true) throw new exception('Свяжитесь с оператором');
else if ($account?->banned === true) throw new exception('Свяжитесь с оператором');
else if ($account->type === 'worker')
if (($worker = account::worker($account->getId()))?->active !== true) throw new exception('Свяжитесь с оператором');
else if ($worker?->fired === true) throw new exception('Свяжитесь с оператором');
return $this; return $this;
} else { } else {
// Не найден связанный с сессией аккаунт // Не найден связанный с сессией аккаунт
if ( if (
match ($authenticate) { match ($authenticate) {
'worker', 'operator', 'market', 'administrator' => true, 'worker', 'market', 'operator', 'administrator' => true,
default => false default => false
} }
) { ) {
@ -94,11 +101,16 @@ final class account extends core
// Удаление использованных данных из буфера сессии // Удаление использованных данных из буфера сессии
$session->write(['entry' => ['number' => null, 'password' => null]]); $session->write(['entry' => ['number' => null, 'password' => null]]);
// Блокировка доступа
if ($account?->active !== true) throw new exception('Свяжитесь с оператором');
else if ($account?->banned === true) throw new exception('Свяжитесь с оператором');
else if ($account->type === 'worker')
if (($worker = account::worker($account->getId()))?->active !== true) throw new exception('Свяжитесь с оператором');
else if ($worker?->fired === true) throw new exception('Свяжитесь с оператором');
// Выход (успех) // Выход (успех)
return $this; return $this;
} else throw new exception('Неправильный пароль'); } else throw new exception('Неправильный пароль');
throw new exception('Неизвестная ошибка на этапе проверки пароля');
} else throw new exception('Не найден аккаунт'); } else throw new exception('Не найден аккаунт');
} else throw new exception('Не найден пароль в буфере сессии'); } else throw new exception('Не найден пароль в буфере сессии');
} else if (!empty($session->buffer['operator']['entry']['_key'])) { } else if (!empty($session->buffer['operator']['entry']['_key'])) {
@ -125,8 +137,6 @@ final class account extends core
// Выход (успех) // Выход (успех)
return $this; return $this;
} else throw new exception('Неправильный пароль'); } else throw new exception('Неправильный пароль');
throw new exception('Неизвестная ошибка на этапе проверки пароля');
} }
} else throw new exception('Не найден пароль в буфере сессии'); } else throw new exception('Не найден пароль в буфере сессии');
} else if (!empty($session->buffer['market']['entry']['id'])) { } else if (!empty($session->buffer['market']['entry']['id'])) {
@ -153,8 +163,6 @@ final class account extends core
// Выход (успех) // Выход (успех)
return $this; return $this;
} else throw new exception('Неправильный пароль'); } else throw new exception('Неправильный пароль');
throw new exception('Неизвестная ошибка на этапе проверки пароля');
} }
} else throw new exception('Не найден пароль в буфере сессии'); } else throw new exception('Не найден пароль в буфере сессии');
} else if (!empty($session->buffer['administrator']['entry'])) { } else if (!empty($session->buffer['administrator']['entry'])) {
@ -181,8 +189,6 @@ final class account extends core
// Выход (успех) // Выход (успех)
return $this; return $this;
} else throw new exception('Неправильный пароль'); } else throw new exception('Неправильный пароль');
throw new exception('Неизвестная ошибка на этапе проверки пароля');
} }
} else throw new exception('Не найден пароль в буфере сессии'); } else throw new exception('Не найден пароль в буфере сессии');
} else throw new exception('Не найдены данные первичной идентификации в буфере сессии'); } else throw new exception('Не найдены данные первичной идентификации в буфере сессии');
@ -227,7 +233,7 @@ final class account extends core
LIMIT 1 LIMIT 1
RETURN e RETURN e
) )
FILTER d._id == e[0]._to && d.active == true FILTER d._id == e[0]._to
SORT d.created DESC, d._key DESC SORT d.created DESC, d._key DESC
LIMIT 1 LIMIT 1
RETURN d RETURN d
@ -285,7 +291,7 @@ final class account extends core
LIMIT 1 LIMIT 1
RETURN e RETURN e
) )
FILTER d._id == e[0]._to && d.active == true FILTER d._id == e[0]._to
SORT d.created DESC, d.id DESC SORT d.created DESC, d.id DESC
LIMIT 1 LIMIT 1
RETURN d RETURN d

View File

@ -56,10 +56,7 @@ section.panel.list > :is(form, search).row.menu > label > button.separated {
margin-left: 7px; margin-left: 7px;
} }
section.panel.list section.panel.list> :is(form, search).row.menu>label>button.separated:before {
> :is(form, search).row.menu
> label
> button.separated:before {
content: ""; content: "";
left: -12px; left: -12px;
position: absolute; position: absolute;
@ -69,10 +66,7 @@ section.panel.list
} }
section.panel.list> :is(form, search).row.menu.stretched>label>button, section.panel.list> :is(form, search).row.menu.stretched>label>button,
section.panel.list section.panel.list> :is(form, search).row.menu.stretched>label>input[type="search"] {
> :is(form, search).row.menu.stretched
> label
> input[type="search"] {
flex-grow: 1; flex-grow: 1;
} }
@ -93,11 +87,7 @@ section.panel.list > :is(form, search).row.menu > label > input[type="date"] {
flex-shrink: 0; flex-shrink: 0;
} }
section.panel.list section.panel.list> :is(form, search).row.menu>label>input[type="search"]+button {
> :is(form, search).row.menu
> label
> input[type="search"]
+ button {
height: 100%; height: 100%;
padding: 0 30px; padding: 0 30px;
flex-grow: 0; flex-grow: 0;
@ -206,85 +196,14 @@ section.panel.list > div.row[data-selected="true"]:after {
color: var(--interface-brown); color: var(--interface-brown);
} }
section.panel.list > div.row:not(:nth-of-type(1)).confirmed {
--background: var(--grass);
}
section.panel.list
> div.row:not(:nth-of-type(1)):nth-child(2n + 1).confirmed {
--background: var(--grass-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).published {
--background: var(--river);
}
section.panel.list
> div.row:not(:nth-of-type(1)):nth-child(2n + 1).published {
--background: var(--river-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).confirmed.published:not(.problematic) {
--background: var(--sea);
}
section.panel.list
> div.row:not(:nth-of-type(1)).confirmed.published:not(.problematic):nth-child(2n + 1) {
--background: var(--sea-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).problematic {
--background: var(--clay);
}
section.panel.list
> div.row:not(:nth-of-type(1)):nth-child(2n + 1).problematic {
--background: var(--clay-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).coming {
--background: var(--magma);
}
section.panel.list
> div.row:not(:nth-of-type(1)):nth-child(2n + 1).coming {
--background: var(--magma-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).completed:not(.problematic) {
--background: var(--sand);
}
section.panel.list
> div.row:not(:nth-of-type(1)):nth-child(2n + 1).completed:not(.problematic) {
--background: var(--sand-above);
}
section.panel.list > div.row:not(:nth-of-type(1)).passed {
filter: brightness(0.8);
}
section.panel.list > div.row:not(:nth-of-type(1)).hided * {
filter: blur(1px);
opacity: 0.3;
}
section.panel.list > div.row:not(:nth-of-type(1)).hided:is(:hover, :focus) * {
filter: unset;
opacity: unset;
}
section.panel.list>div.row.reinitialized { section.panel.list>div.row.reinitialized {
animation-duration: 3s; animation-duration: 3s;
animation-name: row-reinitialized; animation-name: row-reinitialized;
animation-timing-function: ease-in; animation-timing-function: ease-in;
} }
section.panel.list section.panel.list>div.row:not(:nth-of-type(1),
> div.row:not( [data-selected="true"]).reinitializable:before {
:nth-of-type(1),
[data-selected="true"]
).reinitializable:before {
content: attr(data-counter); content: attr(data-counter);
position: absolute; position: absolute;
left: -95px; left: -95px;
@ -297,11 +216,8 @@ section.panel.list
color: var(--earth-text); color: var(--earth-text);
} }
section.panel.list section.panel.list>div.row:not(:nth-of-type(1), [data-selected="true"]).reinitializable:is(:hover,
> div.row:not(:nth-of-type(1), [data-selected="true"]).reinitializable:is( :focus):before {
:hover,
:focus
):before {
content: attr(id); content: attr(id);
color: var(--earth-text-important-below); color: var(--earth-text-important-below);
} }
@ -367,54 +283,196 @@ section.panel.list > div.row:not(:nth-of-type(1)) > span:is(.important, .interac
--box-shadow: var(--border-left, 0) 0 0 0 var(--box-shadow-color, var(--background)), var(--border-right, 0) 0 0 0 var(--box-shadow-color, var(--background)); --box-shadow: var(--border-left, 0) 0 0 0 var(--box-shadow-color, var(--background)), var(--border-right, 0) 0 0 0 var(--box-shadow-color, var(--background));
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1) > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).confirmed {
--background: var(--grass);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).confirmed {
--background: var(--grass-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).published {
--background: var(--river);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).published {
--background: var(--river-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).confirmed.published:not(.problematic) {
--background: var(--sea);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).confirmed.published:not(.problematic):nth-child(2n + 1) {
--background: var(--sea-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).problematic {
--background: var(--clay);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).problematic {
--background: var(--clay-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).coming {
--background: var(--magma);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).coming {
--background: var(--magma-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).completed:not(.problematic) {
--background: var(--sand);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).completed:not(.problematic) {
--background: var(--sand-above);
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).passed {
filter: brightness(0.8);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).banned {
--background: var(--clay);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).banned a {
--color: var(--clay-text);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).banned a:is(:hover, :focus) {
--color: var(--clay-text-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).banned a:active {
--color: var(--clay-text-below);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).banned {
--background: var(--clay-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).banned a {
--color: var(--clay-text);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).banned a:is(:hover, :focus) {
--color: var(--clay-text-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).banned a:active {
--color: var(--clay-text-below);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).fired {
--background: var(--magma);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).fired a:is(:hover, :focus) {
--color: var(--magma-text-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).fired a:active {
--color: var(--magma-text-below);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).fired a {
--color: var(--magma-text);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).fired {
--background: var(--magma-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).fired a {
--color: var(--magma-text);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).fired a:is(:hover, :focus) {
--color: var(--magma-text-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).fired a:active {
--color: var(--magma-text-below);
}
section.panel.list>div.row:not(:nth-of-type(1)).hided * {
filter: blur(1px);
opacity: 0.3;
}
section.panel.list>div.row:not(:nth-of-type(1)).hided:is(:hover, :focus) * {
filter: unset;
opacity: unset;
}
section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1)>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--cloud-rainy-above); --background: var(--cloud-rainy-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).published > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).published>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--river-deep); --background: var(--river-deep);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).published > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).published>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--river-deep-above); --background: var(--river-deep-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).confirmed > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).confirmed>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--grass-dense); --background: var(--grass-dense);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).confirmed > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).confirmed>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--grass-dense-above); --background: var(--grass-dense-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).confirmed.published:not(.problematic) > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).confirmed.published:not(.problematic)>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--sea-deep); --background: var(--sea-deep);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).confirmed.published:not(.problematic) > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).confirmed.published:not(.problematic)>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--sea-deep-above); --background: var(--sea-deep-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).problematic > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).problematic>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--clay-important); --background: var(--clay-important);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).problematic > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).problematic>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--clay-important-above); --background: var(--clay-important-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).coming > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).coming>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--magma-important); --background: var(--magma-important);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).coming > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).coming>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--magma-important-above); --background: var(--magma-important-above);
} }
section.panel.list > div.row:not(:nth-of-type(1)).completed:not(.problematic) > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)).completed:not(.problematic)>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--sand-important); --background: var(--sand-important);
} }
section.panel.list > div.row:not(:nth-of-type(1)):nth-child(2n + 1).completed:not(.problematic) > span:is(.important, .interactive:is(:hover, :focus)) { section.panel.list>div.row[data-row="task"]:not(:nth-of-type(1)):nth-child(2n + 1).completed:not(.problematic)>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--sand-important-above); --background: var(--sand-important-above);
} }
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).banned>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--clay-important);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).banned>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--clay-important-above);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)).fired>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--magma-important);
}
section.panel.list>div.row[data-row="worker"]:not(:nth-of-type(1)):nth-child(2n + 1).fired>span:is(.important, .interactive:is(:hover, :focus)) {
--background: var(--magma-important-above);
}

View File

@ -259,15 +259,16 @@ button:is(.transparent, .transparent:is(:hover, :focus), .transparent:active) {
} }
a { a {
color: var(--link); --color: var(--link);
color: var(--color);
} }
a:is(:hover, :focus) { a:is(:hover, :focus) {
color: var(--link-hover); --color: var(--link-hover);
} }
a:active { a:active {
color: var(--link-active); --color: var(--link-active);
transition: unset; transition: unset;
} }

View File

@ -15,7 +15,7 @@ section#workers.panel.list
[data-column="worker"], [data-column="worker"],
[data-column="name"], [data-column="name"],
[data-column="number"], [data-column="number"],
[data-column="mail"], [data-column="work"],
[data-column="passport"], [data-column="passport"],
[data-column="address"], [data-column="address"],
[data-column="tax"], [data-column="tax"],

View File

@ -38,7 +38,6 @@ div#popup>section.stretched {
flex-grow: unset; flex-grow: unset;
} }
div#popup>section.calculated { div#popup>section.calculated {
width: calc(var(--calculated-width) - var(--padding-horizontal, 0px) * 2); width: calc(var(--calculated-width) - var(--padding-horizontal, 0px) * 2);
} }
@ -53,6 +52,11 @@ div#popup>section.list {
border-radius: 3px; border-radius: 3px;
} }
div#popup>section.list.extensive {
max-width: unset;
max-height: unset;
}
div#popup>section.list>h3 { div#popup>section.list>h3 {
margin-top: 4px; margin-top: 4px;
margin-bottom: 22px; margin-bottom: 22px;

View File

@ -83,10 +83,9 @@
--sand-important: #d7c06c; --sand-important: #d7c06c;
--sand-important-below: #dfc79a; --sand-important-below: #dfc79a;
--magma-text-above: ; --magma-text-above: #111;
--magma-text: ; --magma-text: #5e1a1a;
--magma-text-below: ; --magma-text-below: #826d1c;
--magma-text-below-1: ;
--magma-above: #ffd325; --magma-above: #ffd325;
--magma: #e6bf26; --magma: #e6bf26;
--magma-below: ; --magma-below: ;

View File

@ -40,6 +40,7 @@ $router->write('/worker/$worker/read', 'task', 'worker', 'POST');
$router->write('/worker/$id/fields', 'worker', 'fields', 'POST'); $router->write('/worker/$id/fields', 'worker', 'fields', 'POST');
$router->write('/worker/$id/update', 'worker', 'update', 'POST'); $router->write('/worker/$id/update', 'worker', 'update', 'POST');
$router->write('/worker/$id/fire', 'worker', 'fire', 'POST'); $router->write('/worker/$id/fire', 'worker', 'fire', 'POST');
$router->write('/worker/$id/hire', 'worker', 'hire', '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/read', 'worker', 'read', 'POST');
@ -68,6 +69,8 @@ $router->write('/$id', 'account', 'index', 'POST');
$router->write('/$id/fields', 'account', 'fields', 'POST'); $router->write('/$id/fields', 'account', 'fields', 'POST');
$router->write('/$id/update', 'account', 'update', 'POST'); $router->write('/$id/update', 'account', 'update', 'POST');
$router->write('/$id/delete', 'account', 'delete', 'POST'); $router->write('/$id/delete', 'account', 'delete', 'POST');
$router->write('/$id/ban', 'account', 'ban', 'POST');
$router->write('/$id/unban', 'account', 'unban', 'POST');
$router->write('/session/worker', 'session', 'worker', 'POST'); $router->write('/session/worker', 'session', 'worker', 'POST');
$router->write('/session/write', 'session', 'write', 'POST'); $router->write('/session/write', 'session', 'write', 'POST');
$router->write('/session/read', 'session', 'read', 'POST'); $router->write('/session/read', 'session', 'read', 'POST');
@ -79,6 +82,7 @@ $router->write('/session/invite', 'session', 'invite', 'POST');
$router->write('/tasks/create', 'task', 'create', 'POST'); $router->write('/tasks/create', 'task', 'create', 'POST');
$router->write('/tasks/read', 'task', 'read', 'POST'); $router->write('/tasks/read', 'task', 'read', 'POST');
$router->write('/works/list', 'work', 'datalist', 'POST'); $router->write('/works/list', 'work', 'datalist', 'POST');
$router->write('/tasks/works', 'task', 'works', 'POST');
$router->write('/task/$task/read', 'task', 'task', 'POST'); $router->write('/task/$task/read', 'task', 'task', 'POST');
$router->write('/task/$task/value', 'task', 'value', 'POST'); $router->write('/task/$task/value', 'task', 'value', 'POST');
$router->write('/task/$task/confirm', 'task', 'confirm', 'POST'); $router->write('/task/$task/confirm', 'task', 'confirm', 'POST');
@ -88,7 +92,6 @@ $router->write('/task/$task/hide', 'task', 'hide', 'POST');
$router->write('/task/$task/remove', 'task', 'remove', 'POST'); $router->write('/task/$task/remove', 'task', 'remove', 'POST');
$router->write('/task/$task/work', 'task', 'work', 'POST'); $router->write('/task/$task/work', 'task', 'work', 'POST');
$router->write('/task/$task/date', 'task', 'date', 'POST'); $router->write('/task/$task/date', 'task', 'date', 'POST');
$router->write('/task/$task/works', 'task', 'works', 'POST');
$router->write('/task/$task/description', 'task', 'description', 'POST'); $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');

View File

@ -338,7 +338,7 @@ if (typeof window.administrators !== "function") {
// Инициализация оболочки всплывающего окна // Инициализация оболочки всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "small"); popup.classList.add("list", "extensive", "small");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");
@ -1056,7 +1056,7 @@ if (typeof window.administrators !== "function") {
); );
/** /**
* Сгенерировать окно с формой создания аккаунт * Сгенерировать окно с формой создания аккаунта
* *
* @param {HTMLElement} row Строка * @param {HTMLElement} row Строка
* *
@ -1069,7 +1069,7 @@ if (typeof window.administrators !== "function") {
// Инициализация оболочки всплывающего окна // Инициализация оболочки всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "small"); popup.classList.add("list", "extensive", "small");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");

View File

@ -339,7 +339,7 @@ if (typeof window.markets !== "function") {
// Инициализация всплывающего окна // Инициализация всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "medium"); popup.classList.add("list", "extensive", "medium");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");
@ -1774,7 +1774,7 @@ if (typeof window.markets !== "function") {
// Инициализация всплывающего окна // Инициализация всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "medium"); popup.classList.add("list", "extensive", "medium");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");

View File

@ -338,7 +338,7 @@ if (typeof window.operators !== "function") {
// Инициализация оболочки всплывающего окна // Инициализация оболочки всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "small"); popup.classList.add("list", "extensive", "small");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");
@ -1069,7 +1069,7 @@ if (typeof window.operators !== "function") {
// Инициализация оболочки всплывающего окна // Инициализация оболочки всплывающего окна
const popup = document.createElement("section"); const popup = document.createElement("section");
popup.classList.add("list", "small"); popup.classList.add("list", "extensive", "small");
// Инициализация заголовка всплывающего окна // Инициализация заголовка всплывающего окна
const title = document.createElement("h3"); const title = document.createElement("h3");

View File

@ -2573,7 +2573,7 @@ if (typeof window.tasks !== "function") {
// Инициализация списка выбора типа работы // Инициализация списка выбора типа работы
const work = document.createElement("select"); const work = document.createElement("select");
work.classList.add("row", "connected", "stretched"); work.classList.add("row", "connected", "stretched");
this.works(row).then((html) => (work.innerHTML = html)); this.works(task).then((html) => (work.innerHTML = html));
work.setAttribute("title", "Тип работы"); work.setAttribute("title", "Тип работы");
// Инициализация поля ввода описания // Инициализация поля ввода описания
@ -3840,28 +3840,22 @@ if (typeof window.tasks !== "function") {
} }
/** /**
* Сгенерировать список работ и выбрать в нём ту, что записана в базе данных у заявки * Список работ
* *
* @param {HTMLElement} row Строка * Сгенерировать список работ и выбрать в нём ту, что записана в базе данных у заявки, если передана
*
* @param {number|null} id Идентификатор заявки
* *
* @return {array|null} Массив HTML-элементов <option> * @return {array|null} Массив HTML-элементов <option>
*/ */
static async works(row) { static async works(id) {
if (row instanceof HTMLElement) {
// Получена строка
// Инициализация идентификатора строки
const id = row.getAttribute("id");
if (typeof id === "string") {
// Инициализирован идентификатор
// Запрос к серверу // Запрос к серверу
return await fetch(`/task/${id}/works`, { return await fetch(`/tasks/works`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
}, },
body: `task=${id}`,
}) })
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
@ -3874,8 +3868,6 @@ if (typeof window.tasks !== "function") {
} }
}); });
} }
}
}
/** /**
* Записать тип работы * Записать тип работы

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
row.worker.name.first|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.last 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.last|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.second is not empty %} {{
row.worker.name.second }}{% endif %}</span> row.worker.name.second }}{% endif %}</span>
<span class="unselectable interactive" data-column="work" title="{{ row.task.description }}">{{ row.task.work <span class="unselectable interactive" data-column="work" title="{{ row.task.description }}">{{ row.task.work|work
}}</span> }}</span>
<span class="unselectable interactive" data-column="start">{{ <span class="unselectable interactive" data-column="start">{{
row.task.generated.start }}</span> row.task.generated.start }}</span>

View File

@ -1,7 +1,7 @@
{% if page != null %}<!-- PAGE #{{ page }} -->{% endif %} {% if page != null %}<!-- PAGE #{{ page }} -->{% endif %}
{% for row in rows %} {% for row in rows %}
<div id="{{ row.account._key }}" <div id="{{ row.account._key }}"
class="row{% if row.account.active is same as(true) %} active{% else %} hided{% endif %}" data-row="worker"> class="row{% if row.account.active is same as(true) %} active{% endif %}{% if row.account.banned is same as(true) %} banned{% endif %}{% if row.worker.fired is same as(true) %} fired{% endif %}" data-row="worker">
<span class="unselectable interactive" data-column="account" title="Настройки аккаунта" <span class="unselectable interactive" data-column="account" title="Настройки аккаунта"
onclick="workers.account.update(this.parentElement)">{{ onclick="workers.account.update(this.parentElement)">{{
row.account._key }}</span> row.account._key }}</span>
@ -17,8 +17,7 @@
row.worker.name.second }}{% endif %}</span> row.worker.name.second }}{% endif %}</span>
<span class="unselectable interactive" data-column="number"><a href="tel:{{ row.worker.number }}" title="Позвонить">{{ <span class="unselectable interactive" data-column="number"><a href="tel:{{ row.worker.number }}" title="Позвонить">{{
row.worker.number|storaged_number_to_readable }}</a></span> row.worker.number|storaged_number_to_readable }}</a></span>
<span class="unselectable interactive" data-column="mail"><a href="mailto:{{ row.worker.mail }}" title="Написать">{{ <span class="unselectable interactive" data-column="work">{{ row.worker.work }}</span>
row.worker.mail }}</a></span>
<span class="unselectable interactive" data-column="address" <span class="unselectable interactive" data-column="address"
title="{{ (row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address)|trim }}" title="{{ (row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address)|trim }}"
onclick="navigator.clipboard.writeText('{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}')">{% onclick="navigator.clipboard.writeText('{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}')">{%

View File

@ -1,3 +1,4 @@
{% if task %}
{% if exist is same as(true) %} {% if exist is same as(true) %}
{% for work in works %} {% for work in works %}
<option value="{{ work }}" {% if task.work==work %} selected{% endif %}>{{ work }}</option> <option value="{{ work }}" {% if task.work==work %} selected{% endif %}>{{ work }}</option>
@ -14,3 +15,25 @@
{% endfor %} {% endfor %}
</optgroup> </optgroup>
{% endif %} {% endif %}
{% elseif worker %}
{% if exist is same as(true) %}
{% for work in works %}
<option value="{{ work }}" {% if worker.work==work %} selected{% endif %}>{{ work }}</option>
{% endfor %}
{% else %}
{% if worker is not null %}
<optgroup label="Текущее">
<option value="{{ worker.work }}" selected>{{ worker.work }}</option>
</optgroup>
{% endif %}
<optgroup label="Доступное">
{% for work in works %}
<option value="{{ work }}">{{ work }}</option>
{% endfor %}
</optgroup>
{% endif %}
{% else %}
{% for work in works %}
<option value="{{ work }}">{{ work }}</option>
{% endfor %}
{% endif %}

View File

@ -21,8 +21,8 @@
<button class="grass dense" onclick="tasks.create()">Создать</button> <button class="grass dense" onclick="tasks.create()">Создать</button>
{% endif %} {% endif %}
{% if account.type == 'administrator' or account.type == 'operator' %} {% if account.type == 'administrator' or account.type == 'operator' %}
<button class="sea" onclick="payments.workers()">Зарплата</button> <button class="sea" onclick="payments.workers()">Сотрудники</button>
<button class="sea" onclick="payments.markets()">Сверка</button> <button class="sea" onclick="payments.markets()">Магазины</button>
{% endif %} {% endif %}
</label> </label>
</form> </form>

View File

@ -58,7 +58,7 @@
<span data-column="worker" class="button" title="Сотрудник"><i class="icon bold user"></i></span> <span data-column="worker" class="button" title="Сотрудник"><i class="icon bold user"></i></span>
<span data-column="name" class="button">ФИО</span> <span data-column="name" class="button">ФИО</span>
<span data-column="number" class="button">Номер</span> <span data-column="number" class="button">Номер</span>
<span data-column="mail" class="button">Почта</span> <span data-column="work" class="button">Работа</span>
<span data-column="address" class="button">Адрес</span> <span data-column="address" class="button">Адрес</span>
<span data-column="passport" class="button">Паспорт</span> <span data-column="passport" class="button">Паспорт</span>
<span data-column="tax" class="button">ИНН</span> <span data-column="tax" class="button">ИНН</span>

View File

@ -59,7 +59,7 @@ final class templater extends controller implements ArrayAccess
} }
if (!empty($account->status())) $this->twig->addGlobal('account', $account); if (!empty($account->status())) $this->twig->addGlobal('account', $account);
// Инициализация фильтров // Инициализация фильтра
$this->twig->addFilter( $this->twig->addFilter(
new TwigFilter( new TwigFilter(
'storaged_number_to_readable', 'storaged_number_to_readable',
@ -67,7 +67,7 @@ final class templater extends controller implements ArrayAccess
) )
); );
// Инициализация фильтров // Инициализация фильтра
$this->twig->addFilter( $this->twig->addFilter(
new TwigFilter( new TwigFilter(
'storaged_requisites_to_card', 'storaged_requisites_to_card',
@ -78,7 +78,7 @@ final class templater extends controller implements ArrayAccess
) )
); );
// Инициализация фильтров // Инициализация фильтра
$this->twig->addFilter( $this->twig->addFilter(
new TwigFilter( new TwigFilter(
'storaged_requisites_preview', 'storaged_requisites_preview',
@ -86,7 +86,7 @@ final class templater extends controller implements ArrayAccess
) )
); );
// Инициализация фильтров // Инициализация фильтра
$this->twig->addFilter( $this->twig->addFilter(
new TwigFilter( new TwigFilter(
'date_to_russian', 'date_to_russian',
@ -94,7 +94,7 @@ final class templater extends controller implements ArrayAccess
) )
); );
// Инициализация фильтров // Инициализация фильтра
$this->twig->addFilter( $this->twig->addFilter(
new TwigFilter( new TwigFilter(
'account_type_to_russian', 'account_type_to_russian',
@ -108,6 +108,14 @@ final class templater extends controller implements ArrayAccess
) )
); );
// Инициализация фильтра
$this->twig->addFilter(
new TwigFilter(
'work',
fn (string $work) => preg_replace('/^Мобильный/', 'Моб.', $work)
)
);
// Инициализация расширений // Инициализация расширений
$this->twig->addExtension(new intl()); $this->twig->addExtension(new intl());
} }