Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
7100c7a2
Commit
7100c7a2
authored
Nov 21, 2019
by
Samantha Ming
Committed by
Natalia Tepluhina
Nov 21, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Keep details in MR when changing target branch
- Add defaultKey to Autosave - Pass defaultKey in issuable form
parent
1284ea5a
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
146 additions
and
14 deletions
+146
-14
app/assets/javascripts/autosave.js
app/assets/javascripts/autosave.js
+12
-4
app/assets/javascripts/issuable_form.js
app/assets/javascripts/issuable_form.js
+44
-10
app/assets/javascripts/lib/utils/url_utility.js
app/assets/javascripts/lib/utils/url_utility.js
+32
-0
changelogs/unreleased/30016-changing-branch-keep-details.yml
changelogs/unreleased/30016-changing-branch-keep-details.yml
+5
-0
spec/frontend/autosave_spec.js
spec/frontend/autosave_spec.js
+37
-0
spec/frontend/lib/utils/url_utility_spec.js
spec/frontend/lib/utils/url_utility_spec.js
+16
-0
No files found.
app/assets/javascripts/autosave.js
View file @
7100c7a2
/* eslint-disable no-param-reassign,
no-void,
consistent-return */
/* eslint-disable no-param-reassign, consistent-return */
import
AccessorUtilities
from
'
./lib/utils/accessor
'
;
import
AccessorUtilities
from
'
./lib/utils/accessor
'
;
export
default
class
Autosave
{
export
default
class
Autosave
{
constructor
(
field
,
key
)
{
constructor
(
field
,
key
,
fallbackKey
)
{
this
.
field
=
field
;
this
.
field
=
field
;
this
.
isLocalStorageAvailable
=
AccessorUtilities
.
isLocalStorageAccessSafe
();
this
.
isLocalStorageAvailable
=
AccessorUtilities
.
isLocalStorageAccessSafe
();
...
@@ -11,6 +11,7 @@ export default class Autosave {
...
@@ -11,6 +11,7 @@ export default class Autosave {
key
=
key
.
join
(
'
/
'
);
key
=
key
.
join
(
'
/
'
);
}
}
this
.
key
=
`autosave/
${
key
}
`
;
this
.
key
=
`autosave/
${
key
}
`
;
this
.
fallbackKey
=
fallbackKey
;
this
.
field
.
data
(
'
autosave
'
,
this
);
this
.
field
.
data
(
'
autosave
'
,
this
);
this
.
restore
();
this
.
restore
();
this
.
field
.
on
(
'
input
'
,
()
=>
this
.
save
());
this
.
field
.
on
(
'
input
'
,
()
=>
this
.
save
());
...
@@ -21,9 +22,12 @@ export default class Autosave {
...
@@ -21,9 +22,12 @@ export default class Autosave {
if
(
!
this
.
field
.
length
)
return
;
if
(
!
this
.
field
.
length
)
return
;
const
text
=
window
.
localStorage
.
getItem
(
this
.
key
);
const
text
=
window
.
localStorage
.
getItem
(
this
.
key
);
const
fallbackText
=
window
.
localStorage
.
getItem
(
this
.
fallbackKey
);
if
(
(
text
!=
null
?
text
.
length
:
void
0
)
>
0
)
{
if
(
text
)
{
this
.
field
.
val
(
text
);
this
.
field
.
val
(
text
);
}
else
if
(
fallbackText
)
{
this
.
field
.
val
(
fallbackText
);
}
}
this
.
field
.
trigger
(
'
input
'
);
this
.
field
.
trigger
(
'
input
'
);
...
@@ -41,7 +45,10 @@ export default class Autosave {
...
@@ -41,7 +45,10 @@ export default class Autosave {
const
text
=
this
.
field
.
val
();
const
text
=
this
.
field
.
val
();
if
(
this
.
isLocalStorageAvailable
&&
(
text
!=
null
?
text
.
length
:
void
0
)
>
0
)
{
if
(
this
.
isLocalStorageAvailable
&&
text
)
{
if
(
this
.
fallbackKey
)
{
window
.
localStorage
.
setItem
(
this
.
fallbackKey
,
text
);
}
return
window
.
localStorage
.
setItem
(
this
.
key
,
text
);
return
window
.
localStorage
.
setItem
(
this
.
key
,
text
);
}
}
...
@@ -51,6 +58,7 @@ export default class Autosave {
...
@@ -51,6 +58,7 @@ export default class Autosave {
reset
()
{
reset
()
{
if
(
!
this
.
isLocalStorageAvailable
)
return
;
if
(
!
this
.
isLocalStorageAvailable
)
return
;
window
.
localStorage
.
removeItem
(
this
.
fallbackKey
);
return
window
.
localStorage
.
removeItem
(
this
.
key
);
return
window
.
localStorage
.
removeItem
(
this
.
key
);
}
}
...
...
app/assets/javascripts/issuable_form.js
View file @
7100c7a2
...
@@ -6,6 +6,36 @@ import UsersSelect from './users_select';
...
@@ -6,6 +6,36 @@ import UsersSelect from './users_select';
import
ZenMode
from
'
./zen_mode
'
;
import
ZenMode
from
'
./zen_mode
'
;
import
AutoWidthDropdownSelect
from
'
./issuable/auto_width_dropdown_select
'
;
import
AutoWidthDropdownSelect
from
'
./issuable/auto_width_dropdown_select
'
;
import
{
parsePikadayDate
,
pikadayToString
}
from
'
./lib/utils/datetime_utility
'
;
import
{
parsePikadayDate
,
pikadayToString
}
from
'
./lib/utils/datetime_utility
'
;
import
{
queryToObject
,
objectToQuery
}
from
'
./lib/utils/url_utility
'
;
function
organizeQuery
(
obj
,
isFallbackKey
=
false
)
{
const
sourceBranch
=
'
merge_request[source_branch]
'
;
const
targetBranch
=
'
merge_request[target_branch]
'
;
if
(
isFallbackKey
)
{
return
{
[
sourceBranch
]:
obj
[
sourceBranch
],
};
}
return
{
[
sourceBranch
]:
obj
[
sourceBranch
],
[
targetBranch
]:
obj
[
targetBranch
],
};
}
function
format
(
searchTerm
,
isFallbackKey
=
false
)
{
const
queryObject
=
queryToObject
(
searchTerm
);
const
organizeQueryObject
=
organizeQuery
(
queryObject
,
isFallbackKey
);
const
formattedQuery
=
objectToQuery
(
organizeQueryObject
);
return
formattedQuery
;
}
function
getFallbackKey
()
{
const
searchTerm
=
format
(
document
.
location
.
search
,
true
);
return
[
'
autosave
'
,
document
.
location
.
pathname
,
searchTerm
].
join
(
'
/
'
);
}
export
default
class
IssuableForm
{
export
default
class
IssuableForm
{
constructor
(
form
)
{
constructor
(
form
)
{
...
@@ -57,16 +87,20 @@ export default class IssuableForm {
...
@@ -57,16 +87,20 @@ export default class IssuableForm {
}
}
initAutosave
()
{
initAutosave
()
{
this
.
autosave
=
new
Autosave
(
this
.
titleField
,
[
const
searchTerm
=
format
(
document
.
location
.
search
);
document
.
location
.
pathname
,
const
fallbackKey
=
getFallbackKey
();
document
.
location
.
search
,
'
title
'
,
this
.
autosave
=
new
Autosave
(
]);
this
.
titleField
,
return
new
Autosave
(
this
.
descriptionField
,
[
[
document
.
location
.
pathname
,
searchTerm
,
'
title
'
],
document
.
location
.
pathname
,
`
${
fallbackKey
}
=title`
,
document
.
location
.
search
,
);
'
description
'
,
]);
return
new
Autosave
(
this
.
descriptionField
,
[
document
.
location
.
pathname
,
searchTerm
,
'
description
'
],
`
${
fallbackKey
}
=description`
,
);
}
}
handleSubmit
()
{
handleSubmit
()
{
...
...
app/assets/javascripts/lib/utils/url_utility.js
View file @
7100c7a2
...
@@ -181,4 +181,36 @@ export function getWebSocketUrl(path) {
...
@@ -181,4 +181,36 @@ export function getWebSocketUrl(path) {
return
`
${
getWebSocketProtocol
()}
//
${
joinPaths
(
window
.
location
.
host
,
path
)}
`
;
return
`
${
getWebSocketProtocol
()}
//
${
joinPaths
(
window
.
location
.
host
,
path
)}
`
;
}
}
/**
* Convert search query into an object
*
* @param {String} query from "document.location.search"
* @returns {Object}
*
* ex: "?one=1&two=2" into {one: 1, two: 2}
*/
export
function
queryToObject
(
query
)
{
const
removeQuestionMarkFromQuery
=
String
(
query
).
startsWith
(
'
?
'
)
?
query
.
slice
(
1
)
:
query
;
return
removeQuestionMarkFromQuery
.
split
(
'
&
'
).
reduce
((
accumulator
,
curr
)
=>
{
const
p
=
curr
.
split
(
'
=
'
);
accumulator
[
decodeURIComponent
(
p
[
0
])]
=
decodeURIComponent
(
p
[
1
]);
return
accumulator
;
},
{});
}
/**
* Convert search query object back into a search query
*
* @param {Object} obj that needs to be converted
* @returns {String}
*
* ex: {one: 1, two: 2} into "one=1&two=2"
*
*/
export
function
objectToQuery
(
obj
)
{
return
Object
.
keys
(
obj
)
.
map
(
k
=>
`
${
encodeURIComponent
(
k
)}
=
${
encodeURIComponent
(
obj
[
k
])}
`
)
.
join
(
'
&
'
);
}
export
{
joinPaths
};
export
{
joinPaths
};
changelogs/unreleased/30016-changing-branch-keep-details.yml
0 → 100644
View file @
7100c7a2
---
title
:
Keep details in MR when changing target branch
merge_request
:
19138
author
:
type
:
changed
spec/frontend/autosave_spec.js
View file @
7100c7a2
...
@@ -9,6 +9,7 @@ describe('Autosave', () => {
...
@@ -9,6 +9,7 @@ describe('Autosave', () => {
let
autosave
;
let
autosave
;
const
field
=
$
(
'
<textarea></textarea>
'
);
const
field
=
$
(
'
<textarea></textarea>
'
);
const
key
=
'
key
'
;
const
key
=
'
key
'
;
const
fallbackKey
=
'
fallbackKey
'
;
describe
(
'
class constructor
'
,
()
=>
{
describe
(
'
class constructor
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
...
@@ -22,6 +23,13 @@ describe('Autosave', () => {
...
@@ -22,6 +23,13 @@ describe('Autosave', () => {
expect
(
AccessorUtilities
.
isLocalStorageAccessSafe
).
toHaveBeenCalled
();
expect
(
AccessorUtilities
.
isLocalStorageAccessSafe
).
toHaveBeenCalled
();
expect
(
autosave
.
isLocalStorageAvailable
).
toBe
(
true
);
expect
(
autosave
.
isLocalStorageAvailable
).
toBe
(
true
);
});
});
it
(
'
should set .isLocalStorageAvailable if fallbackKey is passed
'
,
()
=>
{
autosave
=
new
Autosave
(
field
,
key
,
fallbackKey
);
expect
(
AccessorUtilities
.
isLocalStorageAccessSafe
).
toHaveBeenCalled
();
expect
(
autosave
.
isLocalStorageAvailable
).
toBe
(
true
);
});
});
});
describe
(
'
restore
'
,
()
=>
{
describe
(
'
restore
'
,
()
=>
{
...
@@ -151,4 +159,33 @@ describe('Autosave', () => {
...
@@ -151,4 +159,33 @@ describe('Autosave', () => {
});
});
});
});
});
});
describe
(
'
restore with fallbackKey
'
,
()
=>
{
beforeEach
(()
=>
{
autosave
=
{
field
,
key
,
fallbackKey
,
};
autosave
.
isLocalStorageAvailable
=
true
;
});
it
(
'
should call .getItem
'
,
()
=>
{
Autosave
.
prototype
.
restore
.
call
(
autosave
);
expect
(
window
.
localStorage
.
getItem
).
toHaveBeenCalledWith
(
fallbackKey
);
});
it
(
'
should call .setItem for key and fallbackKey
'
,
()
=>
{
Autosave
.
prototype
.
save
.
call
(
autosave
);
expect
(
window
.
localStorage
.
setItem
).
toHaveBeenCalledTimes
(
2
);
});
it
(
'
should call .removeItem for key and fallbackKey
'
,
()
=>
{
Autosave
.
prototype
.
reset
.
call
(
autosave
);
expect
(
window
.
localStorage
.
removeItem
).
toHaveBeenCalledTimes
(
2
);
});
});
});
});
spec/frontend/lib/utils/url_utility_spec.js
View file @
7100c7a2
...
@@ -282,4 +282,20 @@ describe('URL utility', () => {
...
@@ -282,4 +282,20 @@ describe('URL utility', () => {
expect
(
urlUtils
.
getWebSocketUrl
(
path
)).
toEqual
(
'
ws://example.com/lorem/ipsum?a=bc
'
);
expect
(
urlUtils
.
getWebSocketUrl
(
path
)).
toEqual
(
'
ws://example.com/lorem/ipsum?a=bc
'
);
});
});
});
});
describe
(
'
queryToObject
'
,
()
=>
{
it
(
'
converts search query into an object
'
,
()
=>
{
const
searchQuery
=
'
?one=1&two=2
'
;
expect
(
urlUtils
.
queryToObject
(
searchQuery
)).
toEqual
({
one
:
'
1
'
,
two
:
'
2
'
});
});
});
describe
(
'
objectToQuery
'
,
()
=>
{
it
(
'
converts search query object back into a search query
'
,
()
=>
{
const
searchQueryObject
=
{
one
:
'
1
'
,
two
:
'
2
'
};
expect
(
urlUtils
.
objectToQuery
(
searchQueryObject
)).
toEqual
(
'
one=1&two=2
'
);
});
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment