Commit 07c32a0d authored by Mike Lewis's avatar Mike Lewis

Merge branch 'master' into 'template-improvements-for-documentation'

# Conflicts:
#   .gitlab/merge_request_templates/Documentation.md
parents f1645c74 fe10964a
......@@ -509,6 +509,7 @@ rspec-mysql:
parallel: 50
.rspec-quarantine: &rspec-quarantine
retry: 0
script:
- export CACHE_CLASSES=true
- scripts/gitaly-test-spawn
......
......@@ -26,7 +26,7 @@ https://docs.gitlab.com/ce/development/documentation/index.html#changing-documen
to the new document if there are any Disqus comments on the old document thread.
- [ ] Update the link in `features.yml` (if applicable)
- [ ] If working on CE and the `ee-compat-check` jobs fails, submit an MR to EE
with the changes as well (https://docs.gitlab.com/ce/development/writing_documentation.html#cherry-picking-from-ce-to-ee).
with the changes as well (https://docs.gitlab.com/ce/development/documentation/index.html#cherry-picking-from-ce-to-ee).
- [ ] Ping one of the technical writers for review.
/label ~Documentation
......@@ -16,7 +16,7 @@ Add a description of your merge request here.
## Database checklist
- [ ] Conforms to the [database guides](https://docs.gitlab.com/ee/development/README.html#databases-guides)
- [ ] Conforms to the [database guides](https://docs.gitlab.com/ee/development/README.html#database-guides)
When adding migrations:
......@@ -49,10 +49,10 @@ When removing columns, tables, indexes or other structures:
## General checklist
- [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary
- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/documentation/index.html#contributing-to-docs)
- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/documentation/)
- [ ] [Tests added for this feature/bug](https://docs.gitlab.com/ee/development/testing_guide/index.html)
- [ ] Conforms to the [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
- [ ] Conforms to the [merge request performance guidelines](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html)
- [ ] Conforms to the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides)
- [ ] Conforms to the [style guides](https://docs.gitlab.com/ee/development/contributing/style_guides.html)
/label ~database
{
"extends": "stylelint-config-recommended",
"plugins": [
"stylelint-scss"
],
"rules": {
"no-descending-specificity": null,
"font-family-no-missing-generic-family-keyword": null,
"at-rule-no-unknown": [ true, {
ignoreAtRules: ["include", "each", "mixin", "extend", "if", "function", "for", "else", "return"]
}],
"selector-type-no-unknown": [true, {
"ignoreTypes": ["gl-emoji"]
}],
"unit-no-unknown" : [true, {
"ignoreFunctions": ["-webkit-image-set"]
}],
"scss/at-extend-no-missing-placeholder": null,
"scss/at-function-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/at-import-no-partial-leading-underscore": true,
"scss/at-import-partial-extension-blacklist": ["scss"],
"scss/at-mixin-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/at-rule-no-unknown": true,
"scss/dollar-variable-colon-space-after": "always",
"scss/dollar-variable-colon-space-before": "never",
"scss/dollar-variable-pattern": "^[_]?[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/percent-placeholder-pattern": "^[a-z]+([a-z0-9-]+[a-z0-9]+)?$",
"scss/selector-no-redundant-nesting-selector": true,
}
}
......@@ -11,3 +11,4 @@ danger.import_dangerfile(path: 'danger/commit_messages')
danger.import_dangerfile(path: 'danger/duplicate_yarn_dependencies')
danger.import_dangerfile(path: 'danger/prettier')
danger.import_dangerfile(path: 'danger/eslint')
danger.import_dangerfile(path: 'danger/roulette')
......@@ -143,7 +143,7 @@ gem 'diffy', '~> 3.1.0'
gem 'rack', '2.0.6'
group :unicorn do
gem 'unicorn', '~> 5.1.0'
gem 'unicorn', '~> 5.4.1'
gem 'unicorn-worker-killer', '~> 0.4.4'
end
......@@ -410,7 +410,7 @@ gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support
gem 'net-ssh', '~> 5.0'
gem 'sshkey', '~> 1.9.0'
gem 'sshkey', '~> 2.0'
# Required for ED25519 SSH host key support
group :ed25519 do
......
......@@ -422,7 +422,7 @@ GEM
activerecord
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
kgio (2.10.0)
kgio (2.11.2)
knapsack (1.17.0)
rake
kubeclient (4.2.2)
......@@ -666,7 +666,7 @@ GEM
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
raindrops (0.18.0)
raindrops (0.19.0)
rake (12.3.2)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
......@@ -855,7 +855,7 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
sshkey (1.9.0)
sshkey (2.0.0)
stackprof (0.2.10)
state_machines (0.5.0)
state_machines-activemodel (0.5.1)
......@@ -898,7 +898,7 @@ GEM
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.3.2)
unicorn (5.1.0)
unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-worker-killer (0.4.4)
......@@ -1157,7 +1157,7 @@ DEPENDENCIES
spring (~> 2.0.0)
spring-commands-rspec (~> 1.0.4)
sprockets (~> 3.7.0)
sshkey (~> 1.9.0)
sshkey (~> 2.0)
stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.5.1)
sys-filesystem (~> 1.1.6)
......@@ -1169,7 +1169,7 @@ DEPENDENCIES
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
unf (~> 0.1.4)
unicorn (~> 5.1.0)
unicorn (~> 5.4.1)
unicorn-worker-killer (~> 0.4.4)
validates_hostname (~> 1.0.6)
version_sorter (~> 2.1.0)
......
......@@ -108,7 +108,19 @@ Merge requests that make changes hidden behind a feature flag, or remove an
existing feature flag because a feature is deemed stable, may be merged (and
picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
corresponding exception request to be created.
corresponding exception request to be created.
A level of common sense should be applied when deciding whether to have a feature
behind a feature flag off or on by default.
The following guideliness can be applied to help make this decision:
* If the feature is not fully ready or functioning, the feature flag should be disabled by default.
* If the feature is ready but there are concerns about performance or impact, the feature flag should be enabled by default, but
disabled via chatops before deployment on GitLab.com environments. If the performance concern is confirmed, the final release should have the feature flag disabled by default.
* In most other cases, the feature flag can be enabled by default.
For more information on rolling out changes using feature flags, read [through the documentation](https://docs.gitlab.com/ee/development/rolling_out_changes_using_feature_flags.html).
In order to build the final package and present the feature for self-hosted
customers, the feature flag should be removed. This should happen before the
......
......@@ -36,13 +36,20 @@ export class CopyAsGFM {
div.appendChild(el.cloneNode(true));
const html = div.innerHTML;
clipboardData.setData('text/plain', el.textContent);
clipboardData.setData('text/html', html);
// We are also setting this as fallback to transform the selection to gfm on paste
clipboardData.setData('text/x-gfm-html', html);
CopyAsGFM.nodeToGFM(el)
.then(res => {
clipboardData.setData('text/plain', el.textContent);
clipboardData.setData('text/x-gfm', res);
clipboardData.setData('text/html', html);
})
.catch(() => {});
.catch(() => {
// Not showing the error as Firefox might doesn't allow
// it or other browsers who have a time limit on the execution
// of the copy event
});
}
static pasteGFM(e) {
......@@ -51,11 +58,28 @@ export class CopyAsGFM {
const text = clipboardData.getData('text/plain');
const gfm = clipboardData.getData('text/x-gfm');
if (!gfm) return;
const gfmHtml = clipboardData.getData('text/x-gfm-html');
if (!gfm && !gfmHtml) return;
e.preventDefault();
window.gl.utils.insertText(e.target, textBefore => {
// We have the original selection already converted to gfm
if (gfm) {
CopyAsGFM.insertPastedText(e.target, text, gfm);
} else {
// Due to the async copy call we are not able to produce gfm so we transform the cached HTML
const div = document.createElement('div');
div.innerHTML = gfmHtml;
CopyAsGFM.nodeToGFM(div)
.then(transformedGfm => {
CopyAsGFM.insertPastedText(e.target, text, transformedGfm);
})
.catch(() => {});
}
}
static insertPastedText(target, text, gfm) {
window.gl.utils.insertText(target, textBefore => {
// If the text before the cursor contains an odd number of backticks,
// we are either inside an inline code span that starts with 1 backtick
// or a code block that starts with 3 backticks.
......
......@@ -221,7 +221,7 @@ export default {
</script>
<template>
<div class="board-list-component d-flex flex-column">
<div class="board-list-component">
<div v-if="loading" class="board-list-loading text-center" aria-label="Loading issues">
<gl-loading-icon />
</div>
......
......@@ -4,6 +4,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import createFlash from '~/flash';
import { GlLoadingIcon } from '@gitlab/ui';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
......@@ -11,6 +12,13 @@ import NoChanges from './no_changes.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
import CommitWidget from './commit_widget.vue';
import TreeList from './tree_list.vue';
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
MIN_TREE_WIDTH,
MAX_TREE_WIDTH,
TREE_HIDE_STATS_WIDTH,
} from '../constants';
export default {
name: 'DiffsApp',
......@@ -23,6 +31,7 @@ export default {
CommitWidget,
TreeList,
GlLoadingIcon,
PanelResizer,
},
props: {
endpoint: {
......@@ -54,8 +63,12 @@ export default {
},
},
data() {
const treeWidth =
parseInt(localStorage.getItem(TREE_LIST_WIDTH_STORAGE_KEY), 10) || INITIAL_TREE_WIDTH;
return {
assignedDiscussions: false,
treeWidth,
};
},
computed: {
......@@ -96,6 +109,9 @@ export default {
this.startVersion.version_index === this.mergeRequestDiff.version_index)
);
},
hideFileStats() {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
},
watch: {
diffViewType() {
......@@ -142,6 +158,7 @@ export default {
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
'setHighlightedRow',
'cacheTreeListWidth',
]),
fetchData() {
this.fetchDiffFiles()
......@@ -184,6 +201,8 @@ export default {
}
},
},
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH,
};
</script>
......@@ -209,7 +228,21 @@ export default {
:data-can-create-note="getNoteableData.current_user.can_create_note"
class="files d-flex prepend-top-default"
>
<div v-show="showTreeList" class="diff-tree-list"><tree-list /></div>
<div
v-show="showTreeList"
:style="{ width: `${treeWidth}px` }"
class="diff-tree-list js-diff-tree-list"
>
<panel-resizer
:size.sync="treeWidth"
:start-size="treeWidth"
:min-size="$options.minTreeWidth"
:max-size="$options.maxTreeWidth"
side="right"
@resize-end="cacheTreeListWidth"
/>
<tree-list :hide-file-stats="hideFileStats" />
</div>
<div class="diff-files-holder">
<commit-widget v-if="commit" :commit="commit" />
<template v-if="renderDiffFiles">
......
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import EmptyFileViewer from '~/vue_shared/components/diff_viewer/viewers/empty_file.vue';
import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
import NoteForm from '../../notes/components/note_form.vue';
......@@ -9,6 +10,7 @@ import ImageDiffOverlay from './image_diff_overlay.vue';
import DiffDiscussions from './diff_discussions.vue';
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
import { getDiffMode } from '../store/utils';
import { diffViewerModes } from '~/ide/constants';
export default {
components: {
......@@ -18,7 +20,8 @@ export default {
NoteForm,
DiffDiscussions,
ImageDiffOverlay,
EmptyFileViewer,
NotDiffableViewer,
NoPreviewViewer,
},
props: {
diffFile: {
......@@ -42,11 +45,17 @@ export default {
diffMode() {
return getDiffMode(this.diffFile);
},
diffViewerMode() {
return this.diffFile.viewer.name;
},
isTextFile() {
return this.diffFile.viewer.name === 'text';
return this.diffViewerMode === diffViewerModes.text;
},
noPreview() {
return this.diffViewerMode === diffViewerModes.no_preview;
},
errorMessage() {
return this.diffFile.viewer.error;
notDiffable() {
return this.diffViewerMode === diffViewerModes.not_diffable;
},
diffFileCommentForm() {
return this.getCommentFormForDiffFile(this.diffFile.file_hash);
......@@ -78,11 +87,10 @@ export default {
<template>
<div class="diff-content">
<div v-if="!errorMessage" class="diff-viewer">
<div class="diff-viewer">
<template v-if="isTextFile">
<empty-file-viewer v-if="diffFile.empty" />
<inline-diff-view
v-else-if="isInlineView"
v-if="isInlineView"
:diff-file="diffFile"
:diff-lines="diffFile.highlighted_diff_lines || []"
:help-page-path="helpPagePath"
......@@ -94,9 +102,12 @@ export default {
:help-page-path="helpPagePath"
/>
</template>
<not-diffable-viewer v-else-if="notDiffable" />
<no-preview-viewer v-else-if="noPreview" />
<diff-viewer
v-else
:diff-mode="diffMode"
:diff-viewer-mode="diffViewerMode"
:new-path="diffFile.new_path"
:new-sha="diffFile.diff_refs.head_sha"
:old-path="diffFile.old_path"
......@@ -132,8 +143,5 @@ export default {
</div>
</diff-viewer>
</div>
<div v-else class="diff-viewer">
<div class="nothing-here-block" v-html="errorMessage"></div>
</div>
</div>
</template>
......@@ -7,6 +7,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
export default {
components: {
......@@ -33,15 +34,13 @@ export default {
return {
isLoadingCollapsedDiff: false,
forkMessageVisible: false,
isCollapsed: this.file.viewer.collapsed || false,
};
},
computed: {
...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']),
isCollapsed() {
return this.file.collapsed || false;
},
viewBlobLink() {
return sprintf(
__('You can %{linkStart}view the blob%{linkEnd} instead.'),
......@@ -52,17 +51,6 @@ export default {
false,
);
},
showExpandMessage() {
return (
this.isCollapsed ||
(!this.file.highlighted_diff_lines &&
!this.isLoadingCollapsedDiff &&
!this.file.too_large &&
this.file.text &&
!this.file.renamed_file &&
!this.file.mode_changed)
);
},
showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
},
......@@ -73,9 +61,15 @@ export default {
this.file.parallel_diff_lines.length > 0
);
},
isFileTooLarge() {
return this.file.viewer.error === diffViewerErrors.too_large;
},
errorMessage() {
return this.file.viewer.error_message;
},
},
watch: {
'file.collapsed': function fileCollapsedWatch(newVal, oldVal) {
isCollapsed: function fileCollapsedWatch(newVal, oldVal) {