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
0b500111
Commit
0b500111
authored
Jul 17, 2017
by
Jacob Schatz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds support for multiple file updating.
parent
631ee31f
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
228 additions
and
46 deletions
+228
-46
app/assets/javascripts/repo/repo_binary_viewer.js
app/assets/javascripts/repo/repo_binary_viewer.js
+6
-12
app/assets/javascripts/repo/repo_bundle.js
app/assets/javascripts/repo/repo_bundle.js
+4
-2
app/assets/javascripts/repo/repo_commit_section.js
app/assets/javascripts/repo/repo_commit_section.js
+28
-0
app/assets/javascripts/repo/repo_edit_button.js
app/assets/javascripts/repo/repo_edit_button.js
+32
-0
app/assets/javascripts/repo/repo_editor.js
app/assets/javascripts/repo/repo_editor.js
+31
-5
app/assets/javascripts/repo/repo_file_buttons.js
app/assets/javascripts/repo/repo_file_buttons.js
+12
-7
app/assets/javascripts/repo/repo_helper.js
app/assets/javascripts/repo/repo_helper.js
+33
-13
app/assets/javascripts/repo/repo_sidebar.js
app/assets/javascripts/repo/repo_sidebar.js
+1
-1
app/assets/javascripts/repo/repo_store.js
app/assets/javascripts/repo/repo_store.js
+8
-1
app/assets/javascripts/repo/repo_tab.js
app/assets/javascripts/repo/repo_tab.js
+12
-1
app/assets/stylesheets/pages/repo.scss
app/assets/stylesheets/pages/repo.scss
+17
-2
app/views/projects/tree/_tree_content.html.haml
app/views/projects/tree/_tree_content.html.haml
+41
-0
app/views/projects/tree/_tree_header.html.haml
app/views/projects/tree/_tree_header.html.haml
+3
-2
No files found.
app/assets/javascripts/repo/repo_binary_viewer.js
View file @
0b500111
...
...
@@ -19,23 +19,17 @@ export default class RepoBinaryViewer {
},
methods
:
{
supportedNonBinaryFileType
()
{
switch
(
this
.
activeFile
.
extension
)
{
case
'
md
'
:
this
.
binaryTypes
.
markdown
=
true
;
return
true
;
break
;
default
:
return
false
;
}
}
isMarkdown
()
{
return
this
.
activeFile
.
extension
===
'
md
'
;
},
},
watch
:
{
blobRaw
()
{
let
supported
=
this
.
supportedNonBinaryFileType
();
if
(
supported
)
{
if
(
this
.
isMarkdown
())
{
this
.
binaryTypes
.
markdown
=
true
;
this
.
activeFile
.
raw
=
false
;
// counts as binaryish so we use the binary viewer in this case.
this
.
binary
=
true
;
return
;
}
...
...
app/assets/javascripts/repo/repo_bundle.js
View file @
0b500111
...
...
@@ -2,8 +2,9 @@ import Tabs from './repo_tabs'
import
Sidebar
from
'
./repo_sidebar
'
import
Editor
from
'
./repo_editor
'
import
FileButtons
from
'
./repo_file_buttons
'
import
EditButton
from
'
./repo_edit_button
'
import
BinaryViewer
from
'
./repo_binary_viewer
'
import
ViewToggler
from
'
./repo_view_toggler
'
import
CommitSection
from
'
./repo_commit_section
'
import
Service
from
'
./repo_service
'
import
Store
from
'
./repo_store
'
import
Helper
from
'
./repo_helper
'
...
...
@@ -17,7 +18,8 @@ export default class RepoBundle {
Store
.
sidebar
=
new
Sidebar
(
url
);
Store
.
editor
=
new
Editor
();
Store
.
buttons
=
new
FileButtons
();
// Store.toggler = new ViewToggler();
Store
.
editButton
=
new
EditButton
();
Store
.
commitSection
=
new
CommitSection
();
Store
.
binaryViewer
=
new
BinaryViewer
();
Helper
.
getContent
();
}
...
...
app/assets/javascripts/repo/repo_commit_section.js
0 → 100644
View file @
0b500111
import
Helper
from
'
./repo_helper
'
import
Vue
from
'
vue
'
import
Store
from
'
./repo_store
'
export
default
class
RepoCommitSection
{
constructor
()
{
this
.
initVue
();
this
.
el
=
document
.
getElementById
(
'
commit-area
'
);
}
initVue
()
{
this
.
vue
=
new
Vue
({
el
:
'
#commit-area
'
,
data
:
()
=>
Store
,
computed
:
{
changedFiles
()
{
const
changedFileList
=
this
.
openedFiles
.
filter
((
file
)
=>
{
return
file
.
changed
;
});
console
.
log
(
'
changedFileList
'
,
changedFileList
);
return
changedFileList
;
},
}
});
}
}
\ No newline at end of file
app/assets/javascripts/repo/repo_
view_toggler
.js
→
app/assets/javascripts/repo/repo_
edit_button
.js
View file @
0b500111
import
Service
from
'
./repo_service
'
import
Helper
from
'
./repo_helper
'
import
Vue
from
'
vue
'
import
Store
from
'
./repo_store
'
export
default
class
Repo
ViewToggler
{
export
default
class
Repo
EditButton
{
constructor
()
{
this
.
initVue
();
this
.
el
=
document
.
getElementById
(
'
editable-mode
'
);
}
initVue
()
{
this
.
vue
=
new
Vue
({
el
:
'
#view-toggler
'
,
el
:
'
#editable-mode
'
,
data
:
()
=>
Store
,
computed
:
{
buttonLabel
()
{
return
this
.
editMode
?
'
Read-only mode
'
:
'
Edit mode
'
;
},
buttonIcon
()
{
return
this
.
editMode
?
[]
:
[
'
fa
'
,
'
fa-pencil
'
];
}
},
methods
:
{
editClicked
()
{
this
.
editMode
=
!
this
.
editMode
;
}
}
});
}
}
\ No newline at end of file
app/assets/javascripts/repo/repo_editor.js
View file @
0b500111
...
...
@@ -10,10 +10,8 @@ export default class RepoEditor {
}
addMonacoEvents
()
{
this
.
vue
.
$watch
(
'
activeFile.lineNumber
'
,
()
=>
{
console
.
log
(
'
cahnged
'
)
})
this
.
monacoEditor
.
onMouseUp
(
this
.
onMonacoEditorMouseUp
);
this
.
monacoEditor
.
onMouseUp
(
this
.
onMonacoEditorMouseUp
.
bind
(
this
));
this
.
monacoEditor
.
onKeyUp
(
this
.
onMonacoEditorKeysPressed
.
bind
(
this
));
}
onMonacoEditorMouseUp
(
e
)
{
...
...
@@ -23,6 +21,10 @@ export default class RepoEditor {
}
}
onMonacoEditorKeysPressed
(
e
)
{
Helper
.
setActiveFileContents
(
this
.
monacoEditor
.
getValue
());
}
initMonaco
()
{
window
.
require
.
config
({
paths
:
{
vs
:
'
/monaco-editor/min/vs
'
}
});
window
.
require
([
'
vs/editor/editor.main
'
],
()
=>
{
...
...
@@ -61,7 +63,7 @@ export default class RepoEditor {
methods
:
{
showHide
()
{
if
(
(
!
this
.
openedFiles
.
length
)
||
this
.
binary
)
{
if
(
!
this
.
openedFiles
.
length
||
(
this
.
binary
&&
!
this
.
activeFile
.
raw
)
)
{
self
.
el
.
style
.
display
=
'
none
'
;
}
else
{
self
.
el
.
style
.
display
=
'
inline-block
'
;
...
...
@@ -77,6 +79,26 @@ export default class RepoEditor {
});
},
editMode
()
{
if
(
this
.
editMode
)
{
document
.
querySelector
(
'
.panel-right
'
).
classList
.
add
(
'
edit-mode
'
);
self
.
monacoEditor
.
updateOptions
({
readOnly
:
false
});
}
else
{
document
.
querySelector
(
'
.panel-right
'
).
classList
.
remove
(
'
edit-mode
'
);
self
.
monacoEditor
.
updateOptions
({
readOnly
:
true
});
}
},
activeFileLabel
()
{
this
.
showHide
();
},
isTree
()
{
this
.
showHide
();
},
...
...
@@ -93,12 +115,16 @@ export default class RepoEditor {
this
.
showHide
();
if
(
!
this
.
isTree
)
{
// kill the current model;
self
.
monacoEditor
.
setModel
(
null
);
// then create the new one
self
.
monacoEditor
.
setModel
(
monaco
.
editor
.
createModel
(
this
.
blobRaw
,
this
.
activeFile
.
mime_type
)
);
console
.
log
(
monaco
.
editor
.
getModels
());
}
}
}
...
...
app/assets/javascripts/repo/repo_file_buttons.js
View file @
0b500111
import
Vue
from
'
vue
'
import
Store
from
'
./repo_store
'
import
Helper
from
'
./repo_helper
'
import
RepoMiniMixin
from
'
./repo_mini_mixin
'
export
default
class
RepoSidebar
{
constructor
(
url
)
{
...
...
@@ -13,8 +14,9 @@ export default class RepoSidebar {
this
.
vue
=
new
Vue
({
el
:
'
#repo-file-buttons
'
,
data
:
()
=>
Store
,
mixins
:
[
RepoMiniMixin
],
template
:
`
<div id='repo-file-buttons' v-if='isMini'>
<div id='repo-file-buttons' v-if='isMini'
:style='{"border-bottom": editableBorder}'
>
<a :href='rawFileURL' target='_blank' class='btn btn-default'>Download file</a>
<div class="btn-group" role="group" aria-label="File actions">
<a :href='blameFileUrl' class='btn btn-default'>Blame</a>
...
...
@@ -22,13 +24,16 @@ export default class RepoSidebar {
<a href='#' class='btn btn-default'>Permalink</a>
<a href='#' class='btn btn-default'>Lock</a>
</div>
<a href='#' v-if='canPreview' class='btn btn-default'>{{previewLabel}}</a>
<a href='#' v-if='canPreview' @click.prevent='rawPreviewToggle' class='btn btn-default'>
{{activeFileLabel}}
</a>
<a href='#' class='btn btn-danger'>Delete</a>
</div>
`
,
computed
:
{
previewLabel
()
{
return
this
.
activeFile
.
raw
?
'
Preview
'
:
'
Raw
'
editableBorder
()
{
return
this
.
editMode
?
'
1px solid #1F78D1
'
:
'
1px solid #f0f0f0
'
;
},
canPreview
()
{
...
...
@@ -49,10 +54,10 @@ export default class RepoSidebar {
},
methods
:
{
setRawPreviewMod
e
()
{
rawPreviewToggl
e
()
{
Helper
.
setCurrentFileRawOrPreview
();
}
}
}
,
});
}
}
\ No newline at end of file
app/assets/javascripts/repo/repo_helper.js
View file @
0b500111
...
...
@@ -70,14 +70,29 @@ let RepoHelper = {
}
},
setCurrentFileRawOrPreview
()
{
Store
.
activeFile
.
raw
=
!
Store
.
activeFile
.
raw
;
Store
.
activeFileLabel
=
Store
.
activeFile
.
raw
?
'
Preview
'
:
'
Raw
'
;
},
setActiveFile
(
file
)
{
Store
.
openedFiles
=
Store
.
openedFiles
.
map
((
openedFile
)
=>
{
// don't load the file that is already loaded
if
(
file
.
url
===
Store
.
activeFile
.
url
)
return
;
Store
.
openedFiles
=
Store
.
openedFiles
.
map
((
openedFile
,
i
)
=>
{
openedFile
.
active
=
file
.
url
===
openedFile
.
url
;
if
(
openedFile
.
active
)
{
Store
.
activeFile
=
openedFile
;
Store
.
activeFileIndex
=
i
;
}
return
openedFile
;
});
// reset the active file raw
Store
.
activeFile
.
raw
=
false
;
// can't get vue to listen to raw for some reason so this for now.
Store
.
activeFileLabel
=
'
Raw
'
;
if
(
file
.
binary
)
{
Store
.
blobRaw
=
file
.
base64
;
}
else
{
...
...
@@ -101,6 +116,7 @@ let RepoHelper = {
return
openedFile
.
url
===
file
.
url
});
if
(
!
openedFilesAlreadyExists
)
{
file
.
changed
=
false
;
Store
.
openedFiles
.
push
(
file
);
}
},
...
...
@@ -132,6 +148,13 @@ let RepoHelper = {
});
},
setActiveFileContents
(
contents
)
{
if
(
!
Store
.
editMode
)
return
;
Store
.
activeFile
.
newContent
=
contents
;
Store
.
activeFile
.
changed
=
Store
.
activeFile
.
plain
!==
Store
.
activeFile
.
newContent
;
Store
.
openedFiles
[
Store
.
activeFileIndex
].
changed
=
Store
.
activeFile
.
changed
;
},
toggleFakeTab
(
loading
,
file
)
{
if
(
loading
)
{
const
randomURL
=
this
.
Time
.
now
();
...
...
@@ -163,6 +186,8 @@ let RepoHelper = {
// may be tree or file.
getContent
(
file
)
{
// don't load the same active file. That's silly.
// if(file && file.url === this.activeFile.url) return;
const
loadingData
=
this
.
setLoading
(
true
);
Service
.
getContent
()
.
then
((
response
)
=>
{
...
...
@@ -182,22 +207,17 @@ let RepoHelper = {
data
);
data
.
binary
=
true
;
if
(
!
file
.
url
)
{
file
.
url
=
location
.
pathname
;
}
data
.
url
=
file
.
url
;
this
.
addToOpenedFiles
(
data
);
this
.
setActiveFile
(
data
);
}
else
{
Store
.
blobRaw
=
data
.
plain
;
if
(
!
file
.
url
)
{
file
.
url
=
location
.
pathname
;
}
data
.
url
=
file
.
url
;
data
.
binary
=
false
;
this
.
addToOpenedFiles
(
data
);
this
.
setActiveFile
(
data
);
}
if
(
!
file
.
url
)
{
file
.
url
=
location
.
pathname
;
}
data
.
url
=
file
.
url
;
data
.
newContent
=
''
;
this
.
addToOpenedFiles
(
data
);
this
.
setActiveFile
(
data
);
// if the file tree is empty
if
(
Store
.
files
.
length
===
0
)
{
...
...
app/assets/javascripts/repo/repo_sidebar.js
View file @
0b500111
...
...
@@ -51,7 +51,7 @@ export default class RepoSidebar {
}
else
{
url
=
file
.
url
;
Service
.
url
=
url
;
Helper
.
getContent
(
file
);
Helper
.
getContent
(
file
);
}
}
else
if
(
typeof
file
===
'
string
'
)
{
// go back
...
...
app/assets/javascripts/repo/repo_store.js
View file @
0b500111
...
...
@@ -2,6 +2,8 @@ let RepoStore = {
service
:
''
,
editor
:
''
,
sidebar
:
''
,
editButton
:
''
,
editMode
:
false
,
isTree
:
false
,
prevURL
:
''
,
trees
:
[],
...
...
@@ -19,9 +21,14 @@ let RepoStore = {
name
:
'
loading...
'
,
plain
:
''
,
size
:
0
,
url
:
''
url
:
''
,
raw
:
false
,
newContent
:
''
,
changed
:
false
},
activeFileIndex
:
0
,
activeLine
:
0
,
activeFileLabel
:
'
Raw
'
,
files
:
[],
binary
:
false
,
binaryMimeType
:
''
,
...
...
app/assets/javascripts/repo/repo_tab.js
View file @
0b500111
...
...
@@ -4,7 +4,7 @@ let RepoTab = {
template
:
`
<li>
<a href='#' @click.prevent='xClicked(tab)' v-if='!tab.loading'>
<i class='fa
fa-times' :class="{'fa-times':saved, 'dot-circle-o': !saved}
"></i>
<i class='fa
' :class="changedClass
"></i>
</a>
<a href='#' v-if='!tab.loading' :title='tab.url' @click.prevent='tabClicked(tab)'>{{tab.name}}</a>
<i v-if='tab.loading' class='fa fa-spinner fa-spin'></i>
...
...
@@ -16,12 +16,23 @@ let RepoTab = {
saved
:
true
,
},
computed
:
{
changedClass
()
{
const
tabChangedObj
=
{
'
fa-times
'
:
!
this
.
tab
.
changed
,
'
fa-circle
'
:
this
.
tab
.
changed
};
return
tabChangedObj
}
},
methods
:
{
tabClicked
(
file
)
{
RepoHelper
.
setActiveFile
(
file
);
},
xClicked
(
file
)
{
if
(
file
.
changed
)
return
;
RepoHelper
.
removeFromOpenedFiles
(
file
);
}
}
...
...
app/assets/stylesheets/pages/repo.scss
View file @
0b500111
...
...
@@ -31,7 +31,7 @@ header {
.monaco-editor.vs
{
.line-numbers
{
cursor
:
pointer
;
&
:hover
{
text-decoration
:
underline
;
}
...
...
@@ -42,6 +42,15 @@ header {
}
}
&
.edit-mode
{
.monaco-editor.vs
{
.cursor
{
background
:
#000
;
border-color
:
#000
;
}
}
}
#tabs
{
height
:
41px
;
border-bottom
:
1px
solid
$white-normal
;
...
...
@@ -70,10 +79,11 @@ header {
color
:
black
;
}
i
.fa.fa-times
{
i
.fa.fa-times
,
i
.fa.fa-circle
{
float
:
right
;
margin-top
:
3px
;
margin-left
:
15px
;
color
:
$gray-darkest
;
}
}
}
...
...
@@ -101,6 +111,11 @@ header {
}
}
#commit-area
{
background
:
$gray-light
;
padding
:
20px
;
}
#view-toggler
{
height
:
41px
;
position
:
relative
;
...
...
app/views/projects/tree/_tree_content.html.haml
View file @
0b500111
...
...
@@ -23,6 +23,47 @@
#binary-viewer
{
"v-if"
=>
"binary"
}
%img
{
"v-if"
=>
"binaryTypes.png"
,
":src"
=>
"pngBlobWithDataURI"
}
%div
{
"v-if"
=>
"binaryTypes.markdown"
,
"v-html"
=>
"activeFile.html"
}
#commit-area
{
"v-if"
=>
"changedFiles.length"
}
%form
.form-horizontal
%fieldset
.form-group
%label
.col-md-4.control-label
Staged files ({{changedFiles.length}})
.col-md-4
%ul
.list-unstyled
%li
{
"v-for"
=>
"file in changedFiles"
}
%span
.help-block
{{file.url}}
/ Textarea
.form-group
%label
.col-md-4.control-label
{
:for
=>
"commit-message"
}
Commit message
.col-md-4
%textarea
#commit-message
.form-control
{
:name
=>
"commit-message"
}
Updating README.md
/ Button Drop Down
.form-group
%label
.col-md-4.control-label
{
:for
=>
"target-branch"
}
Target branch
.col-md-4
.input-group
.input-group-btn
%button
.btn.btn-default.dropdown-toggle
{
"data-toggle"
=>
"dropdown"
,
:type
=>
"button"
}
Action
=
icon
"caret-down"
%ul
.dropdown-menu.pull-right
%li
%a
{
:href
=>
"#"
}
Target branch
%li
%a
{
:href
=>
"#"
}
Create my own branch
%input
#target-branch
.form-control
{
:name
=>
"target-branch"
,
:placeholder
=>
"placeholder"
,
:type
=>
"text"
}
/
/ Multiple Checkboxes
.form-group
%label
.col-md-4.control-label
{
:for
=>
"checkboxes"
}
.col-md-4
.checkbox
%label
{
:for
=>
"checkboxes-0"
}
%input
#checkboxes-0
{
:name
=>
"checkboxes"
,
:type
=>
"checkbox"
,
:value
=>
"1"
}
/
Start a new merge request with these changes
-
if
can_edit_tree?
=
render
'projects/blob/upload'
,
title:
_
(
'Upload New File'
),
placeholder:
_
(
'Upload New File'
),
button_title:
_
(
'Upload file'
),
form_path:
namespace_project_create_blob_path
(
@project
.
namespace
,
@project
,
@id
),
method: :post
=
render
'projects/blob/new_dir'
...
...
app/views/projects/tree/_tree_header.html.haml
View file @
0b500111
.tree-controls
%a
.btn.btn-default.editable-mode
{
"href"
=>
"#"
}
Edit mode
%a
.btn.btn-default.btn-grouped
#editable-mode
{
"href"
=>
"#"
,
"@click.prevent"
=>
"editClicked"
,
"v-cloak"
=>
1
}
%i
{
":class"
=>
"buttonIcon"
}
%span
{{buttonLabel}}
=
render
'projects/find_file_link'
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
@ref
...
...
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