Commit 0b500111 authored by Jacob Schatz's avatar Jacob Schatz

Adds support for multiple file updating.

parent 631ee31f
......@@ -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;
}
......
......@@ -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();
}
......
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
import Service from './repo_service'
import Helper from './repo_helper'
import Vue from 'vue'
import Store from './repo_store'
export default class RepoViewToggler {
export default class RepoEditButton {
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
......@@ -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());
}
}
}
......
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: {
setRawPreviewMode() {
rawPreviewToggle() {
Helper.setCurrentFileRawOrPreview();
}
}
},
});
}
}
\ No newline at end of file
......@@ -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) {
......
......@@ -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
......
......@@ -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: '',
......
......@@ -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);
}
}
......
......@@ -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;
......
......@@ -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'
......
.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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment