feat(admin): open ticket creation in a dialog on the list page
Move "代客提交工单" back into a native <dialog> on the ticket list while the ticket workspace stays a full page. Closing asks before discarding input, ignores backdrop clicks, resets the form and returns focus; an uncertain create result keeps the form locked behind "重新加载". Remove the ?view=new create page route and its styles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d86a85e6a6
commit
54cc5301c3
9 files changed
+169
-65
No files matched your search
@@ -13,12 +13,13 @@ function rendered() {
|
||||
return fixture;
|
||||
}
|
||||
|
||||
test('list view links to page views and renders no dialogs or eager conversations', () => {
|
||||
test('list view links rows to the workspace and offers creation only as a dialog', () => {
|
||||
const { list, initial } = rendered();
|
||||
assert.doesNotMatch(list, /<dialog|data-aksrt-dialog-open|aria-haspopup="dialog"/);
|
||||
assert.match(list, /aksrt-native-header__actions[^]*href="[^"]*page=aksrt_tickets&view=new&status=handling&ticket_type_id=1&s=needle&paged=2"/);
|
||||
assert.equal((list.match(/<dialog /g) || []).length, 1, 'only the create dialog');
|
||||
assert.match(list, /aksrt-native-header__actions[^]*data-aksrt-dialog-open="aksrt-ticket-create-dialog"/);
|
||||
assert.doesNotMatch(list, /view=new/);
|
||||
assert.match(list, /<a class="row-title" href="[^"]*page=aksrt_tickets&id=21&status=handling&ticket_type_id=1&s=needle&paged=2"/);
|
||||
assert.doesNotMatch(list, /data-aksrt-ticket-detail=|data-aksrt-ticket-form=/);
|
||||
assert.doesNotMatch(list, /data-aksrt-ticket-detail=|data-aksrt-ticket-form="(?:reply|status|note)"/);
|
||||
assert.equal(initial.detail_reads, 0);
|
||||
assert.equal(initial.reply_reads, 0);
|
||||
assert.equal(initial.queries.at(-1).offset, 20);
|
||||
@@ -88,14 +89,14 @@ test('missing ticket renders an empty state with a way back and no forms', () =>
|
||||
assert.doesNotMatch(missing, /data-aksrt-ticket-form|data-aksrt-ticket-detail/);
|
||||
});
|
||||
|
||||
test('create page is a full-page form that posts to REST and returns to the list context', () => {
|
||||
const { create } = rendered();
|
||||
assert.doesNotMatch(create, /<dialog|data-aksrt-dialog/);
|
||||
assert.match(create, /<form method="post" action="https:\/\/example.test\/wp-json\/aksrt\/v1\/admin\/tickets" class="aksrt-tickets-admin__create-form" data-aksrt-ticket-form="create">/);
|
||||
for (const name of ['user_id', 'ticket_type_id', 'title', 'order_number', 'content']) assert.ok(create.includes(`name="${name}"`), name);
|
||||
assert.match(create, /data-aksrt-ticket-feedback/);
|
||||
const back = /href="[^"]*page=aksrt_tickets&status=pending&paged=2"/g;
|
||||
assert.equal((create.match(back) || []).length, 2, 'header back link and cancel both keep the list context');
|
||||
test('create dialog is a labelled REST form with its own feedback and close controls', () => {
|
||||
const { list } = rendered();
|
||||
const dialog = list.match(/<dialog id="aksrt-ticket-create-dialog"[^]*?<\/dialog>/)?.[0] || '';
|
||||
assert.match(dialog, /aria-labelledby="aksrt-ticket-create-title"/);
|
||||
assert.match(dialog, /<form method="post" action="https:\/\/example.test\/wp-json\/aksrt\/v1\/admin\/tickets" class="aksrt-ticket-dialog__frame" data-aksrt-ticket-form="create">/);
|
||||
for (const name of ['user_id', 'ticket_type_id', 'title', 'order_number', 'content']) assert.ok(dialog.includes(`name="${name}"`), name);
|
||||
assert.match(dialog, /data-aksrt-ticket-feedback/);
|
||||
assert.equal((dialog.match(/data-aksrt-dialog-close/g) || []).length, 2, 'header X and footer cancel');
|
||||
});
|
||||
|
||||
test('real rendering escapes user content, quotes and metadata', () => {
|
||||
|
||||
Reference in new issue
Block a user