fix pages editing
This commit is contained in:
parent
1ab8659a21
commit
68a04ab18d
@ -131,6 +131,10 @@ class mysql {
|
||||
return $q;
|
||||
}
|
||||
|
||||
function error() {
|
||||
return $this->link?->error;
|
||||
}
|
||||
|
||||
function fetch($q): ?array {
|
||||
$row = $q->fetch_assoc();
|
||||
if (!$row) {
|
||||
|
@ -39,7 +39,7 @@ function render($f, ...$vars): void {
|
||||
$lang = [];
|
||||
foreach ($SkinState->lang as $key)
|
||||
$lang[$key] = lang($key);
|
||||
$lang = !empty($lang) ? json_encode($lang, JSON_UNESCAPED_UNICODE) : '';
|
||||
$lang = !empty($lang) ? jsonEncode($lang, JSON_UNESCAPED_UNICODE) : '';
|
||||
|
||||
$title = $SkinState->title;
|
||||
if (!$SkinState->options['is_index'])
|
||||
|
@ -122,6 +122,8 @@ class AdminHandler extends request_handler {
|
||||
}
|
||||
|
||||
function POST_ajax_md_preview() {
|
||||
if (!is_xhr_request())
|
||||
forbidden();
|
||||
list($md, $title, $use_image_previews) = input('md, title, b:use_image_previews');
|
||||
$html = markup::markdownToHtml($md, $use_image_previews);
|
||||
$ctx = new SkinContext('\\skin\\admin');
|
||||
@ -136,8 +138,16 @@ class AdminHandler extends request_handler {
|
||||
list($name) = input('short_name');
|
||||
$page = pages::getByName($name);
|
||||
if ($page)
|
||||
not_found();
|
||||
return $this->_get_pageAdd($name);
|
||||
redirect($page->getUrl(), code: HTTPCode::Found);
|
||||
add_skin_strings_re('/^(err_)?pages_/');
|
||||
add_skin_strings_re('/^(err_)?blog_/');
|
||||
set_title(lang('pages_create_title', $name));
|
||||
static::make_wide();
|
||||
render('admin/pageForm',
|
||||
short_name: $name,
|
||||
title: '',
|
||||
text: '',
|
||||
langs: PostLanguage::cases());
|
||||
}
|
||||
|
||||
function POST_page_add() {
|
||||
@ -168,7 +178,7 @@ class AdminHandler extends request_handler {
|
||||
}
|
||||
|
||||
$page = pages::getByName($name);
|
||||
redirect($page->getUrl());
|
||||
ajax_ok(['url' => $page->getUrl()]);
|
||||
}
|
||||
|
||||
function GET_post_add() {
|
||||
@ -265,9 +275,11 @@ class AdminHandler extends request_handler {
|
||||
if (!$page)
|
||||
not_found();
|
||||
|
||||
$url = $page->getUrl();
|
||||
|
||||
csrf_check('delpage'.$page->shortName);
|
||||
pages::delete($page);
|
||||
redirect('/');
|
||||
redirect($url, code: HTTPCode::Found);
|
||||
}
|
||||
|
||||
function GET_post_delete() {
|
||||
@ -279,7 +291,7 @@ class AdminHandler extends request_handler {
|
||||
|
||||
csrf_check('delpost'.$post->id);
|
||||
posts::delete($post);
|
||||
redirect('/articles/');
|
||||
redirect('/articles/', code: HTTPCode::Found);
|
||||
}
|
||||
|
||||
function GET_post_edit() {
|
||||
@ -400,19 +412,35 @@ class AdminHandler extends request_handler {
|
||||
if (!$page)
|
||||
not_found();
|
||||
|
||||
return $this->_get_pageEdit($page,
|
||||
add_skin_strings_re('/^(err_)?pages_/');
|
||||
add_skin_strings_re('/^(err_)?blog_/');
|
||||
set_title(lang('pages_page_edit_title', $page->shortName.'.html'));
|
||||
static::make_wide();
|
||||
$js_text = [
|
||||
'text' => $page->md,
|
||||
'title' => $page->title,
|
||||
];
|
||||
render('admin/pageForm',
|
||||
is_edit: true,
|
||||
short_name: $page->shortName,
|
||||
title: $page->title,
|
||||
text: $page->md,
|
||||
saved: $saved,
|
||||
visible: $page->visible,
|
||||
);
|
||||
saved: $saved,
|
||||
langs: PostLanguage::cases(),
|
||||
js_text: $js_text);
|
||||
}
|
||||
|
||||
function POST_auto_edit() {
|
||||
function POST_page_edit() {
|
||||
if (!is_xhr_request())
|
||||
forbidden();
|
||||
|
||||
list($short_name) = input('short_name');
|
||||
|
||||
$page = pages::getByName($short_name);
|
||||
if ($page) {
|
||||
if (!$page)
|
||||
not_found();
|
||||
|
||||
csrf_check('editpage'.$page->shortName);
|
||||
|
||||
list($text, $title, $visible, $short_name)
|
||||
@ -430,13 +458,8 @@ class AdminHandler extends request_handler {
|
||||
$error_code = 'no_short_name';
|
||||
}
|
||||
|
||||
if ($error_code) {
|
||||
return $this->_get_pageEdit($page,
|
||||
title: $title,
|
||||
text: $text,
|
||||
visible: $visible,
|
||||
);
|
||||
}
|
||||
if ($error_code)
|
||||
ajax_error(['code' => $error_code]);
|
||||
|
||||
$page->edit([
|
||||
'title' => $title,
|
||||
@ -445,10 +468,7 @@ class AdminHandler extends request_handler {
|
||||
'short_name' => $short_name,
|
||||
]);
|
||||
|
||||
redirect($page->getUrl().'edit/?saved=1');
|
||||
}
|
||||
|
||||
not_found();
|
||||
ajax_ok(['url' => $page->getUrl().'edit/?saved=1']);
|
||||
}
|
||||
|
||||
protected static function make_wide() {
|
||||
@ -458,38 +478,4 @@ class AdminHandler extends request_handler {
|
||||
]);
|
||||
}
|
||||
|
||||
protected function _get_pageAdd(
|
||||
string $name,
|
||||
string $title = '',
|
||||
string $text = ''
|
||||
) {
|
||||
add_skin_strings_re('/^(err_)?pages_/');
|
||||
set_title(lang('pages_create_title', $name));
|
||||
static::make_wide();
|
||||
render('admin/pageForm',
|
||||
short_name: $name,
|
||||
title: $title,
|
||||
text: $text);
|
||||
}
|
||||
|
||||
protected function _get_pageEdit(
|
||||
Page $page,
|
||||
string $title = '',
|
||||
string $text = '',
|
||||
bool $saved = false,
|
||||
bool $visible = false,
|
||||
?string $error_code = null
|
||||
) {
|
||||
add_skin_strings_re('/^(err_)?pages_/');
|
||||
set_title(lang('pages_page_edit_title', $page->shortName.'.html'));
|
||||
static::make_wide();
|
||||
render('admin/pageForm',
|
||||
is_edit: true,
|
||||
short_name: $page->shortName,
|
||||
title: $title,
|
||||
text: $text,
|
||||
visible: $visible,
|
||||
saved: $saved);
|
||||
}
|
||||
|
||||
}
|
@ -7,16 +7,14 @@ class AdminWriteEditForm {
|
||||
this.previewRequest = null
|
||||
this.tocByLang = {}
|
||||
|
||||
if (!this.isEditing()) {
|
||||
if (!this.isEditing() && this.isPost()) {
|
||||
for (const l of opts.langs) {
|
||||
this.tocByLang[l] = false
|
||||
}
|
||||
}
|
||||
|
||||
this.form.addEventListener('submit', this.onSubmit)
|
||||
if (this.isPost())
|
||||
this.form.title.addEventListener('input', this.onInput)
|
||||
|
||||
this.form.text.addEventListener('input', this.onInput)
|
||||
ge('toggle_wrap').addEventListener('click', this.onToggleWrapClick)
|
||||
|
||||
@ -46,6 +44,7 @@ class AdminWriteEditForm {
|
||||
|
||||
this.draft = new Draft(draftId, lang);
|
||||
if (this.isEditing()) {
|
||||
if (this.isPost()) {
|
||||
for (let l in opts.texts) {
|
||||
this.draft.setLang(l)
|
||||
this.draft.title = opts.texts[l].title
|
||||
@ -53,6 +52,10 @@ class AdminWriteEditForm {
|
||||
this.tocByLang[l] = opts.texts[l].toc
|
||||
}
|
||||
this.draft.setLang(lang)
|
||||
} else {
|
||||
this.draft.title = opts.text.title
|
||||
this.draft.text = opts.text.text
|
||||
}
|
||||
this.showPreview()
|
||||
} else {
|
||||
this.fillFromDraft()
|
||||
@ -131,14 +134,16 @@ class AdminWriteEditForm {
|
||||
}
|
||||
|
||||
// fd.append('lang', this.getCurrentLang())
|
||||
if (this.isPost())
|
||||
fd.append('visible', ge('visible_cb').checked ? 1 : 0)
|
||||
|
||||
// language-specific fields
|
||||
// text-specific fields
|
||||
let atLeastOneLangIsWritten = false
|
||||
const writtenLangs = []
|
||||
if (this.isPost()) {
|
||||
for (const l of this.opts.langs) {
|
||||
let title = this.draft.getForLang(l, 'title')
|
||||
let text = this.draft.getForLang(l, 'text')
|
||||
const title = this.draft.getForLang(l, 'title')
|
||||
const text = this.draft.getForLang(l, 'text')
|
||||
console.log(`lang: ${l}`, title, text)
|
||||
if (title !== '' && text !== '')
|
||||
atLeastOneLangIsWritten = true
|
||||
@ -147,16 +152,27 @@ class AdminWriteEditForm {
|
||||
fd.append(`toc:${l}`, this.tocByLang[l] ? 1 : 0)
|
||||
writtenLangs.push(l)
|
||||
}
|
||||
} else {
|
||||
const title = this.draft.title
|
||||
const text = this.draft.text
|
||||
if (title !== '' && text !== '') {
|
||||
atLeastOneLangIsWritten = true
|
||||
fd.append('title', title)
|
||||
fd.append('text', text)
|
||||
}
|
||||
}
|
||||
if (!atLeastOneLangIsWritten)
|
||||
throw 'no_text'
|
||||
|
||||
fd.append('langs', writtenLangs.join(','))
|
||||
|
||||
// date field
|
||||
if (this.isPost()) {
|
||||
const dateInput = evt.target.elements.date;
|
||||
if (!dateInput.value)
|
||||
throw 'no_date'
|
||||
fd.append('date', dateInput.value)
|
||||
}
|
||||
|
||||
fd.append('token', this.opts.token)
|
||||
cancelEvent(evt)
|
||||
|
@ -44,13 +44,13 @@ class Page extends model {
|
||||
|
||||
class pages {
|
||||
|
||||
static function add(array $data): ?int {
|
||||
static function add(array $data): bool {
|
||||
$db = DB();
|
||||
$data['ts'] = time();
|
||||
$data['html'] = markup::markdownToHtml($data['md']);
|
||||
if (!$db->insert('pages', $data))
|
||||
return null;
|
||||
return $db->insertId();
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static function delete(Page $page): void {
|
||||
|
@ -269,20 +269,30 @@ function pageForm($ctx,
|
||||
string|Stringable $title,
|
||||
string|Stringable $text,
|
||||
string|Stringable $short_name,
|
||||
array $langs,
|
||||
bool $is_edit = false,
|
||||
$error_code = null,
|
||||
?bool $saved = null,
|
||||
bool $visible = false): array {
|
||||
bool $visible = false,
|
||||
?array $js_text = null): array {
|
||||
$form_url = '/'.$short_name.'/'.($is_edit ? 'edit' : 'create').'/';
|
||||
|
||||
// breadcrumbs
|
||||
if ($is_edit) {
|
||||
$bc_html = $ctx->bc([
|
||||
['url' => '/'.$short_name.'/', 'text' => $ctx->lang('view_page')]
|
||||
], 'padding-bottom: 20px');
|
||||
} else {
|
||||
$bc_html = '';
|
||||
}
|
||||
|
||||
$html = <<<HTML
|
||||
{$ctx->if_true($error_code, fn() => '<div class="form-error">'.$ctx->lang('err_pages_'.$error_code).'</div>')}
|
||||
<div class="form-error" id="form-error" style="display:none"></div>
|
||||
{$ctx->if_true($saved, fn() => '<div class="form-success">'.$ctx->lang('info_saved').'</div>')}
|
||||
{$bc_html}
|
||||
<table cellpadding="0" cellspacing="0" class="blog-write-table">
|
||||
<tr>
|
||||
<td id="form_first_cell">
|
||||
<form class="blog-write-form form-layout-v" name="pageForm" action="{$form_url}" method="post">
|
||||
<input type="hidden" name="token" value="{$ctx->if_then_else($is_edit, $ctx->csrf('editpage'.$short_name), $ctx->csrf('addpage'))}" />
|
||||
|
||||
<div class="form-field-wrap clearfix">
|
||||
<div class="form-field-label">{$ctx->lang('pages_write_form_title')}</div>
|
||||
<div class="form-field">
|
||||
@ -312,7 +322,16 @@ $html = <<<HTML
|
||||
</table>
|
||||
HTML;
|
||||
|
||||
$js_params = json_encode(['pages' => true, 'edit' => $is_edit]);
|
||||
$js_params = [
|
||||
'pages' => true,
|
||||
'edit' => $is_edit,
|
||||
'token' => $is_edit ? $ctx->csrf('editpage'.$short_name) : $ctx->csrf('addpage'),
|
||||
'langs' => array_map(fn($lang) => $lang->value, $langs), // still needed for draft erasing
|
||||
];
|
||||
if ($js_text !== null)
|
||||
$js_params['text'] = $js_text;
|
||||
$js_params = jsonEncode($js_params);
|
||||
|
||||
$js = <<<JS
|
||||
cur.form = new AdminWriteEditForm({$js_params});
|
||||
JS;
|
||||
|
@ -7,7 +7,7 @@ use Stringable;
|
||||
|
||||
function layout($ctx, $title, $unsafe_body, $static, $meta, $js, $opts, $unsafe_lang, $theme, $exec_time, $admin_email) {
|
||||
global $config;
|
||||
$app_config = json_encode([
|
||||
$app_config = jsonEncode([
|
||||
'domain' => $config['domain'],
|
||||
'devMode' => $config['is_dev'],
|
||||
'cookieHost' => $config['cookie_host'],
|
||||
@ -64,7 +64,7 @@ HTML;
|
||||
function renderScript($ctx, $unsafe_js, $unsafe_lang) {
|
||||
global $config;
|
||||
|
||||
$styles = json_encode($ctx->styleNames);
|
||||
$styles = jsonEncode($ctx->styleNames);
|
||||
if ($config['is_dev'])
|
||||
$versions = '{}';
|
||||
else {
|
||||
@ -73,7 +73,7 @@ else {
|
||||
list($type, $bname) = getStaticNameParts($name);
|
||||
$versions[$type][$bname] = $v;
|
||||
}
|
||||
$versions = json_encode($versions);
|
||||
$versions = jsonEncode($versions);
|
||||
}
|
||||
|
||||
return <<<HTML
|
||||
|
@ -20,6 +20,7 @@ toc: 'Table of Contents'
|
||||
# blog
|
||||
blog_new_post: "New post"
|
||||
blog_view_post: "View post"
|
||||
view_page: "View page"
|
||||
#blog_editing: "Editing..."
|
||||
blog_latest: 'Latest posts'
|
||||
blog_no: 'No posts yet.'
|
||||
|
Loading…
x
Reference in New Issue
Block a user