Skip to content

Commit

Permalink
Merge pull request #903 from traPtitech/unsaved-warning
Browse files Browse the repository at this point in the history
formが書き途中でページ遷移を行おうとしたときに確認メッセージを出す
  • Loading branch information
itt828 authored Oct 27, 2023
2 parents a32c0a4 + cb02124 commit def3551
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 7 deletions.
107 changes: 107 additions & 0 deletions src/components/event/EventFormBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ import EventFormSummary, {
} from '@/components/event/EventFormSummary.vue'
import FormNextButton from '@/components/shared/FormNextButton.vue'
import FormBackButton from '@/components/shared/FormBackButton.vue'
import { useDraftConfirmer } from '@/workers/draftConfirmer'
import { removeDraftConfirmer } from '@/workers/draftConfirmer'
import router from '@/router'
import { Route } from 'vue-router'
export type EventInput = EventInputContent &
(
Expand Down Expand Up @@ -115,6 +119,10 @@ export default class EventFormBase extends Vue {
instant: boolean = null!
originalSummary: EventSummary = null!
beforeEachControl: (() => void) | null = null
created() {
this.content = {
name: this.event?.name ?? '',
Expand Down Expand Up @@ -197,8 +205,107 @@ export default class EventFormBase extends Vue {
}
}
isChanged(): boolean {
if (this.summary && this.originalSummary) {
return (
JSON.stringify(this.summary) !== JSON.stringify(this.originalSummary)
)
}
return false
}
cleanupContent(): void {
this.summary.name = ''
this.summary.description = ''
this.summary.tags = []
this.summary.groupName = ''
this.summary.place = ''
this.summary.timeStart = ''
this.summary.timeEnd = ''
this.summary.open = false
this.summary.sharedRoom = true
}
isEventNewOrEdit(): boolean {
const currentRoute: Route = this.$route
return currentRoute.name === 'EventNew'
}
beforLeaveGuardinEventEdit = (to, from, next) => {
if (from.name !== 'EventEdit') {
return next()
}
if (!this.isChanged()) {
return next()
}
if (
confirm(
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
)
) {
removeDraftConfirmer()
this.cleanupContent()
return next()
}
return next(false)
}
beforLeaveGuardinEventNew = (to, from, next) => {
if (from.name !== 'EventNew' || !this.isChanged()) {
return next()
}
if (
confirm(
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
)
) {
removeDraftConfirmer()
this.cleanupContent()
return next()
}
return next(false)
}
mounted() {
this.$watch(
'summary',
() => {
if (this.isChanged()) {
useDraftConfirmer()
} else {
removeDraftConfirmer()
}
},
{ deep: true }
)
if (this.isEventNewOrEdit()) {
this.beforeEachControl = router.beforeEach(this.beforLeaveGuardinEventNew)
} else {
this.beforeEachControl = router.beforeEach(
this.beforLeaveGuardinEventEdit
)
}
this.originalSummary = JSON.parse(JSON.stringify(this.summary))
}
beforeDestroy() {
if (this.beforeEachControl) {
this.beforeEachControl()
}
}
@Emit()
submit(): EventOutput {
removeDraftConfirmer()
this.cleanupContent()
if (this.beforeEachControl) {
this.beforeEachControl()
}
return {
...this.content,
group: this.content.group!,
Expand Down
31 changes: 27 additions & 4 deletions src/components/main/SidebarFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@

<script lang="ts">
import { isValidVerifiedroomData } from '@/workers/isValidVerifiedroomData'
import { useDraftConfirmer } from '@/workers/draftConfirmer'
import { removeDraftConfirmer } from '@/workers/draftConfirmer'
import { baseURL } from '@/workers/api'
export default {
Expand All @@ -75,21 +77,42 @@ export default {
return this.$store.direct.state.me?.privileged ?? false
},
},
mounted: function () {
this.$watch('inputData', newVal => {
if (newVal !== '') {
useDraftConfirmer()
} else {
removeDraftConfirmer()
}
})
},
methods: {
showModal() {
this.isVisible = true
},
hideModal() {
this.isVisible = false
this.showError = false
this.inputData = ''
if (this.inputData) {
if (
confirm(
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
)
) {
this.isVisible = false
this.showError = false
this.inputData = ''
}
return
} else {
this.isVisible = false
this.showError = false
this.inputData = ''
}
},
async saveData() {
if (isValidVerifiedroomData(this.inputData)) {
this.showError = false
try {
await fetch(`${baseURL}/rooms/all`, {
//開発環境url
method: 'POST',
credentials: 'include',
headers: {
Expand Down
66 changes: 63 additions & 3 deletions src/pages/GroupEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ import FormBackButton from '@/components/shared/FormBackButton.vue'
import ProgressCircular from '@/components/shared/ProgressCircular.vue'
import LoadFailedText from '@/components/shared/LoadFailedText.vue'
import api, { RequestGroup } from '@/api'
import router from '@/router'
import { useDraftConfirmer } from '@/workers/draftConfirmer'
import { removeDraftConfirmer } from '@/workers/draftConfirmer'
@Component({
components: {
Expand All @@ -74,6 +77,8 @@ export default class GroupEdit extends Vue {
step = 1
group: RequestGroup | null = null
originalGroup: RequestGroup | null = null
beforeEachControl: (() => void) | null = null
get groupId() {
return this.$route.params.id
Expand All @@ -84,6 +89,7 @@ export default class GroupEdit extends Vue {
try {
const group = await api.groups.getGroup({ groupID: this.groupId })
this.group = group
this.originalGroup = JSON.parse(JSON.stringify(group))
this.canEdit =
!group.isTraQGroup && !!this.me && group.admins.includes(this.me)
this.status = 'loaded'
Expand All @@ -92,13 +98,44 @@ export default class GroupEdit extends Vue {
}
}
isChanged(): boolean {
if (this.group && this.originalGroup) {
return JSON.stringify(this.group) !== JSON.stringify(this.originalGroup)
}
return false
}
cleanupContent(): void {
this.group = this.originalGroup
}
beforeLeaveGuard = (to, from, next) => {
if (from.path !== `/groups/edit/${this.groupId}` || !this.isChanged()) {
return next()
}
if (
confirm(
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
)
) {
removeDraftConfirmer()
this.cleanupContent()
return next()
}
return next(false)
}
async submitGroup() {
if (!this.group) return
try {
await api.groups.updateGroup({
groupID: this.groupId,
requestGroup: this.group,
})
removeDraftConfirmer()
this.cleanupContent()
this.$router.push(`/groups/${this.groupId}`)
} catch (__) {
alert('Failed to submit...')
Expand All @@ -125,9 +162,32 @@ export default class GroupEdit extends Vue {
if (!confirmed) return
try {
await api.groups.deleteGroup({ groupID: this.groupId })
this.$router.push('/')
} catch (__) {
alert('Failed to submit...')
removeDraftConfirmer()
this.cleanupContent()
this.$router.push('/groups')
} catch (error) {
alert('Failed to delete...')
}
}
mounted() {
this.$watch(
'group',
() => {
if (this.isChanged()) {
useDraftConfirmer()
} else {
removeDraftConfirmer()
}
},
{ deep: true }
)
this.beforeEachControl = router.beforeEach(this.beforeLeaveGuard)
}
beforeDestroy() {
if (this.beforeEachControl) {
this.beforeEachControl()
}
}
Expand Down
58 changes: 58 additions & 0 deletions src/pages/GroupNew.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ import GroupFormSummary from '@/components/group/GroupFormSummary.vue'
import FormNextButton from '@/components/shared/FormNextButton.vue'
import FormBackButton from '@/components/shared/FormBackButton.vue'
import api, { RequestGroup } from '@/api'
import { useDraftConfirmer } from '@/workers/draftConfirmer'
import { removeDraftConfirmer } from '@/workers/draftConfirmer'
import router from '@/router'
@Component({
components: {
Expand All @@ -48,6 +51,8 @@ export default class GroupNew extends Vue {
valid = false
step = 1
beforeEachControl: (() => void) | null = null
group: RequestGroup = {
name: '',
description: '',
Expand All @@ -60,13 +65,66 @@ export default class GroupNew extends Vue {
: [],
}
hasContent(): boolean {
return (
this.group.name !== '' || this.group.description !== '' || this.group.open
)
}
cleanupContent(): void {
this.group.name = ''
this.group.description = ''
this.group.open = false
}
beforeLeaveGuard = (to, from, next) => {
if (from.name !== 'GroupNew' || this.hasContent()) {
return next()
}
if (
confirm(
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
)
) {
removeDraftConfirmer()
this.cleanupContent()
return next()
}
return next(false)
}
mounted() {
this.$watch(
'group',
() => {
if (this.hasContent()) {
useDraftConfirmer()
} else {
removeDraftConfirmer()
}
},
{ deep: true }
)
this.beforeEachControl = router.beforeEach(this.beforeLeaveGuard)
}
beforeDestroy() {
if (this.beforeEachControl) {
this.beforeEachControl()
}
}
async submitGroup() {
try {
await api.groups.createGroup({ requestGroup: this.group })
} catch (__) {
alert('Failed to submit...')
return
}
removeDraftConfirmer()
this.cleanupContent()
this.$router.push('/events/new')
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/workers/draftConfirmer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const beforeUnloadListener = (event: BeforeUnloadEvent) => {
event.preventDefault()
event.returnValue =
'入力されたデータは送信されないまま破棄されますが,よろしいですか。'
}

export function useDraftConfirmer(): void {
window.addEventListener('beforeunload', beforeUnloadListener)
}

export function removeDraftConfirmer(): void {
window.removeEventListener('beforeunload', beforeUnloadListener)
}

0 comments on commit def3551

Please sign in to comment.