BigW Consortium Gitlab

Improve web IDE commit input

Improves the web IDE commit message imput by highlighting any characters on the first line after 50 & every other line after 72 Closes #44832
parent 25cb70ba
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
commitToCurrentBranchText() { commitToCurrentBranchText() {
return sprintf( return sprintf(
__('Commit to %{branchName} branch'), __('Commit to %{branchName} branch'),
{ branchName: `<strong>${this.currentBranchId}</strong>` }, { branchName: `<strong class="monospace">${this.currentBranchId}</strong>` },
false, false,
); );
}, },
......
<script>
import { __ } from '../../../locale';
import popover from '../../../vue_shared/directives/popover';
export const MAX_TITLE_LENGTH = 50;
export const MAX_BODY_LENGTH = 72;
export default {
directives: {
popover,
},
props: {
text: {
type: String,
required: true,
},
},
data() {
return {
scrollTop: 0,
isFocused: false,
};
},
computed: {
allLines() {
return this.text.replace(/\n$/g, '\n\n').split('\n');
},
},
methods: {
handleScroll() {
this.$nextTick(() => {
this.scrollTop = this.$refs.textarea.scrollTop;
});
},
getLineLength(i) {
return i === 0 ? MAX_TITLE_LENGTH : MAX_BODY_LENGTH;
},
onInput(e) {
this.$emit('input', e.target.value);
},
},
popoverOptions: {
html: true,
trigger: 'hover',
placement: 'top',
content: __(`
The character highligher helps you keep the subject line to 50 characters
and wrap the body at 72 so they are readable in git.
`),
},
};
</script>
<template>
<fieldset class="common-note-form ide-commit-message-field">
<div
class="md-area"
:class="{
'is-focused': isFocused
}"
>
<div
v-once
class="md-header"
>
<ul class="nav-links">
<li>
{{ __('Commit Message') }}
<span
v-popover="$options.popoverOptions"
class="help-block prepend-left-10"
>
<i
aria-hidden="true"
class="fa fa-question-circle"
></i>
</span>
</li>
</ul>
</div>
<div class="ide-commit-message-textarea-container">
<div class="ide-commit-message-highlights-container">
<div
class="note-textarea highlights monospace"
:style="{
transform: `translate3d(0, ${-scrollTop}px, 0)`
}"
>
<div
v-for="(line, index) in allLines"
:key="index"
>
<span
v-text="line.substr(0, getLineLength(index)) || ' '"
>
</span><mark
v-if="line.length > getLineLength(index)"
v-text="line.substr(getLineLength(index))"
>
</mark>
</div>
</div>
</div>
<textarea
class="note-textarea ide-commit-message-textarea"
:placeholder="__('Write a commit message...')"
:value="text"
@scroll="handleScroll"
@input="onInput"
@focus="isFocused = true"
@blur="isFocused = false"
ref="textarea"
>
</textarea>
</div>
</div>
</fieldset>
</template>
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
> >
<input <input
type="text" type="text"
class="form-control" class="form-control monospace"
:placeholder="newBranchName" :placeholder="newBranchName"
@input="updateBranchName($event.target.value)" @input="updateBranchName($event.target.value)"
/> />
......
...@@ -5,6 +5,7 @@ import icon from '~/vue_shared/components/icon.vue'; ...@@ -5,6 +5,7 @@ import icon from '~/vue_shared/components/icon.vue';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue'; import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue';
import commitFilesList from './commit_sidebar/list.vue'; import commitFilesList from './commit_sidebar/list.vue';
import CommitMessageField from './commit_sidebar/message_field.vue';
import * as consts from '../stores/modules/commit/constants'; import * as consts from '../stores/modules/commit/constants';
import Actions from './commit_sidebar/actions.vue'; import Actions from './commit_sidebar/actions.vue';
...@@ -15,6 +16,7 @@ export default { ...@@ -15,6 +16,7 @@ export default {
commitFilesList, commitFilesList,
Actions, Actions,
LoadingButton, LoadingButton,
CommitMessageField,
}, },
directives: { directives: {
tooltip, tooltip,
...@@ -38,15 +40,9 @@ export default { ...@@ -38,15 +40,9 @@ export default {
'changedFiles', 'changedFiles',
]), ]),
...mapState('commit', ['commitMessage', 'submitCommitLoading']), ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
...mapGetters('commit', [ ...mapGetters('commit', ['commitButtonDisabled', 'discardDraftButtonDisabled', 'branchName']),
'commitButtonDisabled',
'discardDraftButtonDisabled',
'branchName',
]),
statusSvg() { statusSvg() {
return this.lastCommitMsg return this.lastCommitMsg ? this.committedStateSvgPath : this.noChangesStateSvgPath;
? this.committedStateSvgPath
: this.noChangesStateSvgPath;
}, },
}, },
methods: { methods: {
...@@ -64,9 +60,7 @@ export default { ...@@ -64,9 +60,7 @@ export default {
}); });
}, },
forceCreateNewBranch() { forceCreateNewBranch() {
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commitChanges());
this.commitChanges(),
);
}, },
}, },
}; };
...@@ -105,16 +99,10 @@ export default { ...@@ -105,16 +99,10 @@ export default {
@submit.prevent.stop="commitChanges" @submit.prevent.stop="commitChanges"
v-if="!rightPanelCollapsed" v-if="!rightPanelCollapsed"
> >
<div class="multi-file-commit-fieldset"> <commit-message-field
<textarea :text="commitMessage"
class="form-control multi-file-commit-message" @input="updateCommitMessage"
name="commit-message" />
:value="commitMessage"
:placeholder="__('Write a commit message...')"
@input="updateCommitMessage($event.target.value)"
>
</textarea>
</div>
<div class="clearfix prepend-top-15"> <div class="clearfix prepend-top-15">
<actions /> <actions />
<loading-button <loading-button
......
...@@ -5,45 +5,71 @@ import * as types from '../mutation_types'; ...@@ -5,45 +5,71 @@ import * as types from '../mutation_types';
export const getProjectData = ( export const getProjectData = (
{ commit, state, dispatch }, { commit, state, dispatch },
{ namespace, projectId, force = false } = {}, { namespace, projectId, force = false } = {},
) => new Promise((resolve, reject) => { ) =>
new Promise((resolve, reject) => {
if (!state.projects[`${namespace}/${projectId}`] || force) { if (!state.projects[`${namespace}/${projectId}`] || force) {
commit(types.TOGGLE_LOADING, { entry: state }); commit(types.TOGGLE_LOADING, { entry: state });
service.getProjectData(namespace, projectId) service
.getProjectData(namespace, projectId)
.then(res => res.data) .then(res => res.data)
.then((data) => { .then(data => {
commit(types.TOGGLE_LOADING, { entry: state }); commit(types.TOGGLE_LOADING, { entry: state });
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data }); commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`); if (!state.currentProjectId)
commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
resolve(data); resolve(data);
}) })
.catch(() => { .catch(() => {
flash('Error loading project data. Please try again.', 'alert', document, null, false, true); flash(
'Error loading project data. Please try again.',
'alert',
document,
null,
false,
true,
);
reject(new Error(`Project not loaded ${namespace}/${projectId}`)); reject(new Error(`Project not loaded ${namespace}/${projectId}`));
}); });
} else { } else {
resolve(state.projects[`${namespace}/${projectId}`]); resolve(state.projects[`${namespace}/${projectId}`]);
} }
}); });
export const getBranchData = ( export const getBranchData = (
{ commit, state, dispatch }, { commit, state, dispatch },
{ projectId, branchId, force = false } = {}, { projectId, branchId, force = false } = {},
) => new Promise((resolve, reject) => { ) =>
if ((typeof state.projects[`${projectId}`] === 'undefined' || new Promise((resolve, reject) => {
!state.projects[`${projectId}`].branches[branchId]) if (
|| force) { typeof state.projects[`${projectId}`] === 'undefined' ||
service.getBranchData(`${projectId}`, branchId) !state.projects[`${projectId}`].branches[branchId] ||
force
) {
service
.getBranchData(`${projectId}`, branchId)
.then(({ data }) => { .then(({ data }) => {
const { id } = data.commit; const { id } = data.commit;
commit(types.SET_BRANCH, { projectPath: `${projectId}`, branchName: branchId, branch: data }); commit(types.SET_BRANCH, {
projectPath: `${projectId}`,
branchName: branchId,
branch: data,
});
commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id }); commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
commit(types.SET_CURRENT_BRANCH, branchId);
resolve(data); resolve(data);
}) })
.catch(() => { .catch(() => {
flash('Error loading branch data. Please try again.', 'alert', document, null, false, true); flash(
'Error loading branch data. Please try again.',
'alert',
document,
null,
false,
true,
);
reject(new Error(`Branch not loaded - ${projectId}/${branchId}`)); reject(new Error(`Branch not loaded - ${projectId}/${branchId}`));
}); });
} else { } else {
resolve(state.projects[`${projectId}`].branches[branchId]); resolve(state.projects[`${projectId}`].branches[branchId]);
} }
}); });
...@@ -662,11 +662,6 @@ ...@@ -662,11 +662,6 @@
} }
} }
.multi-file-commit-message.form-control {
height: 160px;
resize: none;
}
.dirty-diff { .dirty-diff {
// !important need to override monaco inline style // !important need to override monaco inline style
width: 4px !important; width: 4px !important;
...@@ -839,3 +834,74 @@ ...@@ -839,3 +834,74 @@
align-items: center; align-items: center;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
} }
.ide-commit-message-field {
height: 200px;
background-color: $white-light;
.md-area {
display: flex;
flex-direction: column;
height: 100%;
}
.nav-links {
height: 30px;
}
.help-block {
margin-top: 0;
color: $blue-500;
cursor: pointer;
}
}
.ide-commit-message-textarea-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
.note-textarea {
font-family: $monospace_font;
}
}
.ide-commit-message-highlights-container {
position: absolute;
left: 0;
top: 0;
right: -100px;
bottom: 0;
padding-right: 100px;
pointer-events: none;
z-index: 1;
.highlights {
white-space: pre-wrap;
word-wrap: break-word;
color: transparent;
}
mark {
margin-left: -1px;
padding: 0 2px;
border-radius: $border-radius-small;
background-color: $orange-200;
color: transparent;
opacity: 0.6;
}
}
.ide-commit-message-textarea {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 2;
background: transparent;
resize: none;
}
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