diff --git a/app/assets/javascripts/repo/repo_binary_viewer.js b/app/assets/javascripts/repo/repo_binary_viewer.js new file mode 100644 index 00000000000..3b4024d8574 --- /dev/null +++ b/app/assets/javascripts/repo/repo_binary_viewer.js @@ -0,0 +1,33 @@ +import Vue from 'vue' +import Store from './repo_store' + +export default class RepoBinaryViewer { + constructor(url) { + this.initVue(); + } + + initVue() { + this.vue = new Vue({ + el: '#binary-viewer', + + data: () => Store, + + computed: { + pngBlobWithDataURI() { + return `data:image/png;base64,${this.blobRaw}`; + } + }, + + watch: { + blobRaw() { + if(!this.binary) return; + switch(this.binaryMimeType) { + case 'image/png': + this.binaryTypes.png = true; + break; + } + } + } + }); + } +} \ No newline at end of file diff --git a/app/assets/javascripts/repo/repo_bundle.js b/app/assets/javascripts/repo/repo_bundle.js index 44b3ce06f38..44c53cc21bf 100644 --- a/app/assets/javascripts/repo/repo_bundle.js +++ b/app/assets/javascripts/repo/repo_bundle.js @@ -1,6 +1,7 @@ import Tabs from './repo_tabs' import Sidebar from './repo_sidebar' import Editor from './repo_editor' +import BinaryViewer from './repo_binary_viewer' import Service from './repo_service' import Store from './repo_store' import Helper from './repo_helper' @@ -13,6 +14,7 @@ export default class RepoBundle { Store.tabs = new Tabs(); Store.sidebar = new Sidebar(url); Store.editor = new Editor(); + Store.binaryViewer = new BinaryViewer(); Helper.getContent(); } } diff --git a/app/assets/javascripts/repo/repo_editor.js b/app/assets/javascripts/repo/repo_editor.js index f9fc9658440..06ee3f83a93 100644 --- a/app/assets/javascripts/repo/repo_editor.js +++ b/app/assets/javascripts/repo/repo_editor.js @@ -20,6 +20,7 @@ export default class RepoEditor { ) Helper.monacoInstance = monaco; this.initVue(); + monaco.languages.getLanguages(); }); } @@ -49,14 +50,21 @@ export default class RepoEditor { }, openedFiles() { - if(this.isTree && !this.openedFiles.length) { + if((this.isTree && !this.openedFiles.length) || this.binary) { self.el.style.display = 'none'; } else { + console.log('inline-block'); self.el.style.display = 'inline-block'; } }, blobRaw() { + if(this.binary) { + self.el.style.display = 'none'; + } else { + console.log('inline-block2'); + self.el.style.display = 'inline-block'; + } if(!this.isTree) { self.monacoEditor.setModel( monaco.editor.createModel( diff --git a/app/assets/javascripts/repo/repo_helper.js b/app/assets/javascripts/repo/repo_helper.js index af0e3764b58..ba8020b2166 100644 --- a/app/assets/javascripts/repo/repo_helper.js +++ b/app/assets/javascripts/repo/repo_helper.js @@ -69,8 +69,14 @@ let RepoHelper = { } return openedFile; }); - Store.blobRaw = file.plain; + if(file.binary) { + Store.blobRaw = file.base64; + console.log('binary', file) + } else { + Store.blobRaw = file.plain; + } this.toURL(file.url); + Store.binary = file.binary; }, removeFromOpenedFiles(file) { @@ -96,6 +102,19 @@ let RepoHelper = { } }, + getRawURLFromBlobURL(url) { + return url.replace('blob', 'raw'); + }, + + setBinaryDataAsBase64(url, file) { + Service.getBase64Content(url) + .then((response) => { + Store.blobRaw = response; + file.base64 = response + console.log('file',file); + }); + }, + // may be tree or file. getContent(file) { Service.getContent() @@ -104,12 +123,26 @@ let RepoHelper = { Store.isTree = this.isTree(data); if(!Store.isTree) { // it's a blob - const parentURL = this.blobURLtoParent(Service.url); - Store.blobRaw = data.plain; - Store.prevURL = this.blobURLtoParent(parentURL); - data.url = file.url; - this.addToOpenedFiles(data); - this.setActiveFile(data); + Store.binary = data.binary; + if(data.binary) { + Store.binaryMimeType = data.mime_type; + this.setBinaryDataAsBase64( + this.getRawURLFromBlobURL(file.url), + data + ); + data.binary = true; + data.url = file.url; + this.addToOpenedFiles(data); + this.setActiveFile(data); + } else { + const parentURL = this.blobURLtoParent(Service.url); + Store.blobRaw = data.plain; + Store.prevURL = this.blobURLtoParent(parentURL); + data.url = file.url; + data.binary = false; + this.addToOpenedFiles(data); + this.setActiveFile(data); + } } else { // it's a tree this.setDirectoryOpen(file); diff --git a/app/assets/javascripts/repo/repo_service.js b/app/assets/javascripts/repo/repo_service.js index 6541bc4f339..137c468478d 100644 --- a/app/assets/javascripts/repo/repo_service.js +++ b/app/assets/javascripts/repo/repo_service.js @@ -17,6 +17,14 @@ let RepoService = { return axios.get(url, this.params); } return axios.get(this.url, this.params); + }, + + getBase64Content(url) { + return axios + .get(url, { + responseType: 'arraybuffer' + }) + .then(response => new Buffer(response.data, 'binary').toString('base64')) } }; diff --git a/app/assets/javascripts/repo/repo_store.js b/app/assets/javascripts/repo/repo_store.js index 5365c2646bd..3dbc7b41d11 100644 --- a/app/assets/javascripts/repo/repo_store.js +++ b/app/assets/javascripts/repo/repo_store.js @@ -11,6 +11,11 @@ let RepoStore = { blobRendered: '', openedFiles: [], activeFile: '', - files: [] + files: [], + binary: false, + binaryMimeType: '', + binaryTypes: { + png: false + } }; export default RepoStore; diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss index 3102b716438..3e0b6db8890 100644 --- a/app/assets/stylesheets/pages/repo.scss +++ b/app/assets/stylesheets/pages/repo.scss @@ -35,6 +35,10 @@ header { padding-left: 0; margin-bottom: 0; background: $gray-light; + display: inline-block; + white-space: nowrap; + width: 100%; + overflow: scroll; li { list-style-type: none; @@ -42,6 +46,7 @@ header { display: inline-block; padding: 10px 18px; border-right: 1px solid $border-color; + white-space: nowrap; &.active { background: $white-light; @@ -63,6 +68,11 @@ header { } } +#binary-viewer { + img { + max-width: 100%; + } +} #sidebar { &.sidebar-mini { diff --git a/app/controllers/concerns/renders_blob.rb b/app/controllers/concerns/renders_blob.rb index 46a3a64b3ad..591cfcb184b 100644 --- a/app/controllers/concerns/renders_blob.rb +++ b/app/controllers/concerns/renders_blob.rb @@ -13,13 +13,22 @@ module RendersBlob end return render_404 unless viewer puts blob - render json: { - html: view_to_html_string("projects/blob/_viewer", viewer: viewer, load_async: false), - plain: blob.data, - name: blob.name, - size: blob.size, - mime_type: blob.mime_type - } + if blob.binary? + render json: { + binary: true, + mime_type: blob.mime_type, + name: blob.name, + size: blob.size + } + else + render json: { + html: view_to_html_string("projects/blob/_viewer", viewer: viewer, load_async: false), + plain: blob.data, + name: blob.name, + size: blob.size, + mime_type: blob.mime_type + } + end end def conditionally_expand_blob(blob) diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index 948d46c02c9..045bade6bec 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -16,7 +16,8 @@ %ul#tabs{"v-if" => "isMini"} %li{ is: "repo-tab", "v-for" => "tab in openedFiles", ":key" => "tab.id", ":tab" => "tab", ":class" => "{'active' : tab.active}" } #ide{ data: { url: repo_url } } - + #binary-viewer{ "v-if" => "binary" } + %img{"v-if" => "binaryTypes.png", ":src" => "pngBlobWithDataURI"} - 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'