Commit 69618e30 authored by Luke "Jared" Bennett's avatar Luke "Jared" Bennett

Merge branch 'ide' of gitlab.com:gitlab-org/gitlab-ce into ide

parents 2e025023 631ee31f
...@@ -19,10 +19,27 @@ export default class RepoBinaryViewer { ...@@ -19,10 +19,27 @@ export default class RepoBinaryViewer {
}, },
}, },
methods: {
supportedNonBinaryFileType() {
switch (this.activeFile.extension) {
case 'md':
this.binaryTypes.markdown = true;
return true;
default:
return false;
}
},
},
watch: { watch: {
blobRaw() { blobRaw() {
const supported = this.supportedNonBinaryFileType();
if (supported) {
this.binaryTypes.markdown = true;
this.binary = true;
return;
}
if (!this.binary) return; if (!this.binary) return;
switch (this.binaryMimeType) { switch (this.binaryMimeType) {
case 'image/png': case 'image/png':
this.binaryTypes.png = true; this.binaryTypes.png = true;
......
import Tabs from './repo_tabs'; import Tabs from './repo_tabs';
import Sidebar from './repo_sidebar'; import Sidebar from './repo_sidebar';
import Editor from './repo_editor'; import Editor from './repo_editor';
import FileButtons from './repo_file_buttons';
import BinaryViewer from './repo_binary_viewer'; import BinaryViewer from './repo_binary_viewer';
import ViewToggler from './repo_view_toggler';
import Service from './repo_service'; import Service from './repo_service';
import Store from './repo_store'; import Store from './repo_store';
import Helper from './repo_helper'; import Helper from './repo_helper';
...@@ -15,7 +15,8 @@ export default class RepoBundle { ...@@ -15,7 +15,8 @@ export default class RepoBundle {
Store.tabs = new Tabs(); Store.tabs = new Tabs();
Store.sidebar = new Sidebar(url); Store.sidebar = new Sidebar(url);
Store.editor = new Editor(); Store.editor = new Editor();
Store.toggler = new ViewToggler(); Store.buttons = new FileButtons();
// Store.toggler = new ViewToggler();
Store.binaryViewer = new BinaryViewer(); Store.binaryViewer = new BinaryViewer();
Helper.getContent(); Helper.getContent();
} }
......
...@@ -9,6 +9,20 @@ export default class RepoEditor { ...@@ -9,6 +9,20 @@ export default class RepoEditor {
this.el = document.getElementById('ide'); this.el = document.getElementById('ide');
} }
addMonacoEvents() {
this.vue.$watch('activeFile.lineNumber', () => {
console.log('cahnged');
});
this.monacoEditor.onMouseUp(this.onMonacoEditorMouseUp);
}
onMonacoEditorMouseUp(e) {
if (e.target.element.className === 'line-numbers') {
location.hash = `L${e.target.position.lineNumber}`;
Store.activeLine = e.target.position.lineNumber;
}
}
initMonaco() { initMonaco() {
window.require.config({ paths: { vs: '/monaco-editor/min/vs' } }); window.require.config({ paths: { vs: '/monaco-editor/min/vs' } });
window.require(['vs/editor/editor.main'], () => { window.require(['vs/editor/editor.main'], () => {
...@@ -16,11 +30,15 @@ export default class RepoEditor { ...@@ -16,11 +30,15 @@ export default class RepoEditor {
.create( .create(
document.getElementById('ide'), { document.getElementById('ide'), {
model: null, model: null,
readOnly: true,
contextmenu: false,
}, },
); );
Helper.monacoInstance = monaco; Helper.monacoInstance = monaco;
this.initVue(); this.initVue();
monaco.languages.getLanguages(); monaco.languages.getLanguages();
this.addMonacoEvents();
}); });
} }
...@@ -30,6 +48,7 @@ export default class RepoEditor { ...@@ -30,6 +48,7 @@ export default class RepoEditor {
this.vue = new Vue({ this.vue = new Vue({
data: () => Store, data: () => Store,
created() { created() {
this.showHide();
if (this.blobRaw !== '') { if (this.blobRaw !== '') {
monacoEditor.setModel( monacoEditor.setModel(
monaco.editor.createModel( monaco.editor.createModel(
...@@ -40,29 +59,39 @@ export default class RepoEditor { ...@@ -40,29 +59,39 @@ export default class RepoEditor {
} }
}, },
watch: { methods: {
isTree() { showHide() {
if (this.isTree || !this.openedFiles.length) { if ((!this.openedFiles.length) || this.binary) {
self.el.style.display = 'none'; self.el.style.display = 'none';
} else { } else {
self.el.style.display = 'inline-block'; self.el.style.display = 'inline-block';
} }
}, },
},
watch: {
activeLine() {
self.monacoEditor.setPosition({
lineNumber: this.activeLine,
column: 1,
});
},
isTree() {
this.showHide();
},
openedFiles() { openedFiles() {
if ((this.isTree || !this.openedFiles.length) || this.binary) { this.showHide();
self.el.style.display = 'none'; },
} else {
self.el.style.display = 'inline-block'; binary() {
} this.showHide();
}, },
blobRaw() { blobRaw() {
if (this.binary) { this.showHide();
self.el.style.display = 'none';
} else {
self.el.style.display = 'inline-block';
}
if (!this.isTree) { if (!this.isTree) {
self.monacoEditor.setModel( self.monacoEditor.setModel(
monaco.editor.createModel( monaco.editor.createModel(
......
const RepoFile = { const RepoFile = {
template: ` template: `
<tr v-if='!loading.tree || hasFiles'> <tr v-if='!loading.tree || hasFiles' :class='{"active": activeFile.url === file.url}'>
<td> <td>
<i class='fa' :class='file.icon' :style='{"margin-left": file.level * 10 + "px"}'></i> <i class='fa' :class='file.icon' :style='{"margin-left": file.level * 10 + "px"}'></i>
<a :href='file.url' @click.prevent='linkClicked(file)' :title='file.url'>{{file.name}}</a> <a :href='file.url' @click.prevent='linkClicked(file)' class='repo-file-name' :title='file.url'>{{file.name}}</a>
</td> </td>
<td v-if='!isMini'> <td v-if='!isMini' class='hidden-sm hidden-xs'>
<div class='ellipsis'>{{file.lastCommitMessage}}</div> <div class='commit-message'>{{file.lastCommitMessage}}</div>
</td> </td>
<td v-if='!isMini'> <td v-if='!isMini' class='hidden-xs'>
<span>{{file.lastCommitUpdate}}</span> <span>{{file.lastCommitUpdate}}</span>
</td> </td>
</tr> </tr>
...@@ -20,6 +20,7 @@ const RepoFile = { ...@@ -20,6 +20,7 @@ const RepoFile = {
isMini: Boolean, isMini: Boolean,
loading: Object, loading: Object,
hasFiles: Boolean, hasFiles: Boolean,
activeFile: Object,
}, },
methods: { methods: {
......
import Vue from 'vue';
import Store from './repo_store';
import Helper from './repo_helper';
export default class RepoSidebar {
constructor(url) {
this.url = url;
this.initVue();
this.el = document.getElementById('repo-file-buttons');
}
initVue() {
this.vue = new Vue({
el: '#repo-file-buttons',
data: () => Store,
template: `
<div id='repo-file-buttons' v-if='isMini'>
<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>
<a :href='historyFileUrl' class='btn btn-default'>History</a>
<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='#' class='btn btn-danger'>Delete</a>
</div>
`,
computed: {
previewLabel() {
return this.activeFile.raw ? 'Preview' : 'Raw';
},
canPreview() {
return this.activeFile.extension === 'md';
},
rawFileURL() {
return Helper.getRawURLFromBlobURL(this.activeFile.url);
},
blameFileUrl() {
return Helper.getBlameURLFromBlobURL(this.activeFile.url);
},
historyFileUrl() {
return Helper.getHistoryURLFromBlobURL(this.activeFile.url);
},
},
methods: {
setRawPreviewMode() {
},
},
});
}
}
const RepoFileOptions = {
template: `
<tr v-if='isMini' class='repo-file-options'>
<td>
<span class='title'>{{projectName}}</span>
<ul>
<li>
<a href='#' title='New File'>
<i class='fa fa-file-o'></i>
</a>
</li>
<li>
<a href='#' title='New Folder'>
<i class='fa fa-folder-o'></i>
</a>
</li>
</ul>
</td>
</tr>
`,
props: {
name: 'repo-file-options',
isMini: Boolean,
projectName: String,
},
};
export default RepoFileOptions;
...@@ -24,12 +24,14 @@ const RepoHelper = { ...@@ -24,12 +24,14 @@ const RepoHelper = {
}, },
blobURLtoParent(url) { blobURLtoParent(url) {
let joined = '';
const split = url.split('/'); const split = url.split('/');
split.pop(); split.pop();
const blobIndex = split.indexOf('blob'); const blobIndex = split.indexOf('blob');
if (blobIndex > -1) { if (blobIndex > -1) {
split[blobIndex] = 'tree'; split[blobIndex] = 'tree';
} }
joined = split.join('/');
return split.join('/'); return split.join('/');
}, },
...@@ -57,6 +59,13 @@ const RepoHelper = { ...@@ -57,6 +59,13 @@ const RepoHelper = {
return newList; return newList;
}, },
resetBinaryTypes() {
let s = '';
for (s in Store.binaryTypes) {
Store.binaryTypes[s] = false;
}
},
setActiveFile(file) { setActiveFile(file) {
Store.openedFiles = Store.openedFiles.map((openedFile) => { Store.openedFiles = Store.openedFiles.map((openedFile) => {
const activeFile = openedFile; const activeFile = openedFile;
...@@ -103,6 +112,14 @@ const RepoHelper = { ...@@ -103,6 +112,14 @@ const RepoHelper = {
return url.replace('blob', 'raw'); return url.replace('blob', 'raw');
}, },
getBlameURLFromBlobURL(url) {
return url.replace('blob', 'blame');
},
getHistoryURLFromBlobURL(url) {
return url.replace('blob', 'commits');
},
setBinaryDataAsBase64(url, file) { setBinaryDataAsBase64(url, file) {
Service.getBase64Content(url) Service.getBase64Content(url)
.then((response) => { .then((response) => {
...@@ -151,6 +168,9 @@ const RepoHelper = { ...@@ -151,6 +168,9 @@ const RepoHelper = {
this.setLoading(false, loadingData); this.setLoading(false, loadingData);
Store.isTree = this.isTree(data); Store.isTree = this.isTree(data);
if (!Store.isTree) { if (!Store.isTree) {
if (!file) {
file = data;
}
// it's a blob // it's a blob
Store.binary = data.binary; Store.binary = data.binary;
if (data.binary) { if (data.binary) {
...@@ -160,18 +180,29 @@ const RepoHelper = { ...@@ -160,18 +180,29 @@ const RepoHelper = {
data, data,
); );
data.binary = true; data.binary = true;
if (!file.url) {
file.url = location.pathname;
}
data.url = file.url; data.url = file.url;
this.addToOpenedFiles(data); this.addToOpenedFiles(data);
this.setActiveFile(data); this.setActiveFile(data);
} else { } else {
const parentURL = this.blobURLtoParent(Service.url);
Store.blobRaw = data.plain; Store.blobRaw = data.plain;
Store.prevURL = this.blobURLtoParent(parentURL); if (!file.url) {
file.url = location.pathname;
}
data.url = file.url; data.url = file.url;
data.binary = false; data.binary = false;
this.addToOpenedFiles(data); this.addToOpenedFiles(data);
this.setActiveFile(data); this.setActiveFile(data);
} }
// if the file tree is empty
if (Store.files.length === 0) {
const parentURL = this.blobURLtoParent(Service.url);
Service.url = parentURL;
this.getContent();
}
} else { } else {
// it's a tree // it's a tree
this.setDirectoryOpen(file); this.setDirectoryOpen(file);
...@@ -208,12 +239,8 @@ const RepoHelper = { ...@@ -208,12 +239,8 @@ const RepoHelper = {
}, },
/* eslint-enable no-param-reassign */ /* eslint-enable no-param-reassign */
dataToListOfFiles(data) { blobToSimpleBlob(blob) {
const a = []; return {
// push in blobs
data.blobs.forEach((blob) => {
a.push({
type: 'blob', type: 'blob',
name: blob.name, name: blob.name,
url: blob.url, url: blob.url,
...@@ -221,17 +248,29 @@ const RepoHelper = { ...@@ -221,17 +248,29 @@ const RepoHelper = {
lastCommitMessage: blob.last_commit.message, lastCommitMessage: blob.last_commit.message,
lastCommitUpdate: blob.last_commit.committed_date, lastCommitUpdate: blob.last_commit.committed_date,
level: 0, level: 0,
}); };
}); },
data.trees.forEach((tree) => { treeToSimpleTree(tree) {
a.push({ return {
type: 'tree', type: 'tree',
name: tree.name, name: tree.name,
url: tree.url, url: tree.url,
icon: this.toFA(tree.icon), icon: this.toFA(tree.icon),
level: 0, level: 0,
};
},
dataToListOfFiles(data) {
const a = [];
// push in blobs
data.blobs.forEach((blob) => {
a.push(this.blobToSimpleBlob(blob));
}); });
data.trees.forEach((tree) => {
a.push(this.treeToSimpleTree(tree));
}); });
data.submodules.forEach((submodule) => { data.submodules.forEach((submodule) => {
......
...@@ -3,36 +3,28 @@ const RepoLoadingFile = { ...@@ -3,36 +3,28 @@ const RepoLoadingFile = {
<tr v-if='loading.tree && !hasFiles'> <tr v-if='loading.tree && !hasFiles'>
<td> <td>
<div class="animation-container animation-container-small"> <div class="animation-container animation-container-small">
<div class="line-of-code-1"></div> <div v-for="n in 6" :class="lineOfCode(n)"></div>
<div class="line-of-code-2"></div>
<div class="line-of-code-3"></div>
<div class="line-of-code-4"></div>
<div class="line-of-code-5"></div>
<div class="line-of-code-6"></div>
</div> </div>
</td> </td>
<td v-if="!isMini"> <td v-if="!isMini" class='hidden-sm hidden-xs'>
<div class="animation-container"> <div class="animation-container">
<div class="line-of-code-1"></div> <div v-for="n in 6" :class="lineOfCode(n)"></div>
<div class="line-of-code-2"></div>
<div class="line-of-code-3"></div>
<div class="line-of-code-4"></div>
<div class="line-of-code-5"></div>
<div class="line-of-code-6"></div>
</div> </div>
</td> </td>
<td v-if="!isMini"> <td v-if="!isMini" class='hidden-xs'>
<div class="animation-container animation-container-small"> <div class="animation-container animation-container-small">
<div class="line-of-code-1"></div> <div v-for="n in 6" :class="lineOfCode(n)"></div>
<div class="line-of-code-2"></div>
<div class="line-of-code-3"></div>
<div class="line-of-code-4"></div>
<div class="line-of-code-5"></div>
<div class="line-of-code-6"></div>
</div> </div>
</td> </td>
</tr> </tr>
`, `,
methods: {
lineOfCode(n) {
return `line-of-code-${n}`;
},
},
props: { props: {
loading: Object, loading: Object,
hasFiles: Boolean, hasFiles: Boolean,
......
...@@ -2,13 +2,13 @@ const RepoPreviousDirectory = { ...@@ -2,13 +2,13 @@ const RepoPreviousDirectory = {
template: ` template: `
<tr> <tr>
<td colspan='3'> <td colspan='3'>
<a :href='prevurl' @click.prevent='linkClicked(prevurl)'>..</a> <a :href='prevUrl' @click.prevent='linkClicked(prevurl)'>..</a>
</td> </td>
</tr> </tr>
`, `,
props: { props: {
name: 'repo-previous-directory', name: 'repo-previous-directory',
prevurl: String, prevUrl: String,
}, },
methods: { methods: {
......
...@@ -12,11 +12,20 @@ const RepoService = { ...@@ -12,11 +12,20 @@ const RepoService = {
this.url = url; this.url = url;
}, },
paramsWithRich(url) {
// copy the obj so we don't modify perm.
const params = JSON.parse(JSON.stringify(this.params));
if (url.substr(url.length - 2) === 'md') {
params.params.viewer = 'rich';
}
return params;
},
getContent(url) { getContent(url) {
if (url) { if (url) {
return axios.get(url, this.params); return axios.get(url, this.paramsWithRich(url, params));
} }
return axios.get(this.url, this.params); return axios.get(this.url, this.paramsWithRich(this.url, this.params));
}, },
getBase64Content(url) { getBase64Content(url) {
......
import Vue from 'vue';
import Service from './repo_service'; import Service from './repo_service';
import Helper from './repo_helper'; import Helper from './repo_helper';
import Vue from 'vue';
import Store from './repo_store'; import Store from './repo_store';
import RepoPreviousDirectory from './repo_prev_directory'; import RepoPreviousDirectory from './repo_prev_directory';
import RepoFileOptions from './repo_file_options';
import RepoFile from './repo_file'; import RepoFile from './repo_file';
import RepoLoadingFile from './repo_loading_file'; import RepoLoadingFile from './repo_loading_file';
import RepoMiniMixin from './repo_mini_mixin'; import RepoMiniMixin from './repo_mini_mixin';
...@@ -19,6 +20,7 @@ export default class RepoSidebar { ...@@ -19,6 +20,7 @@ export default class RepoSidebar {
el: '#sidebar', el: '#sidebar',
mixins: [RepoMiniMixin], mixins: [RepoMiniMixin],
components: { components: {
'repo-file-options': RepoFileOptions,
'repo-previous-directory': RepoPreviousDirectory, 'repo-previous-directory': RepoPreviousDirectory,
'repo-file': RepoFile, 'repo-file': RepoFile,
'repo-loading-file': RepoLoadingFile, 'repo-loading-file': RepoLoadingFile,
...@@ -33,6 +35,7 @@ export default class RepoSidebar { ...@@ -33,6 +35,7 @@ export default class RepoSidebar {
methods: { methods: {
addPopEventListener() { addPopEventListener() {
window.addEventListener('popstate', () => { window.addEventListener('popstate', () => {
if (location.href.indexOf('#') > -1) return;
this.linkClicked({ this.linkClicked({
url: location.href, url: location.href,
}); });
...@@ -41,19 +44,18 @@ export default class RepoSidebar { ...@@ -41,19 +44,18 @@ export default class RepoSidebar {
linkClicked(file) { linkClicked(file) {
let url = ''; let url = '';
if (typeof file === 'string') {
// go back
url = file;
} else {
url = file.url;
}
Service.url = url;
if (typeof file === 'object') { if (typeof file === 'object') {
if (file.type === 'tree' && file.opened) { if (file.type === 'tree' && file.opened) {
Helper.removeChildFilesOfTree(file); Helper.removeChildFilesOfTree(file);
return;
} }
url = file.url;
Service.url = url;
Helper.getContent(file); Helper.getContent(file);
} else if (typeof file === 'string') {
// go back
url = file;
Service.url = url;
Helper.getContent();
} }
}, },
}, },
......
...@@ -10,7 +10,18 @@ const RepoStore = { ...@@ -10,7 +10,18 @@ const RepoStore = {
blobRaw: '', blobRaw: '',
blobRendered: '', blobRendered: '',
openedFiles: [], openedFiles: [],
activeFile: '', activeFile: {
active: true,
binary: false,
extension: '',
html: '',
mime_type: '',
name: 'loading...',
plain: '',
size: 0,
url: '',
},
activeLine: 0,
files: [], files: [],
binary: false, binary: false,
binaryMimeType: '', binaryMimeType: '',
...@@ -18,6 +29,7 @@ const RepoStore = { ...@@ -18,6 +29,7 @@ const RepoStore = {
scrollWidth: 0, scrollWidth: 0,
binaryTypes: { binaryTypes: {
png: false, png: false,
markdown: false,
}, },
loading: { loading: {
tree: false, tree: false,
......
...@@ -120,3 +120,9 @@ of the body element here, we negate cascading side effects but allow momentum sc ...@@ -120,3 +120,9 @@ of the body element here, we negate cascading side effects but allow momentum sc
.page-with-sidebar { .page-with-sidebar {
-webkit-overflow-scrolling: auto; -webkit-overflow-scrolling: auto;
} }
.truncate {
width: 250px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
\ No newline at end of file
...@@ -118,3 +118,10 @@ ...@@ -118,3 +118,10 @@
@content; @content;
} }
} }
@mixin truncate($width: 250px) {
width: $width;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
...@@ -2,20 +2,18 @@ ...@@ -2,20 +2,18 @@
display: none; display: none;
} }
.ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 300px;
}
.fade-enter-active, .fade-leave-active { .fade-enter-active, .fade-leave-active {
transition: opacity .5s transition: opacity .5s
} }
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ { .fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0 opacity: 0
} }
.commit-message {
@include truncate(250px);
}
.tree-content-holder { .tree-content-holder {
border: 1px solid $border-color; border: 1px solid $border-color;
border-radius: $border-radius-default; border-radius: $border-radius-default;
...@@ -29,12 +27,26 @@ header { ...@@ -29,12 +27,26 @@ header {
.panel-right{ .panel-right{
display: inline-block; display: inline-block;
width: 85%; width: 85%;
.monaco-editor.vs {
.line-numbers{
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
.cursor {
background: rgba(255,255,255,0);
border-color: rgba(255,255,255,0);
}
}
#tabs { #tabs {
height: 41px; height: 41px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid $white-normal;
padding-left: 0; padding-left: 0;
margin-bottom: 0; margin-bottom: 0;
background: $gray-light;
display: inline-block; display: inline-block;
white-space: nowrap; white-space: nowrap;
width: 100%; width: 100%;
...@@ -68,6 +80,25 @@ header { ...@@ -68,6 +80,25 @@ header {
#ide { #ide {
height: 70vh; height: 70vh;
} }
#repo-file-buttons {
background: $gray-light;
padding: 5px;
margin-top: -5px;
border-bottom: 1px solid $white-normal;
}
#binary-viewer {
height: 70vh;
overflow: auto;
margin-top: 5px;
margin-left: 10px;
.blob-viewer {
padding-top: 20px;
padding-left: 20px;
}
}
} }
#view-toggler { #view-toggler {
...@@ -92,21 +123,72 @@ header { ...@@ -92,21 +123,72 @@ header {
vertical-align: top; vertical-align: top;
width: 15%; width: 15%;
border-right: 1px solid $white-normal; border-right: 1px solid $white-normal;
height: 75vh; height: 80vh;
overflow: auto; overflow: auto;
} }
tr { tr {
-webkit-animation: fadein 0.5s; -webkit-animation: fadein 0.5s;
&.repo-file-options td {
padding: 0;
border-top: none;
background: $gray-light;
width: 190px;
display: inline-block;
border-top: none;
&:hover {
.title {
width: 105px;
}
ul {
display: inline-block;
}
}
.title {
display: inline-block;
font-size: 10px;
text-transform: uppercase;
font-weight: bold;
color: $gray-darkest;
width: 185px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
padding: 2px 16px;
}
ul {
display: none;
float: right;
margin: 0 10px 0 0;
padding: 1px 0;
li {
display: inline-block;
padding: 0px 2px;
border-bottom: none;
}
}
}
.fa {
margin-right: 5px;
}
} }
a { a {
color: $almost-black; color: $almost-black;
display: inline-block;
vertical-align: middle;
} }
ul { ul {
list-style-type: none; list-style-type: none;
padding: 0; padding: 0;
li { li {
border-bottom: 1px solid $border-gray-normal; border-bottom: 1px solid $border-gray-normal;
padding: 10px 20px; padding: 10px 20px;
......
...@@ -132,7 +132,6 @@ ...@@ -132,7 +132,6 @@
} }
.tree-ref-holder { .tree-ref-holder {
float: left;
margin-right: 15px; margin-right: 15px;
} }
......
...@@ -11,8 +11,9 @@ module RendersBlob ...@@ -11,8 +11,9 @@ module RendersBlob
else else
blob.simple_viewer blob.simple_viewer
end end
return render_404 unless viewer return render_404 unless viewer
puts blob
if blob.binary? if blob.binary?
render json: { render json: {
binary: true, binary: true,
......
...@@ -37,12 +37,10 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -37,12 +37,10 @@ class Projects::BlobController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } assign_ref_vars
@environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last @last_commit = @repository.last_commit_for_path(@commit.id, tree.path) || @commit
@last_commit = @repository.last_commit_for_path(@commit.id, @blob.path) render 'projects/tree/show'
render 'show'
end end
format.json do format.json do
......
...@@ -11,4 +11,10 @@ ...@@ -11,4 +11,10 @@
- else - else
- viewer.prepare! - viewer.prepare!
= render 'projects/tree/tree_content' -# In the rare case where the first kilobyte of the file looks like text,
-# but the file turns out to actually be binary after loading all data,
-# we fall back on the binary Download viewer.
- viewer = BlobViewer::Download.new(viewer.blob) if viewer.binary_detected_after_load?
= render viewer.partial_path, viewer: viewer
...@@ -6,20 +6,23 @@ ...@@ -6,20 +6,23 @@
Name Name
%th{"v-else" => "1"} %th{"v-else" => "1"}
Project Project
%th{"v-if" => "!isMini"} %th.hidden-sm.hidden-xs{"v-if" => "!isMini"}
Last Commit Last Commit
%th{"v-if" => "!isMini"} %th.hidden-xs{"v-if" => "!isMini"}
Last Update Last Update
%tbody %tbody
%tr{ is: "repo-previous-directory", ":prevurl" => "prevURL", "@linkclicked" => "linkClicked" } %tr{ is: "repo-file-options", ":is-mini" => "isMini", "project-name" => @project.name }
%tr{ is: "repo-previous-directory", ":prev-url" => "prevURL", "@linkclicked" => "linkClicked(prevURL)" }
%tr{ is: "repo-loading-file", "v-for" => "n in 5", ":loading" => "loading", ":has-files" => "!!files.length", ":is-mini" => "isMini"} %tr{ is: "repo-loading-file", "v-for" => "n in 5", ":loading" => "loading", ":has-files" => "!!files.length", ":is-mini" => "isMini"}
%tr{ is: "repo-file", "v-for" => "file in files", ":key" => "file.id", ":file" => "file",":is-mini" => "isMini", "@linkclicked" => "linkClicked(file)", ":is-tree" => "isTree", ":loading" => "loading", ":has-files" => "!!files.length" } %tr{ is: "repo-file", "v-for" => "file in files", ":key" => "file.id", ":file" => "file",":is-mini" => "isMini", "@linkclicked" => "linkClicked(file)", ":is-tree" => "isTree", ":loading" => "loading", ":has-files" => "!!files.length", ":active-file" => "activeFile" }
.panel-right> .panel-right>
%ul#tabs{"v-if" => "isMini", ":style" => "{height: 41 + scrollWidth + 'px'}", "v-cloak" => "1"} %ul#tabs{"v-if" => "isMini", ":style" => "{height: 41 + scrollWidth + 'px'}", "v-cloak" => "1"}
%li{ is: "repo-tab", "v-for" => "tab in openedFiles", ":key" => "tab.id", ":tab" => "tab", ":class" => "{'active' : tab.active}" } %li{ is: "repo-tab", "v-for" => "tab in openedFiles", ":key" => "tab.id", ":tab" => "tab", ":class" => "{'active' : tab.active}" }
#repo-file-buttons
#ide{ data: { url: repo_url } } #ide{ data: { url: repo_url } }
#binary-viewer{ "v-if" => "binary" } #binary-viewer{ "v-if" => "binary" }
%img{"v-if" => "binaryTypes.png", ":src" => "pngBlobWithDataURI"} %img{"v-if" => "binaryTypes.png", ":src" => "pngBlobWithDataURI"}
%div{"v-if" => "binaryTypes.markdown", "v-html" => "activeFile.html"}
- if can_edit_tree? - 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/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' = render 'projects/blob/new_dir'
......
.tree-controls .tree-controls
%a.btn.btn-default.editable-mode{"href"=>"#"}
Edit mode
= render 'projects/find_file_link' = render 'projects/find_file_link'
= link_to s_('Commits|History'), namespace_project_commits_path(@project.namespace, @project, @id), class: 'btn btn-grouped'
= render 'projects/buttons/download', project: @project, ref: @ref = render 'projects/buttons/download', project: @project, ref: @ref
.tree-ref-holder .tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path = render 'shared/ref_switcher', destination: 'tree', path: @path
%ul.breadcrumb.repo-breadcrumb
%li
= link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
= @project.path
- path_breadcrumbs do |title, path|
%li
= link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, tree_join(@ref, path))
- if current_user
%li
- if !on_top_of_branch?
%span.btn.add-to-tree.disabled.has-tooltip{ title: _("You can only add files when you are on a branch"), data: { container: 'body' } }
= icon('plus')
- else
%span.dropdown
%a.dropdown-toggle.btn.add-to-tree{ href: '#', "data-toggle" => "dropdown" }
= icon('plus')
%ul.dropdown-menu
- if can_edit_tree?
%li
= link_to namespace_project_new_blob_path(@project.namespace, @project, @id) do
= icon('pencil fw')
#{ _('New file') }
%li
= link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } do
= icon('file fw')
#{ _('Upload file') }
%li
= link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal' } do
= icon('folder fw')
#{ _('New directory') }
- elsif can?(current_user, :fork_project, @project)
%li
- continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @id),
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params)
= link_to fork_path, method: :post do
= icon('pencil fw')
#{ _('New file') }
%li
- continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to upload a file again.",
notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params)
= link_to fork_path, method: :post do
= icon('file fw')
#{ _('Upload file') }
%li
- continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to create a new directory again.",
notice_now: edit_in_new_fork_notice_now }
- fork_path = namespace_project_forks_path(@project.namespace, @project, namespace_key: current_user.namespace.id,
continue: continue_params)
= link_to fork_path, method: :post do
= icon('folder fw')
#{ _('New directory') }
%li.divider
%li
= link_to new_namespace_project_branch_path(@project.namespace, @project) do
= icon('code-fork fw')
#{ _('New branch') }
%li
= link_to new_namespace_project_tag_path(@project.namespace, @project) do
= icon('tags fw')
#{ _('New tag') }
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