rev.15 Add smilies management

This commit is contained in:
Visman 2020-09-12 14:26:42 +07:00
parent e3e41628d9
commit 72c250be11
16 changed files with 910 additions and 19 deletions

View file

@ -540,6 +540,30 @@ class Routing
'AdminParser:edit',
'AdminParser'
);
$r->add(
$r::DUO,
'/admin/parser/bbcode',
'AdminParserBBCode:view',
'AdminBBCode'
);
$r->add(
$r::DUO,
'/admin/parser/smilies',
'AdminParserSmilies:view',
'AdminSmilies'
);
$r->add(
$r::GET,
'/admin/parser/smilies/delete/{name}/{token}',
'AdminParserSmilies:delete',
'AdminSmiliesDelete'
);
$r->add(
$r::PST,
'/admin/parser/smilies/upload',
'AdminParserSmilies:upload',
'AdminSmiliesUpload'
);
$r->add(
$r::DUO,
'/admin/categories',

View file

@ -49,7 +49,7 @@ class Parser extends Parserus
$smilies = [];
foreach ($this->c->smilies->list as $cur) {
$smilies[$cur['text']] = $this->c->PUBLIC_URL . '/img/sm/' . $cur['image'];
$smilies[$cur['sm_code']] = $this->c->PUBLIC_URL . '/img/sm/' . $cur['sm_image'];
}
$info = $this->c->BBCODE_INFO;

View file

@ -959,10 +959,10 @@ class Install extends Admin
// smilies
$schema = [
'FIELDS' => [
'id' => ['SERIAL', false],
'image' => ['VARCHAR(40)', false, ''],
'text' => ['VARCHAR(20)', false, ''],
'disp_position' => ['TINYINT(4) UNSIGNED', false, 0],
'id' => ['SERIAL', false],
'sm_image' => ['VARCHAR(40)', false, ''],
'sm_code' => ['VARCHAR(20)', false, ''],
'sm_position' => ['INT(10) UNSIGNED', false, 0],
],
'PRIMARY KEY' => ['id'],
'ENGINE' => $this->DBEngine,

View file

@ -61,7 +61,7 @@ class Edit extends Parser
$this->nameTpl = 'admin/form';
$this->form = $this->formEdit($config);
$this->titleForm = __('Parser settings head');
$this->classForm = 'editparsersettings';
$this->classForm = 'parser-settings';
return $this;
}
@ -138,6 +138,13 @@ class Edit extends Parser
'caption' => __('Quote depth label'),
'info' => __('Quote depth help'),
],
'bbcode_management' => [
'type' => 'btn',
'caption' => null,
'value' => __('BBCode management'),
'title' => __('BBCode management'),
'link' => $this->c->Router->link('AdminBBCode'),
],
],
];
@ -148,8 +155,8 @@ class Edit extends Parser
'type' => 'radio',
'value' => $config->o_smilies,
'values' => $yn,
'caption' => __('Smilies label'),
'info' => __('Smilies help'),
'caption' => __('Smilies mess label'),
'info' => __('Smilies mess help'),
],
'o_smilies_sig' => [
'type' => 'radio',
@ -158,6 +165,13 @@ class Edit extends Parser
'caption' => __('Smilies sigs label'),
'info' => __('Smilies sigs help'),
],
'smilies_management' => [
'type' => 'btn',
'caption' => null,
'value' => __('Smilies management'),
'title' => __('Smilies management'),
'link' => $this->c->Router->link('AdminSmilies'),
],
],
];

View file

