2017-09-10 17:25:29 +05:30
< script >
2021-06-08 01:23:25 +05:30
import { GlAlert } from '@gitlab/ui' ;
2022-11-25 23:54:43 +05:30
import { getDraft , updateDraft , getLockVersion , clearDraft } from '~/lib/utils/autosave' ;
2022-01-26 12:08:38 +05:30
import { IssuableType } from '~/issues/constants' ;
2019-07-31 22:56:46 +05:30
import eventHub from '../event_hub' ;
2021-09-04 01:27:46 +05:30
import EditActions from './edit_actions.vue' ;
import DescriptionField from './fields/description.vue' ;
import DescriptionTemplateField from './fields/description_template.vue' ;
import IssuableTitleField from './fields/title.vue' ;
import IssuableTypeField from './fields/type.vue' ;
import LockedWarning from './locked_warning.vue' ;
2017-09-10 17:25:29 +05:30
2018-12-13 13:39:08 +05:30
export default {
components : {
2021-09-04 01:27:46 +05:30
DescriptionField ,
DescriptionTemplateField ,
EditActions ,
2021-06-08 01:23:25 +05:30
GlAlert ,
2021-09-04 01:27:46 +05:30
IssuableTitleField ,
IssuableTypeField ,
LockedWarning ,
2018-12-13 13:39:08 +05:30
} ,
props : {
2022-01-26 12:08:38 +05:30
endpoint : {
type : String ,
required : true ,
} ,
2018-12-13 13:39:08 +05:30
formState : {
type : Object ,
required : true ,
2017-09-10 17:25:29 +05:30
} ,
2018-12-13 13:39:08 +05:30
issuableTemplates : {
2021-04-17 20:07:23 +05:30
type : [ Object , Array ] ,
2018-12-13 13:39:08 +05:30
required : false ,
2021-10-27 15:23:28 +05:30
default : ( ) => [ ] ,
2017-09-10 17:25:29 +05:30
} ,
2018-12-13 13:39:08 +05:30
issuableType : {
type : String ,
required : true ,
} ,
markdownPreviewPath : {
type : String ,
required : true ,
} ,
markdownDocsPath : {
type : String ,
required : true ,
} ,
projectPath : {
type : String ,
required : true ,
} ,
2021-03-11 19:13:27 +05:30
projectId : {
type : Number ,
required : true ,
} ,
2018-12-13 13:39:08 +05:30
projectNamespace : {
type : String ,
required : true ,
} ,
canAttachFile : {
type : Boolean ,
required : false ,
default : true ,
} ,
enableAutocomplete : {
type : Boolean ,
required : false ,
default : true ,
} ,
2021-06-08 01:23:25 +05:30
initialDescriptionText : {
type : String ,
required : false ,
default : '' ,
} ,
} ,
data ( ) {
2022-11-25 23:54:43 +05:30
const autosaveKey = [ document . location . pathname , document . location . search ] ;
const descriptionAutosaveKey = [ ... autosaveKey , 'description' ] ;
const titleAutosaveKey = [ ... autosaveKey , 'title' ] ;
2021-06-08 01:23:25 +05:30
return {
2022-11-25 23:54:43 +05:30
titleAutosaveKey ,
descriptionAutosaveKey ,
autosaveReset : false ,
2022-06-21 17:19:12 +05:30
formData : {
2022-11-25 23:54:43 +05:30
title : getDraft ( titleAutosaveKey ) || this . formState . title ,
description : getDraft ( descriptionAutosaveKey ) || this . formState . description ,
2022-06-21 17:19:12 +05:30
} ,
2021-06-08 01:23:25 +05:30
showOutdatedDescriptionWarning : false ,
} ;
2018-12-13 13:39:08 +05:30
} ,
computed : {
hasIssuableTemplates ( ) {
2021-04-17 20:07:23 +05:30
return Object . values ( Object ( this . issuableTemplates ) ) . length ;
2018-12-13 13:39:08 +05:30
} ,
2019-10-12 21:52:04 +05:30
showLockedWarning ( ) {
return this . formState . lockedWarningVisible && ! this . formState . updateLoading ;
} ,
2021-09-04 01:27:46 +05:30
isIssueType ( ) {
return this . issuableType === IssuableType . Issue ;
} ,
2018-12-13 13:39:08 +05:30
} ,
2022-06-21 17:19:12 +05:30
watch : {
formData : {
handler ( value ) {
this . $emit ( 'updateForm' , value ) ;
} ,
deep : true ,
} ,
} ,
2019-07-31 22:56:46 +05:30
created ( ) {
eventHub . $on ( 'delete.issuable' , this . resetAutosave ) ;
eventHub . $on ( 'update.issuable' , this . resetAutosave ) ;
eventHub . $on ( 'close.form' , this . resetAutosave ) ;
} ,
mounted ( ) {
this . initAutosave ( ) ;
} ,
beforeDestroy ( ) {
eventHub . $off ( 'delete.issuable' , this . resetAutosave ) ;
eventHub . $off ( 'update.issuable' , this . resetAutosave ) ;
eventHub . $off ( 'close.form' , this . resetAutosave ) ;
} ,
methods : {
initAutosave ( ) {
2022-11-25 23:54:43 +05:30
const savedLockVersion = getLockVersion ( this . descriptionAutosaveKey ) ;
2021-06-08 01:23:25 +05:30
this . showOutdatedDescriptionWarning =
savedLockVersion && String ( this . formState . lock _version ) !== savedLockVersion ;
2019-07-31 22:56:46 +05:30
} ,
resetAutosave ( ) {
2022-11-25 23:54:43 +05:30
this . autosaveReset = true ;
clearDraft ( this . descriptionAutosaveKey ) ;
clearDraft ( this . titleAutosaveKey ) ;
2019-07-31 22:56:46 +05:30
} ,
2021-06-08 01:23:25 +05:30
keepAutosave ( ) {
2022-11-25 23:54:43 +05:30
this . $refs . description . focus ( ) ;
2021-06-08 01:23:25 +05:30
this . showOutdatedDescriptionWarning = false ;
} ,
discardAutosave ( ) {
2022-11-25 23:54:43 +05:30
this . formData . description = this . initialDescriptionText ;
clearDraft ( this . descriptionAutosaveKey ) ;
this . $refs . description . focus ( ) ;
2021-06-08 01:23:25 +05:30
this . showOutdatedDescriptionWarning = false ;
} ,
2022-11-25 23:54:43 +05:30
updateTitleDraft ( title ) {
updateDraft ( this . titleAutosaveKey , title ) ;
} ,
updateDescriptionDraft ( description ) {
/ *
* This conditional statement prevents a race - condition
* between clearing the draft and submitting a new draft
* update while the user is typing . It happens when saving
* using the cmd + enter keyboard shortcut .
* /
if ( ! this . autosaveReset ) {
updateDraft ( this . descriptionAutosaveKey , description , this . formState . lock _version ) ;
}
} ,
2019-07-31 22:56:46 +05:30
} ,
2018-12-13 13:39:08 +05:30
} ;
2017-09-10 17:25:29 +05:30
< / script >
< template >
2021-09-04 01:27:46 +05:30
< form data -testid = " issuable -form " >
2023-03-04 22:38:38 +05:30
< locked-warning v-if = "showLockedWarning" :issuable-type="issuableType" / >
2021-06-08 01:23:25 +05:30
< gl-alert
v - if = "showOutdatedDescriptionWarning"
class = "gl-mb-5"
variant = "warning"
: primary - button - text = "__('Keep')"
: secondary - button - text = "__('Discard')"
: dismissible = "false"
@ primaryAction = "keepAutosave"
@ secondaryAction = "discardAutosave"
> { {
_ _ (
'The comment you are editing has been changed by another user. Would you like to keep your changes and overwrite the new description or discard your changes?' ,
)
} } < / g l - a l e r t
>
2021-09-04 01:27:46 +05:30
< div class = "row gl-mb-3" >
< div class = "col-12" >
2022-11-25 23:54:43 +05:30
< issuable-title-field ref = "title" v-model = "formData.title" @input="updateTitleDraft" / >
2021-09-04 01:27:46 +05:30
< / div >
< / div >
2017-09-10 17:25:29 +05:30
< div class = "row" >
2021-09-04 01:27:46 +05:30
< div v-if = "isIssueType" class="col-12 col-md-4 pr-md-0" >
< issuable-type-field ref = "issue-type" / >
< / div >
2022-06-21 17:19:12 +05:30
2021-09-04 01:27:46 +05:30
< div v-if = "hasIssuableTemplates" class="col-12 col-md-4 pl-md-2" >
< description-template-field
2022-06-21 17:19:12 +05:30
v - model = "formData.description"
2017-09-10 17:25:29 +05:30
: issuable - templates = "issuableTemplates"
: project - path = "projectPath"
2021-03-11 19:13:27 +05:30
: project - id = "projectId"
2018-03-17 18:26:18 +05:30
: project - namespace = "projectNamespace"
/ >
2017-09-10 17:25:29 +05:30
< / div >
< / div >
2022-06-21 17:19:12 +05:30
2017-09-10 17:25:29 +05:30
< description-field
2019-07-31 22:56:46 +05:30
ref = "description"
2022-06-21 17:19:12 +05:30
v - model = "formData.description"
2018-03-17 18:26:18 +05:30
: markdown - preview - path = "markdownPreviewPath"
: markdown - docs - path = "markdownDocsPath"
: can - attach - file = "canAttachFile"
: enable - autocomplete = "enableAutocomplete"
2022-11-25 23:54:43 +05:30
@ input = "updateDescriptionDraft"
2018-03-17 18:26:18 +05:30
/ >
2022-06-21 17:19:12 +05:30
2022-10-11 01:57:18 +05:30
< edit-actions :endpoint = "endpoint" :form-state = "formState" :issuable-type = "issuableType" / >
2017-09-10 17:25:29 +05:30
< / form >
< / template >