Create a generic confirmation dialog

This commit is contained in:
Pavel Djundik 2020-02-25 11:16:05 +02:00
parent 7216b8124b
commit 44a8925b8c
6 changed files with 131 additions and 61 deletions

View File

@ -5,6 +5,7 @@
<router-view ref="window"></router-view>
<ImageViewer ref="imageViewer" />
<ContextMenu ref="contextMenu" />
<ConfirmDialog ref="confirmDialog" />
<div id="upload-overlay"></div>
</div>
</template>
@ -18,6 +19,7 @@ import storage from "../js/localStorage";
import Sidebar from "./Sidebar.vue";
import ImageViewer from "./ImageViewer.vue";
import ContextMenu from "./ContextMenu.vue";
import ConfirmDialog from "./ConfirmDialog.vue";
export default {
name: "App",
@ -25,6 +27,7 @@ export default {
Sidebar,
ImageViewer,
ContextMenu,
ConfirmDialog,
},
computed: {
viewportClasses() {

View File

@ -0,0 +1,84 @@
<template>
<div id="confirm-dialog-overlay" :class="{opened: data !== null}">
<div v-if="data !== null" id="confirm-dialog">
<div class="confirm-text">
<div class="confirm-text-title">{{ data.title }}</div>
<p>{{ data.text }}</p>
</div>
<div class="confirm-buttons">
<button class="btn btn-cancel" @click="close(false)">Cancel</button>
<button class="btn btn-danger" @click="close(true)">{{ data.button }}</button>
</div>
</div>
</div>
</template>
<style>
#confirm-dialog {
background: var(--body-bg-color);
color: #fff;
margin: 10px;
border-radius: 5px;
max-width: 500px;
}
#confirm-dialog .confirm-text {
padding: 15px;
user-select: text;
}
#confirm-dialog .confirm-text-title {
font-size: 20px;
font-weight: 700;
margin-bottom: 10px;
}
#confirm-dialog .confirm-buttons {
display: flex;
justify-content: flex-end;
padding: 15px;
background: rgba(0, 0, 0, 0.3);
}
#confirm-dialog .confirm-buttons .btn {
margin-bottom: 0;
margin-left: 10px;
}
#confirm-dialog .confirm-buttons .btn-cancel {
border-color: transparent;
}
</style>
<script>
export default {
name: "ConfirmDialog",
data() {
return {
data: null,
callback: null,
};
},
mounted() {
this.$root.$on("escapekey", this.close);
this.$root.$on("confirm-dialog", this.open);
},
destroyed() {
this.$root.$off("escapekey", this.close);
this.$root.$off("confirm-dialog", this.open);
},
methods: {
open(data, callback) {
this.data = data;
this.callback = callback;
},
close(result) {
this.data = null;
if (this.callback) {
this.callback(!!result);
}
},
},
};
</script>

View File

@ -38,11 +38,7 @@
</template>
<script>
import {
generateUserContextMenu,
generateChannelContextMenu,
generateRemoveNetwork,
} from "../js/helpers/contextMenu.js";
import {generateUserContextMenu, generateChannelContextMenu} from "../js/helpers/contextMenu.js";
export default {
name: "ContextMenu",
@ -65,21 +61,15 @@ export default {
this.$root.$on("escapekey", this.close);
this.$root.$on("contextmenu:user", this.openUserContextMenu);
this.$root.$on("contextmenu:channel", this.openChannelContextMenu);
this.$root.$on("contextmenu:removenetwork", this.openRemoveNetworkContextMenu);
},
destroyed() {
this.$root.$off("escapekey", this.close);
this.$root.$off("contextmenu:user", this.openUserContextMenu);
this.$root.$off("contextmenu:channel", this.openChannelContextMenu);
this.$root.$off("contextmenu:removenetwork", this.openRemoveNetworkContextMenu);
this.close();
},
methods: {
openRemoveNetworkContextMenu(data) {
const items = generateRemoveNetwork(this.$root, data.lobby);
this.open(data.event, items);
},
openChannelContextMenu(data) {
const items = generateChannelContextMenu(this.$root, data.channel, data.network);
this.open(data.event, items);

View File

@ -2709,6 +2709,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
/* Image viewer and drag-and-drop overlay */
#confirm-dialog-overlay,
#upload-overlay,
#image-viewer,
#image-viewer .open-btn,
@ -2720,6 +2721,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
justify-content: center;
}
#confirm-dialog-overlay,
#upload-overlay,
#image-viewer {
position: fixed;
@ -2735,12 +2737,14 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
user-select: none;
}
#confirm-dialog-overlay.opened,
#upload-overlay.is-dragover,
#image-viewer.opened {
visibility: visible;
opacity: 1;
}
#confirm-dialog-overlay,
#image-viewer {
background: rgba(0, 0, 0, 0.9);
}

View File

@ -135,17 +135,29 @@ export function generateChannelContextMenu($root, channel, network) {
type: "item",
class: "clear-history",
action() {
// TODO: Confirmation window
$root.$emit(
"confirm-dialog",
{
title: "Clear history",
text: `Are you sure you want to clear history for ${channel.name}? This cannot be undone.`,
button: "Clear history",
},
(result) => {
if (!result) {
return;
}
channel.messages = [];
channel.unread = 0;
channel.highlight = 0;
channel.firstUnread = 0;
channel.moreHistoryAvailable = false;
channel.messages = [];
channel.unread = 0;
channel.highlight = 0;
channel.firstUnread = 0;
channel.moreHistoryAvailable = false;
socket.emit("history:clear", {
target: channel.id,
});
socket.emit("history:clear", {
target: channel.id,
});
}
);
},
});
}
@ -282,31 +294,3 @@ export function generateUserContextMenu($root, channel, network, user) {
return items;
}
export function generateRemoveNetwork($root, lobby) {
return [
{
label: lobby.name,
type: "item",
class: "network",
},
{
type: "divider",
},
{
label: "Yes, remove this",
type: "item",
action() {
lobby.closed = true;
socket.emit("input", {
target: Number(lobby.id),
text: "/quit",
});
},
},
{
label: "Cancel",
type: "item",
},
];
}

View File

@ -30,20 +30,25 @@ const vueApp = new Vue({
},
closeChannel(channel) {
if (channel.type === "lobby") {
const el = document.querySelector(
`#sidebar .channel-list-item[aria-controls="#chan-${channel.id}"]`
);
const rect = el.getBoundingClientRect();
const event = new MouseEvent("click", {
view: window,
clientX: rect.left + 10,
clientY: rect.top,
});
this.$root.$emit(
"confirm-dialog",
{
title: "Remove network",
text: `Are you sure you want to quit and remove ${channel.name}? This cannot be undone.`,
button: "Remove network",
},
(result) => {
if (!result) {
return;
}
this.$root.$emit("contextmenu:removenetwork", {
event: event,
lobby: channel,
});
channel.closed = true;
socket.emit("input", {
target: Number(channel.id),
text: "/quit",
});
}
);
return;
}