@ -0,0 +1,423 @@
<?php
namespace ForkBB\Models\Pages\Admin\Parser;
use ForkBB\Core\Image;
use ForkBB\Core\Validator;
use ForkBB\Models\Page;
use ForkBB\Models\Pages\Admin\Parser;
use ForkBB\Models\Config\Model as Config;
use function \ForkBB\__;
class Smilies extends Parser
{
/**
* Паттерн для имени изображения
* @var string
*/
protected $pattern = '%^[a-z0-9-_]+\.(?:gif|jpe?g|png|webp)$%isD';
/**
* Паттерн для доступных к загрузке типов файлов
* @var string
*/
protected $accept = 'image/*';
/**
* Заполняет список файлов из каталога смайлов
*/
protected function calcImages(): void
{
$dir = $this->c->DIR_PUBLIC . '/img/sm/';
$result = [];
if (
\is_dir($dir)
&& false !== ($dh = \opendir($dir))
) {
while (false !== ($entry = \readdir($dh))) {
if (
\preg_match($this->pattern, $entry)
&& \is_file($dir . $entry)
) {
$result[] = $entry;
}
}
\closedir($dh);
\sort($result, \SORT_NATURAL);
}
$this->imageList = $result;
}
/**
* Управление смайлами
*/
public function view(array $args, string $method): Page
{
$this->calcImages();
if ('POST' === $method) {
$imageStr = \implode(',', $this->imageList);
$v = $this->c->Validator->reset()
->addValidators([
])->addRules([
'token' => 'token:AdminSmilies',
'smilies.*.sm_code' => 'required|string:trim|max:20',
'smilies.*.sm_position' => 'required|integer|min:0|max:9999',
'smilies.*.sm_image' => 'required|string|max:40|in:' . $imageStr,
'new_sm_code' => 'string:trim|max:20',
'new_sm_position' => 'integer|min:0|max:9999',
'new_sm_image' => 'string|max:40|in:' . $imageStr,
])->addAliases([
'smilies.*.sm_code' => 'Smiley code label',
'smilies.*.sm_position' => 'Position label',
'smilies.*.sm_image' => 'Name label',
'new_sm_code' => 'Smiley code label',
'new_sm_position' => 'Position label',
'new_sm_image' => 'Name label',
])->addArguments([
])->addMessages([
]);
$valid = $v->validation($_POST);
$data = $v->getData();
if ($valid) {
$old = $this->c->smilies->list;
$new = $v->smilies;
foreach ($new as $id => $cur) {
if (isset($old[$id]) && $cur != $old[$id]) {
$this->c->smilies->update($id, $cur);
}
}
if ('' != $v->new_sm_code) {
$this->c->smilies->insert([
'sm_code' => $v->new_sm_code,
'sm_position' => $v->new_sm_position,
'sm_image' => $v->new_sm_image,
]);
}
$this->c->Cache->delete('smilies');
return $this->c->Redirect->page('AdminSmilies')->message('Smilies updated redirect');
}
$this->fIswev = $v->getErrors();
} else {
$data = [];
}
$this->nameTpl = 'admin/smilies';
$this->aCrumbs[] = [
$this->c->Router->link('AdminSmilies'),
__('Smilies management'),
];
$this->formSmilies = $this->formSmilies($data);
$this->formImages = $this->formImages();
$this->formUploadImage = $this->formUploadImage();
return $this;
}
/**
* Формирует данные для формы смайлов
*/
protected function formSmilies(array $data): array
{
$form = [
'action' => $this->c->Router->link('AdminSmilies'),
'hidden' => [
'token' => $this->c->Csrf->create('AdminSmilies'),
],
'sets' => [
'smilies-legend' => [
'class' => 'smilies-legend',
'legend' => __('Smilies list subhead'),
'fields' => [],
],
],
'btns' => [
'save' => [
'type' => 'submit',
'value' => __('Save changes'),
// 'accesskey' => 's',
],
],
];
$imageList = \array_combine($this->imageList, $this->imageList);
$i = 1;
$max = 0;
foreach ($this->c->smilies->list as $id => $cur) {
$fields = [];
$max = \max($max, $cur['sm_position']);
$fields["smilies[{$id}][sm_code]"] = [
'class' => ['code', 'smile'],
'type' => 'text',
'maxlength' => 20,
'value' => $data['smilies'][$id]['sm_code'] ?? $cur['sm_code'],
'caption' => __('Smiley code label'),
'required' => true,
];
$fields["smilies[{$id}][sm_position]"] = [
'class' => ['position', 'smile'],
'type' => 'number',
'min' => 0,
'max' => 255,
'value' => $data['smilies'][$id]['sm_position'] ?? $cur['sm_position'],
'caption' => __('Position label'),
'required' => true,
];
$fields["smilies[{$id}][sm_image]"] = [
'class' => ['image', 'smile'],
'type' => 'select',
'options' => $imageList,
'value' => $data['smilies'][$id]['sm_image'] ?? $cur['sm_image'],
'caption' => __('Name label'),
'required' => true,
];
$fields["smile{$id}-pic"] = [
'class' => ['pic', 'smile'],
'type' => 'str',
'value' => __('<img src="%1$s" alt="%2$s">', $this->c->PUBLIC_URL . '/img/sm/' . $cur['sm_image'], $cur['sm_image']),
'caption' => __('Picture label'),
'html' => true,
];
$fields["smile{$id}-del"] = [
'class' => ['delete', 'smile'],
'type' => 'btn',
'value' => '❌',
'caption' => __('Delete'),
'title' => __('Delete'),
'link' => $this->c->Router->link(
'AdminSmiliesDelete',
[
'name' => $id,
'token' => $this->c->Csrf->create(
'AdminSmiliesDelete',
[
'name' => $id,
]
),
]
),
];
$form['sets']["smile{$id}"] = [
'class' => 'smile',
'legend' => __('Smiley number %s', $i),
'fields' => $fields,
];
++$i;
}
$form['sets']['new-smile'] = [
'class' => 'new-smile',
'legend' => __('New smile subhead'),
'fields' => [
'new_sm_code' => [
'class' => ['code', 'new-smile'],
'type' => 'text',
'maxlength' => 20,
'value' => $data['new_sm_code'] ?? '',
'caption' => __('Smiley code label'),
],
'new_sm_position' => [
'class' => ['position', 'new-smile'],
'type' => 'number',
'min' => 0,
'max' => 255,
'value' => $data['new_sm_position'] ?? $max + 1,
'caption' => __('Position label'),
],
'new_sm_image' => [
'class' => ['image', 'new-smile'],
'type' => 'select',
'options' => $imageList,
'value' => $data['new_image'] ?? null,
'caption' => __('Name label'),
],
],
];
return $form;
}
/**
* Формирует данные для формы изображений
*/
protected function formImages(): array
{
$form = [
'sets' => [
'image-legend' => [
'class' => 'image-legend',
'legend' => __('Available images subhead'),
'fields' => [],
],
],
];
foreach ($this->imageList as $key => $name) {
$fields = [];
$fields["image{$key}-pic"] = [
'class' => ['pic', 'image'],
'type' => 'str',
'value' => __('<img src="%1$s" alt="%2$s">', $this->c->PUBLIC_URL . '/img/sm/' . $name, $name),
'caption' => __('Picture label'),
'html' => true,
];
$fields["image{$key}-name"] = [
'class' => ['name', 'image'],
'type' => 'str',
'value' => $name,
'caption' => __('Name label'),
];
$fields["image{$key}-del"] = [
'class' => ['delete', 'image'],
'type' => 'link',
'value' => '❌',
'caption' => __('Delete'),
'title' => __('Delete'),
'href' => $this->c->Router->link(
'AdminSmiliesDelete',
[
'name' => $name,
'token' => $this->c->Csrf->create(
'AdminSmiliesDelete',
[
'name' => $name,
]
),
]
),
];
$form['sets']["image{$key}"] = [
'class' => 'image',
'legend' => $name,
'fields' => $fields,
];
}
return $form;
}
/**
* Формирует данные для формы загрузки картинки
*/
protected function formUploadImage(): array
{
$form = [
'action' => $this->c->Router->link('AdminSmiliesUpload'),
'enctype' => 'multipart/form-data',
'hidden' => [
'token' => $this->c->Csrf->create('AdminSmiliesUpload'),
'MAX_FILE_SIZE' => $this->c->Files->maxImgSize(),
],
'sets' => [
'upload' => [
'class' => 'upload_smile',
'legend' => __('Upload image subhead'),
'fields' => [
'upload_image' => [
'type' => 'file',
'caption' => __('Upload image label'),
'info' => __('Upload image info'),
'accept' => $this->accept,
],
],
],
],
'btns' => [
'upload' => [
'type' => 'submit',
'value' => __('Upload'),
// 'accesskey' => 's',
],
],
];
return $form;
}
/**
* Удаляет смайл или изображение
*/
public function delete(array $args, string $method): Page
{
if (! $this->c->Csrf->verify($args['token'], 'AdminSmiliesDelete', $args)) {
return $this->c->Message->message('Bad token');
}
if (
\is_numeric($args['name'])
&& \is_int(0 + $args['name'])
) {
$this->c->smilies->delete((int) $args['name']);
$message = 'Smile deleted redirect';
} elseif (\preg_match($this->pattern, $args['name'])) {
$file = $this->c->DIR_PUBLIC . '/img/sm/' . $args['name'];
if (
\is_file($file)
&& @\unlink($file)
) {
$message = __('File %s deleted redirect', $args['name']);
} else {
$message = __('File %s not deleted redirect', $args['name']);
}
} else {
return $this->c->Message->message('Bad request');
}
return $this->c->Redirect->page('AdminSmilies')->message($message);
}
/**
* Загружает изображение
*/
public function upload(array $args, string $method): Page
{
$v = $this->c->Validator->reset()
->addValidators([
])->addRules([
'token' => 'token:AdminSmiliesUpload',
'upload_image' => "required|image|max:{$this->c->Files->maxImgSize('K')}",
])->addAliases([
'upload_image' => 'Upload image label',
])->addArguments([
])->addMessages([
]);
if (
$v->validation($_FILES + $_POST)
&& $v->upload_image instanceof Image
) {
if (
$v->upload_image
->rename(true)
->rewrite(false)
->toFile($this->c->DIR_PUBLIC . '/img/sm/*.(jpg|png|gif)')
) {
return $this->c->Redirect->page('AdminSmilies')->message('Image uploaded redirect');
} else {
return $this->c->Message->message($v->upload_image->error());
}
}
$this->fIswev = $v->getErrors();
return $this->view([], 'GET');
}
}

View file

@ -17,7 +17,7 @@ class Update extends Admin
{
const PHP_MIN = '7.3.0';
const LATEST_REV_WITH_DB_CHANGES = 9;
const LATEST_REV_WITH_DB_CHANGES = 15;
const LOCK_NAME = 'lock_update';
const LOCk_TTL = 1800;
@ -693,4 +693,45 @@ class Update extends Admin
return null;
}
/**
* rev.14 to rev.15
*/
protected function stageNumber14(array $args): ?int
{
$coreConfig = new CoreConfig($this->c->DIR_CONFIG . '/' . self::CONFIG_FILE);
$result = $coreConfig->delete(
'multiple=>SmileyListModelLoad',
);
$coreConfig->add(
'shared=>SmileyListModelLoad',
'\\ForkBB\\Models\\SmileyList\\Load::class'
);
$coreConfig->add(
'shared=>SmileyListModelUpdate',
'\\ForkBB\\Models\\SmileyList\\Update::class'
);
$coreConfig->add(
'shared=>SmileyListModelInsert',
'\\ForkBB\\Models\\SmileyList\\Insert::class'
);
$coreConfig->add(
'shared=>SmileyListModelDelete',
'\\ForkBB\\Models\\SmileyList\\Delete::class'
);
$coreConfig->save();
$this->c->DB->renameField('smilies', 'image', 'sm_image');
$this->c->DB->renameField('smilies', 'text', 'sm_code');
$this->c->DB->renameField('smilies', 'disp_position', 'sm_position');
$this->c->DB->alterField('smilies', 'sm_position', 'INT(10) UNSIGNED', false, 0);
return null;
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace ForkBB\Models\SmileyList;
use ForkBB\Models\Method;
use ForkBB\Models\SmileyList\Model as SmileyList;
class Delete extends Method
{
/**
* Удаляет смайл из БД
* Удаляет кеш смайлов
*/
public function delete(int $id): SmileyList
{
$vars = [
':id' => $id,
];
$query = 'DELETE
FROM ::smilies
WHERE id=?i:id';
$this->c->DB->exec($query, $vars);
$this->c->Cache->delete('smilies');
return $this->model;
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace ForkBB\Models\SmileyList;
use ForkBB\Models\Method;
use InvalidArgumentException;
class Insert extends Method
{
/**
* Создает запись в БД для смайла
*/
public function insert(array $data): int
{
if (
isset($data['id'])
|| ! isset($data['sm_code'], $data['sm_position'], $data['sm_image'])
|| '' == $data['sm_code']
|| '' == $data['sm_image']
) {
throw new InvalidArgumentException('Expected an array with a smile description');
}
$query = 'INSERT INTO ::smilies (sm_code, sm_position, sm_image)
VALUES (?s:sm_code, ?i:sm_position, ?s:sm_image)';
$this->c->DB->exec($query, $data);
return (int) $this->c->DB->lastInsertId();
}
}

View file

@ -16,9 +16,9 @@ class Load extends Method
*/
public function load(): SmileyList
{
$query = 'SELECT sm.id, sm.text, sm.image, sm.disp_position
FROM ::smilies AS sm
ORDER BY sm.disp_position';
$query = 'SELECT id, sm_code, sm_image, sm_position
FROM ::smilies
ORDER BY sm_position';
$list = $this->c->DB->query($query)->fetchAll(PDO::FETCH_UNIQUE);

View file

@ -0,0 +1,35 @@
<?php
namespace ForkBB\Models\SmileyList;
use ForkBB\Models\Method;
use ForkBB\Models\SmileyList\Model as SmileyList;
use InvalidArgumentException;
class Update extends Method
{
/**
* Обновляет запись в БД для смайла
*/
public function update(int $id, array $data): SmileyList
{
if (
isset($data['id'])
|| ! isset($data['sm_code'], $data['sm_position'], $data['sm_image'])
|| '' == $data['sm_code']
|| '' == $data['sm_image']
) {
throw new InvalidArgumentException('Expected an array with a smile description');
}
$data[':id'] = $id;
$query = 'UPDATE ::smilies
SET sm_code=?s:sm_code, sm_position=?i:sm_position, sm_image=?s:sm_image
WHERE id=?i:id';
$this->c->DB->exec($query, $data);
return $this->model;
}
}

View file

@ -42,7 +42,7 @@ if (
}
$c->PUBLIC_URL = $c->BASE_URL . $forkPublicPrefix;
$c->FORK_REVISION = 14;
$c->FORK_REVISION = 15;
$c->START = $forkStart;
$c->DIR_APP = __DIR__;
$c->DIR_PUBLIC = $forkPublic;

View file

@ -140,6 +140,11 @@ return [
'SubscriptionModelSend' => \ForkBB\Models\Subscription\Send::class,
'BanListModelIsBanned' => \ForkBB\Models\BanList\IsBanned::class,
'SmileyListModelLoad' => \ForkBB\Models\SmileyList\Load::class,
'SmileyListModelUpdate' => \ForkBB\Models\SmileyList\Update::class,
'SmileyListModelInsert' => \ForkBB\Models\SmileyList\Insert::class,
'SmileyListModelDelete' => \ForkBB\Models\SmileyList\Delete::class,
],
'multiple' => [
'CtrlPrimary' => \ForkBB\Controllers\Primary::class,
@ -221,7 +226,6 @@ return [
'AdminListModel' => \ForkBB\Models\AdminList\Model::class,
'SmileyListModel' => \ForkBB\Models\SmileyList\Model::class,
'SmileyListModelLoad' => \ForkBB\Models\SmileyList\Load::class,
'DBMapModel' => \ForkBB\Models\DBMap\Model::class,

View file

@ -48,10 +48,10 @@ msgstr "Allow the BBCode [img][/img] tag in user signatures (not recommended)."
msgid "Smilies subhead"
msgstr "Smilies"
msgid "Smilies label"
msgid "Smilies mess label"
msgstr "Smilies in posts"
msgid "Smilies help"
msgid "Smilies mess help"
msgstr "Convert smilies to small graphic icons."
msgid "Smilies sigs label"
@ -71,3 +71,72 @@ msgstr "Maximum [quote] depth"
msgid "Quote depth help"
msgstr "The maximum times a [quote] tag can go inside other [quote] tags, any tags deeper than this will be discarded."
msgid "BBCode management"
msgstr "BBCode management"
msgid "Smilies management"
msgstr "Smilies management"
msgid "Smilies head"
msgstr "Smilies"
msgid "Available images head"
msgstr "Available images"
msgid "Available images subhead"
msgstr "Available images"
msgid "Upload image head"
msgstr "Upload image"
msgid "Upload image subhead"
msgstr "Upload"
msgid "Picture label"
msgstr "Picture"
msgid "<img src=\"%1$s\" alt=\"%2$s\">"
msgstr "<img src=\"%1$s\" alt=\"%2$s\">"
msgid "Name label"
msgstr "File name"
msgid "File %s deleted redirect"
msgstr "File '%s' deleted."
msgid "File %s not deleted redirect"
msgstr "File '%s' not deleted."
msgid "Upload"
msgstr "Upload"
msgid "Upload image label"
msgstr "New image"
msgid "Upload image info"
msgstr "Select an image file to upload."
msgid "Image uploaded redirect"
msgstr "Image uploaded."
msgid "Smilies list subhead"
msgstr "Smilies list"
msgid "Smiley number %s"
msgstr "Smile #%s"
msgid "Smiley code label"
msgstr "Code"
msgid "Position label"
msgstr "Position"
msgid "New smile subhead"
msgstr "New smile"
msgid "Smilies updated redirect"
msgstr "Smilies updated."
msgid "Smile deleted redirect"
msgstr "Smile deleted."

View file

@ -48,10 +48,10 @@ msgstr "Разрешить тег [img][/img] в подписях пользов
msgid "Smilies subhead"
msgstr "Смайлы"
msgid "Smilies label"
msgid "Smilies mess label"
msgstr "Смайлы в сообщениях"
msgid "Smilies help"
msgid "Smilies mess help"
msgstr "Преобразовывать смайлы из сообщений в графические иконки."
msgid "Smilies sigs label"
@ -71,3 +71,72 @@ msgstr "Максимальная глубина [quote]"
msgid "Quote depth help"
msgstr "Сколько раз тег [quote] может вкладываться в другие [quote], все теги свыше указанного порога будут игнорироваться."
msgid "BBCode management"
msgstr "Управление BB-кодами"
msgid "Smilies management"
msgstr "Управление смайлами"
msgid "Smilies head"
msgstr "Смайлы"
msgid "Available images head"
msgstr "Доступные изображения"
msgid "Available images subhead"
msgstr "Доступные изображения"
msgid "Upload image head"
msgstr "Загрузка изображения"
msgid "Upload image subhead"
msgstr "Загрузка"
msgid "Picture label"
msgstr "Изображение"
msgid "<img src=\"%1$s\" alt=\"%2$s\">"
msgstr "<img src=\"%1$s\" alt=\"%2$s\">"
msgid "Name label"
msgstr "Имя файла"
msgid "File %s deleted redirect"
msgstr "Файл '%s' удален."
msgid "File %s not deleted redirect"
msgstr "Файл '%s' не получилось удалить."
msgid "Upload"
msgstr "Загрузить"
msgid "Upload image label"
msgstr "Новое изображение"
msgid "Upload image info"
msgstr "Выберите файл изображения для загрузки."
msgid "Image uploaded redirect"
msgstr "Изображение загружено."
msgid "Smilies list subhead"
msgstr "Список смайлов"
msgid "Smiley number %s"
msgstr "Смайл #%s"
msgid "Smiley code label"
msgstr "Код"
msgid "Position label"
msgstr "Позиция"
msgid "New smile subhead"
msgstr "Новый смайл"
msgid "Smilies updated redirect"
msgstr "Смайлы обновлены."
msgid "Smile deleted redirect"
msgstr "Смайл удален."

View file

@ -0,0 +1,25 @@
@extends ('layouts/admin')
@if ($form = $p->formSmilies)
<section class="f-admin f-smilies-form">
<h2>{!! __('Smilies head') !!}</h2>
<div class="f-fdiv">
@include ('layouts/form')
</div>
</section>
@endif
@if ($form = $p->formImages)
<section class="f-admin f-images-list">
<h2>{!! __('Available images head') !!}</h2>
<div class="f-fdiv">
@include ('layouts/form')
</div>
</section>
@endif
@if ($form = $p->formUploadImage)
<section class="f-admin f-image-upload-form">
<h2>{!! __('Upload image head') !!}</h2>
<div class="f-fdiv">
@include ('layouts/form')
</div>
</section>
@endif

View file

@ -2079,7 +2079,6 @@ body,
#fork .f-fs-forum {
display: flex;
align-items: stretch;
/*min-width: 0;*/
}
#fork .f-fs-forum > legend {
@ -2922,3 +2921,131 @@ body,
padding-bottom: 0;
}
}
/****************************************/
/* Админка/Парсер */
/****************************************/
#fork .f-smilies-form .f-fs-new-smile,
#fork .f-images-list .f-fdiv {
display: flex;
flex-wrap: wrap;
}
#fork .f-images-list .f-fs-image {
display: flex;
align-items: center;
border: 0.0625rem dotted #AA7939;
margin: 0.3125rem;
}
#fork #id-fs-image-legend {
width: 100%;
}
#fork .f-images-list .f-field-image {
border: 0;
margin: 0;
}
#fork .f-smilies-form .f-fs-smile > legend,
#fork .f-smilies-form .f-fs-new-smile > legend {
border-top: 0.0625rem dotted #AA7939;
}
#fork .f-images-list .f-fs-image > legend,
#fork .f-images-list .f-field-image > dt {
display: none;
}
#fork .f-images-list .f-field-image > dd {
width: 100%;
}
#fork .f-field-pic img {
max-width: 100%;
min-width: 1rem;
height: auto;
}
#fork .f-images-list .f-field-name {
max-width: 80%;
}
#fork .f-smilies-form .f-field-new-smile {
display: flex;
flex-direction: column;
width: 33.33%;
}
#fork .f-smilies-form .f-field-new-smile .f-child1 {
font-weight: normal;
}
#fork .f-smilies-form .f-field-new-smile > dt {
width: 100%;
white-space: nowrap;
overflow: hidden;
}
#fork .f-smilies-form .f-field-new-smile > dd {
width: 100%;
}
@media screen and (min-width: 35rem) {
#fork .f-smilies-form .f-fs-smile {
display: flex;
}
#fork .f-smilies-form .f-field-smile {
display: flex;
flex-direction: column;
/* justify-content: space-between; */
}
#fork .f-smilies-form .f-fs-smile > legend,
#fork .f-smilies-form .f-field-smile > dt {
display: none;
}
#fork .f-fs-smilies-legend + .f-fs-smile .f-field-smile > dt {
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
}
#fork .f-smilies-form .f-field-smile .f-child1 {
font-weight: normal;
}
#fork .f-smilies-form .f-field-smile > dd {
width: 100%;
flex-grow: 1;
}
#fork .f-field-smile.f-field-code {
width: 10rem;
}
#fork .f-field-smile.f-field-position {
width: 5rem;
}
#fork .f-field-smile.f-field-image {
width: 12rem;
}
#fork .f-field-smile.f-field-pic {
width: calc(100% - 30rem);
text-align: center;
}
#fork .f-field-smile.f-field-delete {
width: 3rem;
}
#fork .f-smilies-form .f-fs-new-smile > legend {
border-top: 0;
}
}