Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[studio] emphasize the action name in confirmation dialog #1439 #1440

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion agdb_studio/src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ ul {
}
}

@media (min-width: 1024px) {
.emphesized {
color: #ff8800;
font-weight: bold;
}
9 changes: 5 additions & 4 deletions agdb_studio/src/components/base/modal/AgdbModal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { describe, beforeEach, it, expect } from "vitest";
import useModal from "@/composables/modal/modal";
import AgdbModal from "./AgdbModal.vue";
import { mount } from "@vue/test-utils";
import { convertArrayOfStringsToContent } from "@/utils/content";

describe("AgdbModal", () => {
const { showModal, hideModal } = useModal();
Expand All @@ -14,15 +15,15 @@ describe("AgdbModal", () => {
expect(wrapper.isVisible()).toBe(false);
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
});
await wrapper.vm.$nextTick();
expect(wrapper.isVisible()).toBe(true);
});
it("hides a modal when clicked on close button", async () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
});
await wrapper.vm.$nextTick();
await wrapper.find(".modal-footer .button").trigger("click");
Expand All @@ -32,7 +33,7 @@ describe("AgdbModal", () => {
it("hides a modal when clicked on close button in heades", async () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
});
await wrapper.vm.$nextTick();
await wrapper.find(".modal-header .close-button").trigger("click");
Expand All @@ -42,7 +43,7 @@ describe("AgdbModal", () => {
it("shows a modal with custom buttons", async () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
buttons: [
{
className: "button",
Expand Down
15 changes: 11 additions & 4 deletions agdb_studio/src/components/base/modal/AgdbModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@
import useModal from "@/composables/modal/modal";
import { ClCloseMd } from "@kalimahapps/vue-icons";

const { content, buttons, hideModal, modalIsVisible } = useModal();
const { modal, buttons, hideModal, modalIsVisible } = useModal();
</script>

<template>
<div v-if="modalIsVisible" class="modal-background">
<section class="modal">
<header class="modal-header">
<h3>{{ content.header }}</h3>
<h3>{{ modal.header }}</h3>
<button @click="hideModal" class="close-button">
<ClCloseMd />
</button>
</header>
<div class="modal-body">
<p v-for="(paragraph, index) in content.body" :key="index">
{{ paragraph }}
<p v-for="(paragraph, index) in modal.content" :key="index">
<span
v-for="(text, index2) in paragraph.paragraph"
:key="index2"
:style="text.style"
:class="text.className"
>
{{ text.text }}
</span>
</p>
</div>
<footer class="modal-footer">
Expand Down
5 changes: 3 additions & 2 deletions agdb_studio/src/components/base/table/AgdbCellMenu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { describe, beforeEach, vi, it, expect } from "vitest";
import { dbActions } from "@/composables/db/dbConfig";
import { INJECT_KEY_ROW } from "@/composables/table/constants";
import useModal from "@/composables/modal/modal";
import { convertArrayOfStringsToContent } from "@/utils/content";
const { fetchDatabases } = vi.hoisted(() => {
return {
fetchDatabases: vi.fn(),
Expand Down Expand Up @@ -84,10 +85,10 @@ describe("AgdbCellMenu", () => {
});
it("should open the modal on click when confirmation is required", async () => {
const deleteAction = vi.fn();
const deleteConfirmation = [
const deleteConfirmation = convertArrayOfStringsToContent([
"Are you sure you want to delete this database?",
"This will permanently delete all data.",
];
]);
const wrapper = mount(AgdbCellMenu, {
props: {
actions: [
Expand Down
2 changes: 1 addition & 1 deletion agdb_studio/src/components/base/table/AgdbCellMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const mapActions = (actions: Action[]): Action[] => {
? ({ event }: ActionProps<undefined>) =>
showModal({
header: "Confirm action",
body: action.confirmation,
content: action.confirmation,
onConfirm: () =>
runAction({ event, params: undefined }),
})
Expand Down
114 changes: 78 additions & 36 deletions agdb_studio/src/composables/db/dbConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ServerDatabase } from "agdb_api/dist/openapi";
import { client } from "@/services/api.service";
import { dateFormatter } from "@/composables/table/utils";
import { convertArrayOfStringsToContent } from "@/utils/content";

type DbActionProps = ActionProps<ServerDatabase>;
const dbActions: Action[] = [
Expand All @@ -17,8 +18,13 @@ const dbActions: Action[] = [
label: "Backup",
action: ({ params }: DbActionProps) => client.value?.db_backup(params),
confirmation: [
"Are you sure you want to backup this database?",
"This will swap the existing backup with the current db.",
...convertArrayOfStringsToContent(
["Are you sure you want to backup this database?"],
{ emphesizedWords: ["backup"] },
),
...convertArrayOfStringsToContent([
"This will swap the existing backup with the current db.",
]),
],
},
{
Expand All @@ -30,38 +36,50 @@ const dbActions: Action[] = [
label: "All",
action: ({ params }: DbActionProps) =>
client.value?.db_clear({ ...params, resource: "all" }),
confirmation: [
"Are you sure you want to clear all resources of this database?",
"This will reset the database.",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to clear all resources of this database?",
"This will reset the database.",
],
{ emphesizedWords: ["clear", "all"] },
),
},
{
key: "db",
label: "Db only",
action: ({ params }: DbActionProps) =>
client.value?.db_clear({ ...params, resource: "db" }),
confirmation: [
"Are you sure you want to clear this database?",
"This will remove all data.",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to clear this database?",
"This will remove all data.",
],
{ emphesizedWords: ["clear", "database"] },
),
},
{
key: "audit",
label: "Audit only",
action: ({ params }: DbActionProps) =>
client.value?.db_clear({ ...params, resource: "audit" }),
confirmation: [
"Are you sure you want to clear the audit log of this database?",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to clear the audit log of this database?",
],
{ emphesizedWords: ["clear", "audit"] },
),
},
{
key: "backup",
label: "Backup only",
action: ({ params }: DbActionProps) =>
client.value?.db_clear({ ...params, resource: "backup" }),
confirmation: [
"Are you sure you want to clear the backup of this database?",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to clear the backup of this database?",
],
{ emphesizedWords: ["clear", "backup"] },
),
},
],
},
Expand All @@ -74,27 +92,36 @@ const dbActions: Action[] = [
label: "Memory",
action: ({ params }: DbActionProps) =>
client.value?.db_convert({ ...params, db_type: "memory" }),
confirmation: [
"Are you sure you want to convert this database to memory only?",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to convert this database to memory only?",
],
{ emphesizedWords: ["convert", "memory"] },
),
},
{
key: "file",
label: "File",
action: ({ params }: DbActionProps) =>
client.value?.db_convert({ ...params, db_type: "file" }),
confirmation: [
"Are you sure you want to convert this database to file based database?",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to convert this database to file based database?",
],
{ emphesizedWords: ["convert", "file"] },
),
},
{
key: "mapped",
label: "Mapped",
action: ({ params }: DbActionProps) =>
client.value?.db_convert({ ...params, db_type: "mapped" }),
confirmation: [
"Are you sure you want to convert this database to memory mapped database?",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to convert this database to memory mapped database?",
],
{ emphesizedWords: ["convert", "mapped"] },
),
},
],
},
Expand All @@ -109,26 +136,38 @@ const dbActions: Action[] = [
label: "Delete",
action: ({ params }: DbActionProps) => client.value?.db_delete(params),
confirmation: [
"Are you sure you want to delete this database?",
"This will permanently delete all data.",
...convertArrayOfStringsToContent(
["Are you sure you want to delete this database?"],
{ emphesizedWords: ["delete"] },
),
...convertArrayOfStringsToContent(
["This will permanently delete all data."],
{ emphesizedWords: ["all data"] },
),
],
},
{
key: "optimize",
label: "Optimize",
action: ({ params }: DbActionProps) =>
client.value?.db_optimize(params),
confirmation: ["Are you sure you want to optimize this database?"],
confirmation: convertArrayOfStringsToContent(
["Are you sure you want to optimize this database?"],
{ emphesizedWords: ["optimize"] },
),
},

{
key: "remove",
label: "Remove",
action: ({ params }: DbActionProps) => client.value?.db_remove(params),
confirmation: [
"Are you sure you want to remove this database?",
"This will only disassociate the database from the server. No data will be deleted.",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to remove this database?",
"This will only disassociate the database from the server. No data will be deleted.",
],
{ emphesizedWords: ["remove"] },
),
},
// todo: implement input for db name
// {
Expand All @@ -140,10 +179,13 @@ const dbActions: Action[] = [
key: "restore",
label: "Restore",
action: ({ params }: DbActionProps) => client.value?.db_restore(params),
confirmation: [
"Are you sure you want to restore backup of this database?",
"This will swap the existing db with the backup.",
],
confirmation: convertArrayOfStringsToContent(
[
"Are you sure you want to restore backup of this database?",
"This will swap the existing db with the backup.",
],
{ emphesizedWords: ["restore"] },
),
},
];

Expand Down
15 changes: 8 additions & 7 deletions agdb_studio/src/composables/modal/modal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, beforeEach, vi, it, expect } from "vitest";
import useModal from "./modal";
import { convertArrayOfStringsToContent } from "@/utils/content";

describe("Modal", () => {
const { showModal, hideModal } = useModal();
Expand All @@ -9,22 +10,22 @@ describe("Modal", () => {
it("shows a modal", () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
});
expect(useModal().modalIsVisible.value).toBe(true);
});
it("hides a modal", () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
});
hideModal();
expect(useModal().modalIsVisible.value).toBe(false);
});
it("shows a modal with custom buttons", () => {
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
buttons: [
{
className: "button",
Expand All @@ -40,16 +41,16 @@ describe("Modal", () => {
const onConfirm = vi.fn();
showModal({
header: "Test Header",
body: ["Test Body"],
content: convertArrayOfStringsToContent(["Test Body"]),
onConfirm,
});
useModal().buttons.value[1].action();
expect(onConfirm).toHaveBeenCalled();
expect(useModal().modalIsVisible.value).toBe(false);
});
it("sets default if no header or body is provided", () => {
it("sets default if no header or content is provided", () => {
showModal({});
expect(useModal().content.header).toBe("");
expect(useModal().content.body).toHaveLength(0);
expect(useModal().modal.header).toBe("");
expect(useModal().modal.content).toHaveLength(0);
});
});
Loading
Loading