Commit f57b06ca authored by Tim Zallmann's avatar Tim Zallmann

Merge branch 'multi-file-editor-css-fixes' into 'master'

Added IDE commit panel

Closes #40041

See merge request gitlab-org/gitlab-ce!15583
parents 29298dc5 e9c70152
<script>
import icon from '../../../vue_shared/components/icon.vue';
import listItem from './list_item.vue';
import listCollapsed from './list_collapsed.vue';
export default {
components: {
icon,
listItem,
listCollapsed,
},
props: {
title: {
type: String,
required: true,
},
fileList: {
type: Array,
required: true,
},
collapsed: {
type: Boolean,
required: true,
},
},
methods: {
toggleCollapsed() {
this.$emit('toggleCollapsed');
},
},
};
</script>
<template>
<div class="multi-file-commit-panel-section">
<header
class="multi-file-commit-panel-header"
:class="{
'is-collapsed': collapsed,
}"
>
<icon
name="list-bulleted"
:size="18"
css-classes="append-right-default"
/>
<template v-if="!collapsed">
{{ title }}
<button
type="button"
class="btn btn-transparent multi-file-commit-panel-collapse-btn"
@click="toggleCollapsed"
>
<i
aria-hidden="true"
class="fa fa-angle-double-right"
>
</i>
</button>
</template>
</header>
<div class="multi-file-commit-list">
<list-collapsed
v-if="collapsed"
/>
<template v-else>
<ul
v-if="fileList.length"
class="list-unstyled append-bottom-0"
>
<li
v-for="file in fileList"
:key="file.key"
>
<list-item
:file="file"
/>
</li>
</ul>
<div
v-else
class="help-block prepend-top-0"
>
No changes
</div>
</template>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import icon from '../../../vue_shared/components/icon.vue';
export default {
components: {
icon,
},
computed: {
...mapGetters([
'addedFiles',
'modifiedFiles',
]),
},
};
</script>
<template>
<div
class="multi-file-commit-list-collapsed text-center"
>
<icon
name="file-addition"
:size="18"
css-classes="multi-file-addition append-bottom-10"
/>
{{ addedFiles.length }}
<icon
name="file-modified"
:size="18"
css-classes="multi-file-modified prepend-top-10 append-bottom-10"
/>
{{ modifiedFiles.length }}
</div>
</template>
<script>
import icon from '../../../vue_shared/components/icon.vue';
export default {
components: {
icon,
},
props: {
file: {
type: Object,
required: true,
},
},
computed: {
iconName() {
return this.file.tempFile ? 'file-addition' : 'file-modified';
},
iconClass() {
return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`;
},
},
};
</script>
<template>
<div class="multi-file-commit-list-item">
<icon
:name="iconName"
:size="16"
:css-classes="iconClass"
/>
<span class="multi-file-commit-list-path">
{{ file.path }}
</span>
</div>
</template>
......@@ -40,20 +40,24 @@ export default {
</script>
<template>
<div class="repository-view">
<div class="tree-content-holder" :class="{'tree-content-holder-mini' : isCollapsed}">
<repo-sidebar/>
<div
v-if="isCollapsed"
class="panel-right"
>
<repo-tabs/>
<component
:is="currentBlobView"
/>
<repo-file-buttons/>
</div>
<div
class="multi-file"
:class="{
'is-collapsed': isCollapsed
}"
>
<repo-sidebar/>
<div
v-if="isCollapsed"
class="multi-file-edit-pane"
>
<repo-tabs />
<component
class="multi-file-edit-pane-content"
:is="currentBlobView"
/>
<repo-file-buttons />
</div>
<repo-commit-section v-if="changedFiles.length" />
<repo-commit-section />
</div>
</template>
<script>
import { mapGetters, mapState, mapActions } from 'vuex';
import tooltip from '../../vue_shared/directives/tooltip';
import icon from '../../vue_shared/components/icon.vue';
import PopupDialog from '../../vue_shared/components/popup_dialog.vue';
import { n__ } from '../../locale';
import commitFilesList from './commit_sidebar/list.vue';
export default {
components: {
PopupDialog,
icon,
commitFilesList,
},
directives: {
tooltip,
},
data() {
return {
......@@ -13,6 +20,7 @@ export default {
submitCommitsLoading: false,
startNewMR: false,
commitMessage: '',
collapsed: true,
};
},
computed: {
......@@ -23,10 +31,10 @@ export default {
'changedFiles',
]),
commitButtonDisabled() {
return !this.commitMessage || this.submitCommitsLoading;
return this.commitMessage === '' || this.submitCommitsLoading || !this.changedFiles.length;
},
commitButtonText() {
return n__('Commit %d file', 'Commit %d files', this.changedFiles.length);
commitMessageCount() {
return this.commitMessage.length;
},
},
methods: {
......@@ -77,12 +85,20 @@ export default {
this.submitCommitsLoading = false;
});
},
toggleCollapsed() {
this.collapsed = !this.collapsed;
},
},
};
</script>
<template>
<div id="commit-area">
<div
class="multi-file-commit-panel"
:class="{
'is-collapsed': collapsed,
}"
>
<popup-dialog
v-if="showNewBranchDialog"
:primary-button-label="__('Create new branch')"
......@@ -92,78 +108,71 @@ export default {
@toggle="showNewBranchDialog = false"
@submit="makeCommit(true)"
/>
<button
v-if="collapsed"
type="button"
class="btn btn-transparent multi-file-commit-panel-collapse-btn is-collapsed prepend-top-10 append-bottom-10"
@click="toggleCollapsed"
>
<i
aria-hidden="true"
class="fa fa-angle-double-left"
>
</i>
</button>
<commit-files-list
title="Staged"
:file-list="changedFiles"
:collapsed="collapsed"
@toggleCollapsed="toggleCollapsed"
/>
<form
class="form-horizontal"
@submit.prevent="tryCommit()">
<fieldset>
<div class="form-group">
<label class="col-md-4 control-label staged-files">
Staged files ({{changedFiles.length}})
</label>
<div class="col-md-6">
<ul class="list-unstyled changed-files">
<li
v-for="(file, index) in changedFiles"
:key="index">
<span class="help-block">
{{ file.path }}
</span>
</li>
</ul>
</div>
</div>
<div class="form-group">
<label
class="col-md-4 control-label"
for="commit-message">
Commit message
</label>
<div class="col-md-6">
<textarea
id="commit-message"
class="form-control"
name="commit-message"
v-model="commitMessage">
</textarea>
</div>
</div>
<div class="form-group target-branch">
<label
class="col-md-4 control-label"
for="target-branch">
Target branch
</label>
<div class="col-md-6">
<span class="help-block">
{{currentBranch}}
</span>
</div>
</div>
<div class="col-md-offset-4 col-md-6">
<button
type="submit"
:disabled="commitButtonDisabled"
class="btn btn-success">
<i
v-if="submitCommitsLoading"
class="js-commit-loading-icon fa fa-spinner fa-spin"
aria-hidden="true"
aria-label="loading">
</i>
<span class="commit-summary">
{{ commitButtonText }}
</span>
</button>
</div>
<div class="col-md-offset-4 col-md-6">
<div class="checkbox">
<label>
<input type="checkbox" v-model="startNewMR">
<span>Start a <strong>new merge request</strong> with these changes</span>
</label>
</div>
class="form-horizontal multi-file-commit-form"
@submit.prevent="tryCommit"
v-if="!collapsed"
>
<div class="multi-file-commit-fieldset">
<textarea
class="form-control multi-file-commit-message"
name="commit-message"
v-model="commitMessage"
placeholder="Commit message"
>
</textarea>
</div>
<div class="multi-file-commit-fieldset">
<label
v-tooltip
title="Create a new merge request with these changes"
data-container="body"
data-placement="top"
>
<input
type="checkbox"
v-model="startNewMR"
/>
Merge Request
</label>
<button
type="submit"
:disabled="commitButtonDisabled"
class="btn btn-default btn-sm append-right-10 prepend-left-10"
>
<i
v-if="submitCommitsLoading"
class="js-commit-loading-icon fa fa-spinner fa-spin"
aria-hidden="true"
aria-label="loading"
>
</i>
Commit
</button>
<div
class="multi-file-commit-message-count"
>
{{ commitMessageCount }}
</div>
</fieldset>
</div>
</form>
</div>
</template>
......@@ -55,7 +55,7 @@
class="file"
@click.prevent="clickedTreeRow(file)">
<td
class="multi-file-table-col-name"
class="multi-file-table-name"
:colspan="submoduleColSpan"
>
<i
......@@ -85,12 +85,11 @@
</td>
<template v-if="!isCollapsed && !isSubmodule">
<td class="hidden-sm hidden-xs">
<td class="multi-file-table-col-commit-message hidden-sm hidden-xs">
<a
v-if="file.lastCommit.message"
@click.stop
:href="file.lastCommit.url"
class="commit-message"
>
{{ file.lastCommit.message }}
</a>
......
......@@ -22,12 +22,12 @@ export default {
<template>
<div
v-if="showButtons"
class="repo-file-buttons"
class="multi-file-editor-btn-group"
>
<a
:href="activeFile.rawPath"
target="_blank"
class="btn btn-default raw"
class="btn btn-default btn-sm raw"
rel="noopener noreferrer">
{{ rawDownloadButtonLabel }}
</a>
......@@ -38,17 +38,17 @@ export default {
aria-label="File actions">
<a
:href="activeFile.blamePath"
class="btn btn-default blame">
class="btn btn-default btn-sm blame">
Blame
</a>
<a
:href="activeFile.commitsPath"
class="btn btn-default history">
class="btn btn-default btn-sm history">
History
</a>
<a
:href="activeFile.permalink"
class="btn btn-default permalink">
class="btn btn-default btn-sm permalink">
Permalink
</a>
</div>
......
......@@ -32,10 +32,12 @@ export default {
</script>
<template>
<div class="blob-viewer-container">
<div>
<div
v-if="!activeFile.renderError"
v-html="activeFile.html">
v-html="activeFile.html"
class="multi-file-preview-holder"
>
</div>
<div
v-else-if="activeFile.tempFile"
......
......@@ -44,20 +44,16 @@ export default {
</script>
<template>
<div id="sidebar" :class="{'sidebar-mini' : isCollapsed}">
<div class="ide-file-list">
<table class="table">
<thead>
<tr>
<th
v-if="isCollapsed"
class="repo-file-options title"
>
<strong class="clgray">
{{ projectName }}
</strong>
</th>
<template v-else>
<th class="name multi-file-table-col-name">
<th class="name multi-file-table-name">
Name
</th>
<th class="hidden-sm hidden-xs last-commit">
......@@ -79,7 +75,7 @@ export default {
:key="n"
/>
<repo-file
v-for="(file, index) in treeList"
v-for="file in treeList"
:key="file.key"
:file="file"
/>
......
......@@ -36,27 +36,32 @@ export default {
<template>
<li
:class="{ active : tab.active }"
@click="setFileActive(tab)"
>
<button
type="button"
class="close-btn"
class="multi-file-tab-close"
@click.stop.prevent="closeFile({ file: tab })"
:aria-label="closeLabel">
:aria-label="closeLabel"
:class="{
'modified': tab.changed,
}"
:disabled="tab.changed"
>
<i
class="fa"
:class="changedClass"
aria-hidden="true">
aria-hidden="true"
>
</i>
</button>
<a
href="#"
class="repo-tab"
<div
class="multi-file-tab"
:class="{active : tab.active }"
:title="tab.url"
@click.prevent.stop="setFileActive(tab)">
{{tab.name}}
</a>
>
{{ tab.name }}
</div>
</li>
</template>
......@@ -16,14 +16,12 @@
<template>
<ul
id="tabs"
class="list-unstyled"
class="multi-file-tabs list-unstyled append-bottom-0"
>
<repo-tab
v-for="tab in openFiles"
:key="tab.id"
:tab="tab"
/>
<li class="tabs-divider" />
</ul>
</template>
......@@ -34,3 +34,7 @@ export const canEditFile = (state) => {
openedFiles.length &&
(currentActiveFile && !currentActiveFile.renderError && !currentActiveFile.binary);
};
export const addedFiles = state => changedFiles(state).filter(f => f.tempFile);
export const modifiedFiles = state => changedFiles(state).filter(f => !f.tempFile);
......@@ -35,270 +35,243 @@
}
}
.repository-view {
border: 1px solid $border-color;
border-radius: $border-radius-default;
color: $almost-black;
.multi-file {
display: flex;
height: calc(100vh - 145px);
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
&.is-collapsed {
.ide-file-list {
max-width: 250px;
}
}
}
.code.white pre .hll {
background-color: $well-light-border !important;
.ide-file-list {
flex: 1;
overflow: scroll;
.file {
cursor: pointer;
}
.tree-content-holder {
display: -webkit-flex;
display: flex;
min-height: 300px;
a {
color: $gl-text-color;
}
.tree-content-holder-mini {
height: 100vh;
th {
position: sticky;
top: 0;
}
}
.panel-right {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
width: 80%;
height: 100%;
.multi-file-table-name,
.multi-file-table-col-commit-message {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 0;
}
.monaco-editor.vs {
.current-line {
border: 0;
background: $well-light-border;
}
.multi-file-table-name {
width: 350px;
}
.line-numbers {
cursor: pointer;
.multi-file-table-col-commit-message {
width: 50%;
}
&:hover {
text-decoration: underline;
}
}
}
.multi-file-edit-pane {
display: flex;
flex-direction: column;
flex: 1;
border-left: 1px solid $white-dark;
overflow: hidden;
}
.blob-no-preview {
.vertical-center {
justify-content: center;
width: 100%;
}
}
.multi-file-tabs {
display: flex;
overflow: scroll;
background-color: $white-normal;
box-shadow: inset 0 -1px $white-dark;
&.blob-editor-container {
overflow: hidden;
}
> li {
position: relative;
}
}
.blob-viewer-container {
-webkit-flex: 1;
flex: 1;
overflow: auto;