Skip to content

Commit 26df5fb

Browse files
committed
Display restart modal after exporting
1 parent f570e3c commit 26df5fb

File tree

9 files changed

+16004
-12
lines changed

9 files changed

+16004
-12
lines changed

package-lock.json

Lines changed: 15793 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313
"dependencies": {
1414
"core-js": "^2.6.5",
15+
"portal-vue": "2.1.6",
1516
"postcss-import": "12.0.1",
1617
"prosemirror-example-setup": "1.0.1",
1718
"prosemirror-model": "1.7.2",

src/App.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<vue-page-transition :name="transitionName">
88
<router-view />
99
</vue-page-transition>
10+
11+
<portal-target name="modals" multiple />
1012
</div>
1113
</template>
1214

@@ -40,4 +42,12 @@ export default {
4042
.fade-in-left .fade-in-left-leave-active {
4143
/* transition: all 10s ease !important; */
4244
}
45+
46+
.vue-slick-popover__overlay {
47+
/* Stop overlay creating horizontal scroll from "width: 100vw" */
48+
height: auto;
49+
width: auto;
50+
bottom: 0;
51+
right: 0;
52+
}
4353
</style>

src/assets/css/element/element-button.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ textarea.Input {
196196
.ButtonComplex .Button--outline,
197197
.Button--outline,
198198
.Button--invisible {
199-
--button-color: theme(colors.text);
199+
--button-color: var(--button-invert-color);
200200
--button-bg-color: transparent;
201201
--button-bg-color-hover: transparent;
202202
}

src/components/ButtonExport.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ export default {
107107
108108
focused.focus();
109109
this.$refs.popover.close();
110+
111+
this.$emit('onExport');
110112
},
111113
exportGmail() {
112114
return this.exportReply(GmailFormatter);

src/components/Modal.vue

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<template>
2+
<transition name="Modal">
3+
<div class="Modal-backdrop z-100" v-show="show" @click="dismiss">
4+
<div class="Modal" @click="stopPropagation">
5+
<slot />
6+
</div>
7+
</div>
8+
</transition>
9+
</template>
10+
11+
<script>
12+
// import IconBase from "@/components/IconBase";
13+
// import IconUIClose from "@/components/icons/IconUIClose";
14+
15+
/* https://learn.adamwathan.com/advanced-vue/encapsulating-external-behavior-background-scrolling */
16+
17+
export default {
18+
components: {},
19+
props: {
20+
show: { required: true },
21+
preventBackgroundScrolling: { default: true },
22+
},
23+
watch: {
24+
show: {
25+
// this watcher will run when first instaniated
26+
immediate: true,
27+
handler(show) {
28+
if (this.preventBackgroundScrolling) {
29+
if (show) {
30+
document.body.style.setProperty('overflow', 'hidden');
31+
} else {
32+
document.body.style.removeProperty('overflow');
33+
}
34+
}
35+
},
36+
},
37+
},
38+
created() {
39+
const escapeHandler = (e) => {
40+
if (e.key === 'Escape' && this.show) {
41+
this.dismiss();
42+
}
43+
};
44+
document.addEventListener('keydown', escapeHandler);
45+
this.$once('hook:destroyed', () => {
46+
document.removeEventListener('keydown', escapeHandler);
47+
});
48+
},
49+
methods: {
50+
stopPropagation(event) {
51+
event.stopPropagation();
52+
},
53+
dismiss() {
54+
this.$emit('close');
55+
document.body.style.removeProperty('overflow');
56+
},
57+
},
58+
};
59+
</script>
60+
61+
<style scoped>
62+
.Modal-backdrop {
63+
position: fixed;
64+
top: 0;
65+
right: 0;
66+
bottom: 0;
67+
left: 0;
68+
overflow: auto;
69+
display: flex;
70+
align-items: center;
71+
justify-content: center;
72+
width: auto;
73+
}
74+
75+
@keyframes headerIn {
76+
from {
77+
opacity: 0;
78+
}
79+
to {
80+
opacity: 1;
81+
}
82+
}
83+
84+
.Modal {
85+
@apply py-5 px-7;
86+
animation: headerIn 750ms cubic-bezier(0.19, 1, 0.22, 1);
87+
background-color: #fff;
88+
89+
@media (max-width: 768px) and (orientation: landscape) {
90+
height: auto;
91+
}
92+
}
93+
94+
.Modal-close {
95+
cursor: pointer;
96+
padding: calc(1.75 * var(--rs-space));
97+
position: absolute;
98+
right: 0;
99+
top: 0;
100+
z-index: 1;
101+
102+
&:focus,
103+
&:active {
104+
outline: none;
105+
}
106+
107+
& >>> svg {
108+
height: 2.5em;
109+
width: 2.5em;
110+
111+
@media (--sm) {
112+
height: 3em;
113+
width: 3em;
114+
}
115+
}
116+
}
117+
118+
/*
119+
* Transitions auto-applied to elements with
120+
* transition="modal" when their visibility is toggled by Vue.
121+
*/
122+
123+
.Modal-enter-active, .Modal-leave-active {
124+
transition: opacity .2s;
125+
}
126+
127+
.Modal-enter, .Modal-leave-to /* .Modal-leave-active below version 2.1.8 */ {
128+
opacity: 0;
129+
}
130+
</style>

src/main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Vue from 'vue';
22
import VuePageTransition from 'vue-page-transition';
3+
import PortalVue from 'portal-vue';
34
import SvgIcon from 'vue-svgicon';
45
import App from './App.vue';
56
import router from './router';
@@ -9,6 +10,7 @@ import './assets/css/tailwind.css';
910

1011
Vue.config.productionTip = false;
1112

13+
Vue.use(PortalVue);
1214
Vue.use(VuePageTransition);
1315

1416
Vue.use(SvgIcon, {

src/store.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@ import Vuex from 'vuex';
33

44
Vue.use(Vuex);
55

6+
const defaultState = {
7+
timestamp: null,
8+
editorState: null,
9+
selections: [],
10+
// Keyed by selection ids
11+
orders: {},
12+
replies: {},
13+
repliesIntro: '',
14+
repliesOutro: '',
15+
};
16+
617
export default new Vuex.Store({
7-
state: {
8-
timestamp: null,
9-
editorState: null,
10-
selections: [],
11-
// Keyed by selection ids
12-
orders: {},
13-
replies: {},
14-
repliesIntro: '',
15-
repliesOutro: '',
16-
},
18+
state: Object.assign({}, defaultState),
1719
mutations: {
1820
setEditorState(state, editorState) {
1921
state.editorState = editorState;
@@ -63,6 +65,11 @@ export default new Vuex.Store({
6365
setRepliesOutro(state, text) {
6466
state.repliesOutro = text;
6567
},
68+
// eslint-disable-next-line no-unused-vars
69+
resetState(state) {
70+
// eslint-disable-next-line no-param-reassign
71+
state = Object.assign(state, defaultState);
72+
},
6673
},
6774
actions: {
6875
},

src/views/Reply.vue

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,40 @@
7373
@input="handleOutroInput"
7474
>{{ $store.state.repliesOutro }}</textarea>
7575

76-
<ButtonExport :groupedSelections="groupedSelections" />
76+
<ButtonExport @onExport="handleExport" :groupedSelections="groupedSelections" />
7777
</div>
78+
<portal to="modals">
79+
<Modal :show="isResetModalOpen" @close="isResetModalOpen = false" ref="resetModal">
80+
<div class="max-w-xl">
81+
<p class="s-p">Successfully copied to your clipboard!</p>
82+
<div class="flex">
83+
<button class="mr-2 w-1/2 Button" @click="resetState">Start again</button>
84+
<button class="ml-2 w-1/2 Button Button--outline" @click="dismiss">Keep Editing</button>
85+
</div>
86+
</div>
87+
</Modal>
88+
</portal>
7889
</div>
7990
</template>
8091

8192
<script>
8293
import draggable from 'vuedraggable';
8394
import ButtonExport from '@/components/ButtonExport.vue';
8495
import Tooltip from '@/components/Tooltip.vue';
96+
import Modal from '@/components/Modal.vue';
8597
8698
export default {
8799
name: 'reply',
88100
components: {
89101
draggable,
90102
ButtonExport,
91103
Tooltip,
104+
Modal,
105+
},
106+
data() {
107+
return {
108+
isResetModalOpen: false,
109+
};
92110
},
93111
computed: {
94112
groupedSelections: {
@@ -101,6 +119,18 @@ export default {
101119
},
102120
},
103121
methods: {
122+
dismiss() {
123+
this.$refs.resetModal.dismiss();
124+
},
125+
async resetState() {
126+
await this.$store.commit('resetState');
127+
this.$refs.resetModal.dismiss();
128+
window.scrollTo({ top: 0, behavior: 'smooth' });
129+
this.$router.push('/');
130+
},
131+
handleExport() {
132+
this.isResetModalOpen = true;
133+
},
104134
handleDragEnd() {
105135
},
106136
goBackIfSelectionsEmpty() {
@@ -229,4 +259,21 @@ export default {
229259
min-width: 150px;
230260
transform: translate(-50%, 100%);
231261
} */
262+
263+
264+
/*
265+
* Modal
266+
*/
267+
268+
.Modal-backdrop {
269+
background: rgba(255, 255, 255, 0.7);
270+
}
271+
272+
>>> .Modal {
273+
box-shadow: 0 0 6px 4px #eaeaea;
274+
}
275+
276+
>>> .Modal .Button {
277+
white-space: nowrap;
278+
}
232279
</style>

0 commit comments

Comments
 (0)