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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
caee9d58
Commit
caee9d58
authored
Oct 12, 2017
by
Phil Hughes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new files & directories in the multi-file editor
Closes #38614
parent
5295f23b
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
257 additions
and
32 deletions
+257
-32
app/assets/javascripts/repo/components/new_dropdown/index.vue
...assets/javascripts/repo/components/new_dropdown/index.vue
+70
-0
app/assets/javascripts/repo/components/new_dropdown/modal.vue
...assets/javascripts/repo/components/new_dropdown/modal.vue
+115
-0
app/assets/javascripts/repo/components/repo_commit_section.vue
...ssets/javascripts/repo/components/repo_commit_section.vue
+1
-1
app/assets/javascripts/repo/components/repo_editor.vue
app/assets/javascripts/repo/components/repo_editor.vue
+25
-18
app/assets/javascripts/repo/components/repo_file_buttons.vue
app/assets/javascripts/repo/components/repo_file_buttons.vue
+10
-2
app/assets/javascripts/repo/components/repo_tab.vue
app/assets/javascripts/repo/components/repo_tab.vue
+2
-2
app/assets/javascripts/repo/helpers/repo_helper.js
app/assets/javascripts/repo/helpers/repo_helper.js
+3
-1
app/assets/javascripts/repo/index.js
app/assets/javascripts/repo/index.js
+15
-0
app/assets/javascripts/repo/mixins/repo_mixin.js
app/assets/javascripts/repo/mixins/repo_mixin.js
+1
-1
app/assets/javascripts/repo/stores/repo_store.js
app/assets/javascripts/repo/stores/repo_store.js
+6
-1
app/assets/javascripts/vue_shared/components/popup_dialog.vue
...assets/javascripts/vue_shared/components/popup_dialog.vue
+6
-5
app/views/projects/tree/_tree_header.html.haml
app/views/projects/tree/_tree_header.html.haml
+3
-1
No files found.
app/assets/javascripts/repo/components/new_dropdown/index.vue
0 → 100644
View file @
caee9d58
<
script
>
import
newModal
from
'
./modal.vue
'
;
export
default
{
components
:
{
newModal
,
},
data
()
{
return
{
openModal
:
false
,
modalType
:
''
,
};
},
methods
:
{
createNewItem
(
type
)
{
this
.
modalType
=
type
;
this
.
toggleModalOpen
();
},
toggleModalOpen
()
{
this
.
openModal
=
!
this
.
openModal
;
},
},
};
</
script
>
<
template
>
<div
class=
"breadcrumb repo-breadcrumb"
>
<div
class=
"dropdown"
>
<button
type=
"button"
class=
"btn btn-default dropdown-toggle add-to-tree"
data-toggle=
"dropdown"
data-target=
".add-to-tree-dropdown"
>
<i
class=
"fa fa-plus"
aria-hidden=
"true"
>
</i>
</button>
</div>
<div
class=
"add-to-tree-dropdown"
>
<ul
class=
"dropdown-menu"
>
<li>
<a
href=
"#"
role=
"button"
@
click.prevent=
"createNewItem('blob')"
>
{{
__
(
'
New file
'
)
}}
</a>
</li>
<li>
<a
href=
"#"
role=
"button"
@
click.prevent=
"createNewItem('tree')"
>
{{
__
(
'
New directory
'
)
}}
</a>
</li>
</ul>
</div>
<new-modal
v-if=
"openModal"
:type=
"modalType"
@
toggle=
"toggleModalOpen"
/>
</div>
</
template
>
app/assets/javascripts/repo/components/new_dropdown/modal.vue
0 → 100644
View file @
caee9d58
<
script
>
import
{
__
}
from
'
../../../locale
'
;
import
popupDialog
from
'
../../../vue_shared/components/popup_dialog.vue
'
;
import
RepoStore
from
'
../../stores/repo_store
'
;
import
RepoHelper
from
'
../../helpers/repo_helper
'
;
export
default
{
props
:
{
type
:
{
type
:
String
,
required
:
true
,
},
},
data
()
{
return
{
entryName
:
''
,
};
},
components
:
{
popupDialog
,
},
methods
:
{
createEntryInStore
()
{
if
(
this
.
entryName
===
''
)
return
;
const
fileName
=
this
.
type
===
'
tree
'
?
'
.gitkeep
'
:
this
.
entryName
;
let
tree
=
null
;
if
(
this
.
type
===
'
tree
'
)
{
tree
=
RepoHelper
.
serializeTree
({
name
:
this
.
entryName
,
path
:
this
.
entryName
,
tempFile
:
true
,
});
RepoStore
.
files
.
push
(
tree
);
RepoHelper
.
setDirectoryOpen
(
tree
,
tree
.
name
);
}
const
file
=
RepoHelper
.
serializeBlob
({
name
:
fileName
,
path
:
tree
?
`
${
tree
}
/
${
fileName
}
`
:
fileName
,
tempFile
:
true
,
});
if
(
tree
)
{
RepoStore
.
addFilesToDirectory
(
tree
,
RepoStore
.
files
,
[
file
]);
}
else
{
RepoStore
.
addFilesToDirectory
(
tree
,
RepoStore
.
files
,
[...
RepoStore
.
files
,
file
]);
}
RepoHelper
.
setFile
(
file
,
file
);
RepoStore
.
editMode
=
true
;
RepoStore
.
toggleBlobView
();
this
.
toggleModalOpen
();
},
toggleModalOpen
()
{
this
.
$emit
(
'
toggle
'
);
},
},
computed
:
{
modalTitle
()
{
if
(
this
.
type
===
'
tree
'
)
{
return
__
(
'
Create new directory
'
);
}
return
__
(
'
Create new file
'
);
},
buttonLabel
()
{
if
(
this
.
type
===
'
tree
'
)
{
return
__
(
'
Create directory
'
);
}
return
__
(
'
Create file
'
);
},
formLabelName
()
{
if
(
this
.
type
===
'
tree
'
)
{
return
__
(
'
Directory name
'
);
}
return
__
(
'
File name
'
);
},
},
};
</
script
>
<
template
>
<popup-dialog
:title=
"modalTitle"
:primary-button-label=
"buttonLabel"
kind=
"success"
@
toggle=
"toggleModalOpen"
@
submit=
"createEntryInStore"
>
<form
class=
"form-horizontal"
slot=
"body"
@
submit.prevent=
"createEntryInStore"
>
<fieldset
class=
"form-group append-bottom-0"
>
<label
class=
"label-light col-sm-3"
>
{{
formLabelName
}}
</label>
<div
class=
"col-sm-9"
>
<input
type=
"text"
class=
"form-control"
v-model=
"entryName"
/>
</div>
</fieldset>
</form>
</popup-dialog>
</
template
>
app/assets/javascripts/repo/components/repo_commit_section.vue
View file @
caee9d58
...
@@ -49,7 +49,7 @@ export default {
...
@@ -49,7 +49,7 @@ export default {
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
const
commitMessage
=
this
.
commitMessage
;
const
commitMessage
=
this
.
commitMessage
;
const
actions
=
this
.
changedFiles
.
map
(
f
=>
({
const
actions
=
this
.
changedFiles
.
map
(
f
=>
({
action
:
'
update
'
,
action
:
f
.
tempFile
?
'
create
'
:
'
update
'
,
file_path
:
f
.
path
,
file_path
:
f
.
path
,
content
:
f
.
newContent
,
content
:
f
.
newContent
,
}));
}));
...
...
app/assets/javascripts/repo/components/repo_editor.vue
View file @
caee9d58
...
@@ -16,28 +16,35 @@ const RepoEditor = {
...
@@ -16,28 +16,35 @@ const RepoEditor = {
},
},
mounted
()
{
mounted
()
{
Service
.
getRaw
(
this
.
activeFile
.
raw_path
)
if
(
!
this
.
activeFile
.
tempFile
)
{
.
then
((
rawResponse
)
=>
{
Service
.
getRaw
(
this
.
activeFile
.
raw_path
)
Store
.
blobRaw
=
rawResponse
.
data
;
.
then
((
rawResponse
)
=>
{
Store
.
activeFile
.
plain
=
rawResponse
.
data
;
Store
.
blobRaw
=
rawResponse
.
data
;
Store
.
activeFile
.
plain
=
rawResponse
.
data
;
const
monacoInstance
=
Helper
.
monaco
.
editor
.
create
(
this
.
$el
,
{
model
:
null
,
this
.
createMonacoInstance
();
readOnly
:
false
,
})
contextmenu
:
true
,
.
catch
(
Helper
.
loadingError
);
scrollBeyondLastLine
:
false
,
}
else
{
});
this
.
createMonacoInstance
();
}
},
Helper
.
monacoInstance
=
monacoInstance
;
methods
:
{
createMonacoInstance
()
{
const
monacoInstance
=
Helper
.
monaco
.
editor
.
create
(
this
.
$el
,
{
model
:
null
,
readOnly
:
false
,
contextmenu
:
true
,
scrollBeyondLastLine
:
false
,
});
this
.
addMonacoEvents
()
;
Helper
.
monacoInstance
=
monacoInstance
;
this
.
setupEditor
();
this
.
addMonacoEvents
();
})
.
catch
(
Helper
.
loadingError
);
},
methods
:
{
this
.
setupEditor
();
},
setupEditor
()
{
setupEditor
()
{
this
.
showHide
();
this
.
showHide
();
...
...
app/assets/javascripts/repo/components/repo_file_buttons.vue
View file @
caee9d58
...
@@ -11,7 +11,12 @@ const RepoFileButtons = {
...
@@ -11,7 +11,12 @@ const RepoFileButtons = {
mixins
:
[
RepoMixin
],
mixins
:
[
RepoMixin
],
computed
:
{
computed
:
{
showButtons
()
{
return
this
.
activeFile
.
raw_path
||
this
.
activeFile
.
blame_path
||
this
.
activeFile
.
commits_path
||
this
.
activeFile
.
permalink
;
},
rawDownloadButtonLabel
()
{
rawDownloadButtonLabel
()
{
return
this
.
binary
?
'
Download
'
:
'
Raw
'
;
return
this
.
binary
?
'
Download
'
:
'
Raw
'
;
},
},
...
@@ -30,7 +35,10 @@ export default RepoFileButtons;
...
@@ -30,7 +35,10 @@ export default RepoFileButtons;
</
script
>
</
script
>
<
template
>
<
template
>
<div
id=
"repo-file-buttons"
>
<div
v-if=
"showButtons"
id=
"repo-file-buttons"
>
<a
<a
:href=
"activeFile.raw_path"
:href=
"activeFile.raw_path"
target=
"_blank"
target=
"_blank"
...
...
app/assets/javascripts/repo/components/repo_tab.vue
View file @
caee9d58
...
@@ -18,8 +18,8 @@ const RepoTab = {
...
@@ -18,8 +18,8 @@ const RepoTab = {
},
},
changedClass
()
{
changedClass
()
{
const
tabChangedObj
=
{
const
tabChangedObj
=
{
'
fa-times close-icon
'
:
!
this
.
tab
.
changed
,
'
fa-times close-icon
'
:
!
this
.
tab
.
changed
&&
!
this
.
tab
.
tempFile
,
'
fa-circle unsaved-icon
'
:
this
.
tab
.
changed
,
'
fa-circle unsaved-icon
'
:
this
.
tab
.
changed
||
this
.
tab
.
tempFile
,
};
};
return
tabChangedObj
;
return
tabChangedObj
;
},
},
...
...
app/assets/javascripts/repo/helpers/repo_helper.js
View file @
caee9d58
...
@@ -157,7 +157,7 @@ const RepoHelper = {
...
@@ -157,7 +157,7 @@ const RepoHelper = {
},
},
serializeRepoEntity
(
type
,
entity
,
level
=
0
)
{
serializeRepoEntity
(
type
,
entity
,
level
=
0
)
{
const
{
id
,
url
,
name
,
icon
,
last_commit
,
tree_url
}
=
entity
;
const
{
id
,
url
,
name
,
icon
,
last_commit
,
tree_url
,
path
,
tempFile
}
=
entity
;
return
{
return
{
id
,
id
,
...
@@ -165,7 +165,9 @@ const RepoHelper = {
...
@@ -165,7 +165,9 @@ const RepoHelper = {
name
,
name
,
url
,
url
,
tree_url
,
tree_url
,
path
,
level
,
level
,
tempFile
,
icon
:
`fa-
${
icon
}
`
,
icon
:
`fa-
${
icon
}
`
,
files
:
[],
files
:
[],
loading
:
false
,
loading
:
false
,
...
...
app/assets/javascripts/repo/index.js
View file @
caee9d58
...
@@ -5,6 +5,7 @@ import Service from './services/repo_service';
...
@@ -5,6 +5,7 @@ import Service from './services/repo_service';
import
Store
from
'
./stores/repo_store
'
;
import
Store
from
'
./stores/repo_store
'
;
import
Repo
from
'
./components/repo.vue
'
;
import
Repo
from
'
./components/repo.vue
'
;
import
RepoEditButton
from
'
./components/repo_edit_button.vue
'
;
import
RepoEditButton
from
'
./components/repo_edit_button.vue
'
;
import
newDropdown
from
'
./components/new_dropdown/index.vue
'
;
import
Translate
from
'
../vue_shared/translate
'
;
import
Translate
from
'
../vue_shared/translate
'
;
function
initDropdowns
()
{
function
initDropdowns
()
{
...
@@ -62,9 +63,22 @@ function initRepoEditButton(el) {
...
@@ -62,9 +63,22 @@ function initRepoEditButton(el) {
});
});
}
}
function
initNewDropdown
(
el
)
{
return
new
Vue
({
el
,
components
:
{
newDropdown
,
},
render
(
createElement
)
{
return
createElement
(
'
new-dropdown
'
);
},
});
}
function
initRepoBundle
()
{
function
initRepoBundle
()
{
const
repo
=
document
.
getElementById
(
'
repo
'
);
const
repo
=
document
.
getElementById
(
'
repo
'
);
const
editButton
=
document
.
querySelector
(
'
.editable-mode
'
);
const
editButton
=
document
.
querySelector
(
'
.editable-mode
'
);
const
newDropdownHolder
=
document
.
querySelector
(
'
.js-new-dropdown
'
);
setInitialStore
(
repo
.
dataset
);
setInitialStore
(
repo
.
dataset
);
addEventsForNonVueEls
();
addEventsForNonVueEls
();
initDropdowns
();
initDropdowns
();
...
@@ -73,6 +87,7 @@ function initRepoBundle() {
...
@@ -73,6 +87,7 @@ function initRepoBundle() {
initRepo
(
repo
);
initRepo
(
repo
);
initRepoEditButton
(
editButton
);
initRepoEditButton
(
editButton
);
initNewDropdown
(
newDropdownHolder
);
}
}
$
(
initRepoBundle
);
$
(
initRepoBundle
);
...
...
app/assets/javascripts/repo/mixins/repo_mixin.js
View file @
caee9d58
...
@@ -8,7 +8,7 @@ const RepoMixin = {
...
@@ -8,7 +8,7 @@ const RepoMixin = {
changedFiles
()
{
changedFiles
()
{
const
changedFileList
=
this
.
openedFiles
const
changedFileList
=
this
.
openedFiles
.
filter
(
file
=>
file
.
changed
);
.
filter
(
file
=>
file
.
changed
||
file
.
tempFile
);
return
changedFileList
;
return
changedFileList
;
},
},
},
},
...
...
app/assets/javascripts/repo/stores/repo_store.js
View file @
caee9d58
...
@@ -75,7 +75,7 @@ const RepoStore = {
...
@@ -75,7 +75,7 @@ const RepoStore = {
RepoStore
.
blobRaw
=
file
.
base64
;
RepoStore
.
blobRaw
=
file
.
base64
;
}
else
if
(
file
.
newContent
||
file
.
plain
)
{
}
else
if
(
file
.
newContent
||
file
.
plain
)
{
RepoStore
.
blobRaw
=
file
.
newContent
||
file
.
plain
;
RepoStore
.
blobRaw
=
file
.
newContent
||
file
.
plain
;
}
else
{
}
else
if
(
!
file
.
tempFile
)
{
Service
.
getRaw
(
file
.
raw_path
)
Service
.
getRaw
(
file
.
raw_path
)
.
then
((
rawResponse
)
=>
{
.
then
((
rawResponse
)
=>
{
RepoStore
.
blobRaw
=
rawResponse
.
data
;
RepoStore
.
blobRaw
=
rawResponse
.
data
;
...
@@ -120,6 +120,11 @@ const RepoStore = {
...
@@ -120,6 +120,11 @@ const RepoStore = {
return
openedFile
.
path
!==
file
.
path
;
return
openedFile
.
path
!==
file
.
path
;
});
});
// remove the file from the sidebar if it is a tempFile
if
(
file
.
tempFile
)
{
RepoStore
.
files
=
RepoStore
.
files
.
filter
(
f
=>
!
(
f
.
tempFile
&&
f
.
path
===
file
.
path
));
}
// now activate the right tab based on what you closed.
// now activate the right tab based on what you closed.
if
(
RepoStore
.
openedFiles
.
length
===
0
)
{
if
(
RepoStore
.
openedFiles
.
length
===
0
)
{
RepoStore
.
activeFile
=
{};
RepoStore
.
activeFile
=
{};
...
...
app/assets/javascripts/vue_shared/components/popup_dialog.vue
View file @
caee9d58
...
@@ -9,7 +9,7 @@ export default {
...
@@ -9,7 +9,7 @@ export default {
},
},
text
:
{
text
:
{
type
:
String
,
type
:
String
,
required
:
tru
e
,
required
:
fals
e
,
},
},
kind
:
{
kind
:
{
type
:
String
,
type
:
String
,
...
@@ -82,14 +82,15 @@ export default {
...
@@ -82,14 +82,15 @@ export default {
type=
"button"
type=
"button"
class=
"btn"
class=
"btn"
:class=
"btnCancelKindClass"
:class=
"btnCancelKindClass"
@
click=
"
emitSubmit(false)
"
>
@
click=
"
close
"
>
{{
closeButtonLabel
}}
{{
closeButtonLabel
}}
</button>
</button>
<button
type=
"button"
<button
type=
"button"
class=
"btn"
class=
"btn"
:class=
"btnKindClass"
:class=
"btnKindClass"
@
click=
"emitSubmit(true)"
>
@
click=
"emitSubmit(true)"
>
{{
primaryButtonLabel
}}
{{
primaryButtonLabel
}}
</button>
</button>
</div>
</div>
</div>
</div>
...
...
app/views/projects/tree/_tree_header.html.haml
View file @
caee9d58
...
@@ -2,7 +2,9 @@
...
@@ -2,7 +2,9 @@
.tree-ref-holder
.tree-ref-holder
=
render
'shared/ref_switcher'
,
destination:
'tree'
,
path:
@path
=
render
'shared/ref_switcher'
,
destination:
'tree'
,
path:
@path
-
unless
show_new_repo?
-
if
show_new_repo?
.js-new-dropdown
-
else
=
render
'projects/tree/old_tree_header'
=
render
'projects/tree/old_tree_header'
.tree-controls
.tree-controls
...
...
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