Commit 03495dd0 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'master' into build-chunks-on-object-storage

parents d7a3180d fb08183e
...@@ -14,3 +14,12 @@ lib/gitlab/gitaly_client/ref_service.rb ...@@ -14,3 +14,12 @@ lib/gitlab/gitaly_client/ref_service.rb
lib/gitlab/gitaly_client/commit_service.rb lib/gitlab/gitaly_client/commit_service.rb
lib/gitlab/git/commit.rb lib/gitlab/git/commit.rb
lib/gitlab/git/tag.rb lib/gitlab/git/tag.rb
ee/db/**/*
ee/app/serializers/ee/merge_request_widget_entity.rb
ee/lib/api/epics.rb
ee/lib/api/geo_nodes.rb
ee/lib/ee/gitlab/ldap/sync/admin_users.rb
ee/app/workers/geo/file_download_dispatch_worker/job_artifact_job_finder.rb
ee/app/workers/geo/file_download_dispatch_worker/lfs_object_job_finder.rb
ee/spec/**/*
...@@ -264,10 +264,10 @@ package-and-qa: ...@@ -264,10 +264,10 @@ package-and-qa:
<<: *single-script-job <<: *single-script-job
variables: variables:
<<: *single-script-job-variables <<: *single-script-job-variables
SCRIPT_NAME: trigger-build-omnibus SCRIPT_NAME: trigger-build
retry: 0 retry: 0
script: script:
- ./$SCRIPT_NAME - ./$SCRIPT_NAME omnibus
when: manual when: manual
only: only:
- //@gitlab-org/gitlab-ce - //@gitlab-org/gitlab-ce
...@@ -415,6 +415,7 @@ setup-test-env: ...@@ -415,6 +415,7 @@ setup-test-env:
script: script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init' - bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here - scripts/gitaly-test-build # Do not use 'bundle exec' here
- BUNDLE_GEMFILE=Gemfile.rails5 bundle install $BUNDLE_INSTALL_FLAGS
artifacts: artifacts:
expire_in: 7d expire_in: 7d
paths: paths:
...@@ -590,6 +591,12 @@ downtime_check: ...@@ -590,6 +591,12 @@ downtime_check:
- /(^docs[\/-].*|.*-docs$)/ - /(^docs[\/-].*|.*-docs$)/
- /(^qa[\/-].*|.*-qa$)/ - /(^qa[\/-].*|.*-qa$)/
rails5_gemfile_lock_check:
<<: *dedicated-no-docs-no-db-pull-cache-job
<<: *except-docs-and-qa
script:
- scripts/rails5-gemfile-lock-check
ee_compat_check: ee_compat_check:
<<: *rake-exec <<: *rake-exec
except: except:
......
...@@ -487,7 +487,7 @@ Style/EmptyLiteral: ...@@ -487,7 +487,7 @@ Style/EmptyLiteral:
- 'lib/gitlab/fogbugz_import/importer.rb' - 'lib/gitlab/fogbugz_import/importer.rb'
- 'lib/gitlab/git/diff_collection.rb' - 'lib/gitlab/git/diff_collection.rb'
- 'lib/gitlab/gitaly_client.rb' - 'lib/gitlab/gitaly_client.rb'
- 'scripts/trigger-build-omnibus' - 'scripts/trigger-build'
- 'spec/features/merge_requests/versions_spec.rb' - 'spec/features/merge_requests/versions_spec.rb'
- 'spec/helpers/merge_requests_helper_spec.rb' - 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/gitlab/request_context_spec.rb' - 'spec/lib/gitlab/request_context_spec.rb'
......
...@@ -301,9 +301,9 @@ For guidance on UX implementation at GitLab, please refer to our [Design System] ...@@ -301,9 +301,9 @@ For guidance on UX implementation at GitLab, please refer to our [Design System]
The UX team uses labels to manage their workflow. The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention. The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/ux/) of the handbook. To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
Once an issue has been worked on and is ready for development, a UXer applies the ~"UX ready" label to that issue. Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
The UX team has a special type label called ~"design artifact". This label indicates that the final output The UX team has a special type label called ~"design artifact". This label indicates that the final output
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone. for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
......
...@@ -296,7 +296,7 @@ GEM ...@@ -296,7 +296,7 @@ GEM
flowdock (~> 0.7) flowdock (~> 0.7)
gitlab-grit (>= 2.4.1) gitlab-grit (>= 2.4.1)
multi_json multi_json
gitlab-gollum-lib (4.2.7.2) gitlab-gollum-lib (4.2.7.4)
gemojione (~> 3.2) gemojione (~> 3.2)
github-markup (~> 1.6) github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0) gollum-grit_adapter (~> 1.0)
...@@ -304,7 +304,7 @@ GEM ...@@ -304,7 +304,7 @@ GEM
rouge (~> 3.1) rouge (~> 3.1)
sanitize (~> 2.1) sanitize (~> 2.1)
stringex (~> 2.6) stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4) gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15) mime-types (>= 1.15)
rugged (~> 0.25) rugged (~> 0.25)
gitlab-grit (2.8.2) gitlab-grit (2.8.2)
......
...@@ -315,7 +315,7 @@ GEM ...@@ -315,7 +315,7 @@ GEM
diff-lcs (~> 1.1) diff-lcs (~> 1.1)
mime-types (>= 1.16) mime-types (>= 1.16)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab-markup (1.6.3) gitlab-markup (1.6.4)
gitlab-styles (2.3.2) gitlab-styles (2.3.2)
rubocop (~> 0.51) rubocop (~> 0.51)
rubocop-gitlab-security (~> 0.1.0) rubocop-gitlab-security (~> 0.1.0)
...@@ -751,36 +751,36 @@ GEM ...@@ -751,36 +751,36 @@ GEM
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
rqrcode (>= 0.4.2) rqrcode (>= 0.4.2)
rspec (3.6.0) rspec (3.7.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.7.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.6.0) rspec-mocks (~> 3.7.0)
rspec-core (3.6.0) rspec-core (3.7.1)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-expectations (3.6.0) rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-mocks (3.6.0) rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-parameterized (0.4.0) rspec-parameterized (0.4.0)
binding_of_caller binding_of_caller
parser parser
proc_to_ast proc_to_ast
rspec (>= 2.13, < 4) rspec (>= 2.13, < 4)
unparser unparser
rspec-rails (3.6.0) rspec-rails (3.7.2)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec-core (~> 3.6.0) rspec-core (~> 3.7.0)
rspec-expectations (~> 3.6.0) rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.6.0) rspec-mocks (~> 3.7.0)
rspec-support (~> 3.6.0) rspec-support (~> 3.7.0)
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-set (0.1.3) rspec-set (0.1.3)
rspec-support (3.6.0) rspec-support (3.7.1)
rspec_profiling (0.0.5) rspec_profiling (0.0.5)
activerecord activerecord
pg pg
...@@ -1054,7 +1054,7 @@ DEPENDENCIES ...@@ -1054,7 +1054,7 @@ DEPENDENCIES
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2) gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4) gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.2) gitlab-markup (~> 1.6.4)
gitlab-styles (~> 2.3) gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4) gitlab_omniauth-ldap (~> 2.0.4)
gon (~> 6.2) gon (~> 6.2)
...@@ -1152,7 +1152,7 @@ DEPENDENCIES ...@@ -1152,7 +1152,7 @@ DEPENDENCIES
rouge (~> 3.1) rouge (~> 3.1)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-parameterized rspec-parameterized
rspec-rails (~> 3.6.0) rspec-rails (~> 3.7.0)
rspec-retry (~> 0.4.5) rspec-retry (~> 0.4.5)
rspec-set (~> 0.1.3) rspec-set (~> 0.1.3)
rspec_profiling (~> 0.0.5) rspec_profiling (~> 0.0.5)
......
...@@ -169,6 +169,7 @@ the stable branch are: ...@@ -169,6 +169,7 @@ the stable branch are:
* Fixes for [regressions](#regressions) * Fixes for [regressions](#regressions)
* Fixes for security issues * Fixes for security issues
* Fixes or improvements to automated QA scenarios * Fixes or improvements to automated QA scenarios
* Documentation updates for changes in the same release
* New or updated translations (as long as they do not touch application code) * New or updated translations (as long as they do not touch application code)
During the feature freeze all merge requests that are meant to go into the During the feature freeze all merge requests that are meant to go into the
...@@ -185,11 +186,7 @@ next patch release. ...@@ -185,11 +186,7 @@ next patch release.
If a merge request is to be picked into more than one release it will need one If a merge request is to be picked into more than one release it will need one
`Pick into X.Y` label per release where the merge request should be back-ported `Pick into X.Y` label per release where the merge request should be back-ported
to. to. For example:
For example, if the current patch release is `10.1.1` and a regression fix needs
to be backported down to the `9.5` release, you will need to assign it the
`10.1` milestone and the following labels:
- `Pick into 10.1` - `Pick into 10.1`
- `Pick into 10.0` - `Pick into 10.0`
......
...@@ -72,11 +72,11 @@ export default { ...@@ -72,11 +72,11 @@ export default {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<img <img
class="project-badge"
:src="imageUrlWithRetries" :src="imageUrlWithRetries"
class="project-badge"
aria-hidden="true"
@load="onLoad" @load="onLoad"
@error="onError" @error="onError"
aria-hidden="true"
/> />
</a> </a>
...@@ -91,9 +91,9 @@ export default { ...@@ -91,9 +91,9 @@ export default {
> >
<div class="btn btn-default btn-sm disabled"> <div class="btn btn-default btn-sm disabled">
<icon <icon
:size="16"
class="prepend-left-8 append-right-8" class="prepend-left-8 append-right-8"
name="doc_image" name="doc_image"
:size="16"
aria-hidden="true" aria-hidden="true"
/> />
</div> </div>
...@@ -105,16 +105,16 @@ export default { ...@@ -105,16 +105,16 @@ export default {
</div> </div>
<button <button
v-tooltip
v-show="hasError" v-show="hasError"
:title="s__('Badges|Reload badge image')"
class="btn btn-transparent btn-sm text-primary" class="btn btn-transparent btn-sm text-primary"
type="button" type="button"
v-tooltip
:title="s__('Badges|Reload badge image')"
@click="reloadImage" @click="reloadImage"
> >
<icon <icon
name="retry"
:size="16" :size="16"
name="retry"
/> />
</button> </button>
</div> </div>
......
...@@ -153,10 +153,10 @@ export default { ...@@ -153,10 +153,10 @@ export default {
<label for="badge-link-url">{{ s__('Badges|Link') }}</label> <label for="badge-link-url">{{ s__('Badges|Link') }}</label>
<input <input
id="badge-link-url" id="badge-link-url"
type="text"
class="form-control"
v-model="linkUrl" v-model="linkUrl"
:placeholder="$options.badgeLinkUrlPlaceholder" :placeholder="$options.badgeLinkUrlPlaceholder"
type="text"
class="form-control"
@input="debouncedPreview" @input="debouncedPreview"
/> />
<span <span
...@@ -169,10 +169,10 @@ export default { ...@@ -169,10 +169,10 @@ export default {
<label for="badge-image-url">{{ s__('Badges|Badge image URL') }}</label> <label for="badge-image-url">{{ s__('Badges|Badge image URL') }}</label>
<input <input
id="badge-image-url" id="badge-image-url"
type="text"
class="form-control"
v-model="imageUrl" v-model="imageUrl"
:placeholder="$options.badgeImageUrlPlaceholder" :placeholder="$options.badgeImageUrlPlaceholder"
type="text"
class="form-control"
@input="debouncedPreview" @input="debouncedPreview"
/> />
<span <span
...@@ -184,8 +184,8 @@ export default { ...@@ -184,8 +184,8 @@ export default {
<div class="form-group"> <div class="form-group">
<label for="badge-preview">{{ s__('Badges|Badge image preview') }}</label> <label for="badge-preview">{{ s__('Badges|Badge image preview') }}</label>
<badge <badge
id="badge-preview"
v-show="renderedBadge && !isRendering" v-show="renderedBadge && !isRendering"
id="badge-preview"
:image-url="renderedImageUrl" :image-url="renderedImageUrl"
:link-url="renderedLinkUrl" :link-url="renderedLinkUrl"
/> />
...@@ -202,16 +202,16 @@ export default { ...@@ -202,16 +202,16 @@ export default {
<div class="row-content-block"> <div class="row-content-block">
<loading-button <loading-button
type="submit"
container-class="btn btn-success"
:disabled="!canSubmit" :disabled="!canSubmit"
:loading="isSaving" :loading="isSaving"
:label="submitButtonLabel" :label="submitButtonLabel"
type="submit"
container-class="btn btn-success"
/> />
<button <button
v-if="isEditing"
class="btn btn-cancel" class="btn btn-cancel"
type="button" type="button"
v-if="isEditing"
@click="onCancel" @click="onCancel"
>{{ __('Cancel') }}</button> >{{ __('Cancel') }}</button>
</div> </div>
......
...@@ -41,9 +41,9 @@ export default { ...@@ -41,9 +41,9 @@ export default {
<template> <template>
<div class="gl-responsive-table-row-layout gl-responsive-table-row"> <div class="gl-responsive-table-row-layout gl-responsive-table-row">
<badge <badge
class="table-section section-30"
:image-url="badge.renderedImageUrl" :image-url="badge.renderedImageUrl"
:link-url="badge.renderedLinkUrl" :link-url="badge.renderedLinkUrl"
class="table-section section-30"
/> />
<span class="table-section section-50 str-truncated">{{ badge.linkUrl }}</span> <span class="table-section section-50 str-truncated">{{ badge.linkUrl }}</span>
<div class="table-section section-10"> <div class="table-section section-10">
...@@ -54,29 +54,29 @@ export default { ...@@ -54,29 +54,29 @@ export default {
v-if="canEditBadge" v-if="canEditBadge"
class="table-action-buttons"> class="table-action-buttons">
<button <button
:disabled="badge.isDeleting"
class="btn btn-default append-right-8" class="btn btn-default append-right-8"
type="button" type="button"
:disabled="badge.isDeleting"
@click="editBadge(badge)" @click="editBadge(badge)"
> >
<icon <icon
name="pencil"
:size="16" :size="16"
:aria-label="__('Edit')" :aria-label="__('Edit')"
name="pencil"
/> />
</button> </button>
<button <button
:disabled="badge.isDeleting"
class="btn btn-danger" class="btn btn-danger"
type="button" type="button"
data-toggle="modal" data-toggle="modal"
data-target="#delete-badge-modal" data-target="#delete-badge-modal"
:disabled="badge.isDeleting"
@click="updateBadgeInModal(badge)" @click="updateBadgeInModal(badge)"
> >
<icon <icon
name="remove"
:size="16" :size="16"
:aria-label="__('Delete')" :aria-label="__('Delete')"
name="remove"
/> />
</button> </button>
<loading-icon <loading-icon
......
...@@ -44,8 +44,8 @@ export default { ...@@ -44,8 +44,8 @@ export default {
<gl-modal <gl-modal
id="delete-badge-modal" id="delete-badge-modal"
:header-title-text="s__('Badges|Delete badge?')" :header-title-text="s__('Badges|Delete badge?')"
footer-primary-button-variant="danger"
:footer-primary-button-text="s__('Badges|Delete badge')" :footer-primary-button-text="s__('Badges|Delete badge')"
footer-primary-button-variant="danger"
@submit="onSubmitModal"> @submit="onSubmitModal">
<div class="well"> <div class="well">
<badge <badge
......
...@@ -119,7 +119,7 @@ const gfmRules = { ...@@ -119,7 +119,7 @@ const gfmRules = {
return el.outerHTML; return el.outerHTML;
}, },
'dl'(el, text) { 'dl'(el, text) {
let lines = text.trim().split('\n'); let lines = text.replace(/\n\n/g, '\n').trim().split('\n');
// Add two spaces to the front of subsequent list items lines, // Add two spaces to the front of subsequent list items lines,
// or leave the line entirely blank. // or leave the line entirely blank.
lines = lines.map((l) => { lines = lines.map((l) => {
...@@ -129,9 +129,13 @@ const gfmRules = { ...@@ -129,9 +129,13 @@ const gfmRules = {
return ` ${line}`; return ` ${line}`;
}); });
return `<dl>\n${lines.join('\n')}\n</dl>`; return `<dl>\n${lines.join('\n')}\n</dl>\n`;
}, },
'sub, dt, dd, kbd, q, samp, var, ruby, rt, rp, abbr, summary, details'(el, text) { 'dt, dd, summary, details'(el, text) {
const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>\n`;
},
'sup, sub, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) {
const tag = el.nodeName.toLowerCase(); const tag = el.nodeName.toLowerCase();
return `<${tag}>${text}</${tag}>`; return `<${tag}>${text}</${tag}>`;
}, },
...@@ -215,22 +219,22 @@ const gfmRules = { ...@@ -215,22 +219,22 @@ const gfmRules = {
return text.replace(/^- /mg, '1. '); return text.replace(/^- /mg, '1. ');
}, },
'h1'(el, text) { 'h1'(el, text) {
return `# ${text.trim()}`; return `# ${text.trim()}\n`;
}, },
'h2'(el, text) { 'h2'(el, text) {
return `## ${text.trim()}`; return `## ${text.trim()}\n`;
}, },
'h3'(el, text) { 'h3'(el, text) {
return `### ${text.trim()}`; return `### ${text.trim()}\n`;
}, },
'h4'(el, text) { 'h4'(el, text) {
return `#### ${text.trim()}`; return `#### ${text.trim()}\n`;
}, },
'h5'(el, text) { 'h5'(el, text) {
return `##### ${text.trim()}`; return `##### ${text.trim()}\n`;
}, },
'h6'(el, text) { 'h6'(el, text) {
return `###### ${text.trim()}`; return `###### ${text.trim()}\n`;
}, },
'strong'(el, text) { 'strong'(el, text) {
return `**${text}**`; return `**${text}**`;
...@@ -241,11 +245,13 @@ const gfmRules = { ...@@ -241,11 +245,13 @@ const gfmRules = {
'del'(el, text) { 'del'(el, text) {
return `~~${text}~~`; return `~~${text}~~`;
}, },
'sup'(el, text) {
return `^${text}`;
},
'hr'(el) { 'hr'(el) {
return '-----'; // extra leading \n is to ensure that there is a blank line between
// a list followed by an hr, otherwise this breaks old redcarpet rendering
return '\n-----\n';
},
'p'(el, text) {
return `${text.trim()}\n`;
}, },
'table'(el) { 'table'(el) {
const theadEl = el.querySelector('thead'); const theadEl = el.querySelector('thead');
...@@ -263,7 +269,9 @@ const gfmRules = { ...@@ -263,7 +269,9 @@ const gfmRules = {
let before = ''; let before = '';
let after = ''; let after = '';
switch (cell.style.textAlign) { const alignment = cell.align || cell.style.textAlign;
switch (alignment) {
case 'center': case 'center':
before = ':'; before = ':';
after = ':'; after = ':';
......
...@@ -14,17 +14,28 @@ window.gl = window.gl || {}; ...@@ -14,17 +14,28 @@ window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.Board = Vue.extend({ gl.issueBoards.Board = Vue.extend({
template: '#js-board-template',
components: { components: {
boardList, boardList,
'board-delete': gl.issueBoards.BoardDelete, 'board-delete': gl.issueBoards.BoardDelete,
BoardBlankState, BoardBlankState,
}, },
props: { props: {
list: Object, list: {
disabled: Boolean, type: Object,
issueLinkBase: String, default: () => ({}),
rootPath: String, },
disabled: {
type: Boolean,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
rootPath: {
type: String,
required: true,
},
boardId: { boardId: {
type: String, type: String,
required: true, required: true,
...@@ -82,20 +93,6 @@ gl.issueBoards.Board = Vue.extend({ ...@@ -82,20 +93,6 @@ gl.issueBoards.Board = Vue.extend({
deep: true deep: true
} }
}, },
methods: {
showNewIssueForm() {
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
},
toggleExpanded(e) {
if (this.list.isExpandable && !e.target.classList.contains('js-no-trigger-collapse')) {
this.list.isExpanded = !this.list.isExpanded;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
}
}
},
},
mounted () { mounted () {
this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({ this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
disabled: this.disabled, disabled: this.disabled,
...@@ -125,4 +122,19 @@ gl.issueBoards.Board = Vue.extend({ ...@@ -125,4 +122,19 @@ gl.issueBoards.Board = Vue.extend({
this.list.isExpanded = !isCollapsed; this.list.isExpanded = !isCollapsed;
} }
}, },
methods: {
showNewIssueForm() {
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
},
toggleExpanded(e) {
if (this.list.isExpandable && !e.target.classList.contains('js-no-trigger-collapse')) {
this.list.isExpanded = !this.list.isExpanded;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
}
}
},
},
template: '#js-board-template',
}); });
...@@ -72,8 +72,8 @@ export default { ...@@ -72,8 +72,8 @@ export default {
:key="index" :key="index"
> >
<span <span
class="label-color" :style="{ backgroundColor: label.color }"
:style="{ backgroundColor: label.color }"> class="label-color">
</span> </span>
{{ label.title }} {{ label.title }}
</li> </li>
......
...@@ -77,7 +77,6 @@ export default { ...@@ -77,7 +77,6 @@ export default {
<template> <template>
<li <li
class="board-card"
:class="{ :class="{
'user-can-drag': !disabled && issue.id, 'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id, 'is-disabled': disabled || !issue.id,
...@@ -85,6 +84,7 @@ export default { ...@@ -85,6 +84,7 @@ export default {
}" }"
:index="index" :index="index"
:data-issue-id="issue.id" :data-issue-id="issue.id"
class="board-card"
@mousedown="mouseDown" @mousedown="mouseDown"
@mousemove="mouseMove" @mousemove="mouseMove"
@mouseup="showIssue($event)"> @mouseup="showIssue($event)">
......
...@@ -8,7 +8,10 @@ window.gl.issueBoards = window.gl.issueBoards || {}; ...@@ -8,7 +8,10 @@ window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardDelete = Vue.extend({ gl.issueBoards.BoardDelete = Vue.extend({
props: { props: {
list: Object list: {
type: Object,
default: () => ({}),
},
}, },
methods: { methods: {
deleteBoard () { deleteBoard () {
......
...@@ -205,22 +205,22 @@ export default { ...@@ -205,22 +205,22 @@ export default {
<template> <template>
<div class="board-list-component"> <div class="board-list-component">
<div <div
v-if="loading"
class="board-list-loading text-center" class="board-list-loading text-center"
aria-label="Loading issues" aria-label="Loading issues">
v-if="loading">
<loading-icon /> <loading-icon />
</div> </div>
<board-new-issue <board-new-issue
v-if="list.type !== 'closed' && showIssueForm"
:group-id="groupId" :group-id="groupId"
:list="list" :list="list"/>
v-if="list.type !== 'closed' && showIssueForm"/>
<ul <ul
class="board-list js-board-list"
v-show="!loading" v-show="!loading"
ref="list" ref="list"
:data-board="list.id" :data-board="list.id"
:data-board-type="list.type" :data-board-type="list.type"
:class="{ 'is-smaller': showIssueForm }"> :class="{ 'is-smaller': showIssueForm }"
class="board-list js-board-list">
<board-card <board-card
v-for="(issue, index) in issues" v-for="(issue, index) in issues"
ref="issue" ref="issue"
...@@ -233,8 +233,8 @@ export default { ...@@ -233,8 +233,8 @@ export default {
:disabled="disabled" :disabled="disabled"
:key="issue.id" /> :key="issue.id" />
<li <li
class="board-list-count text-center"
v-if="showCount" v-if="showCount"
class="board-list-count text-center"
data-issue-id="-1"> data-issue-id="-1">
<loading-icon <loading-icon
v-show="list.loadingMore" v-show="list.loadingMore"
......
...@@ -96,26 +96,26 @@ export default { ...@@ -96,26 +96,26 @@ export default {
<div class="board-card"> <div class="board-card">
<form @submit="submit($event)"> <form @submit="submit($event)">
<div <div
class="flash-container"
v-if="error" v-if="error"
class="flash-container"
> >
<div class="flash-alert"> <div class="flash-alert">
An error occurred. Please try again. An error occurred. Please try again.
</div> </div>
</div> </div>
<label <label
class="label-light"
:for="list.id + '-title'" :for="list.id + '-title'"
class="label-light"
> >
Title Title
</label> </label>
<input <input
ref="input"
v-model="title"
:id="list.id + '-title'"
class="form-control" class="form-control"
type="text" type="text"
v-model="title"
ref="input"
autocomplete="off" autocomplete="off"
:id="list.id + '-title'"
/> />
<project-select <project-select
v-if="groupId" v-if="groupId"
...@@ -123,10 +123,10 @@ export default { ...@@ -123,10 +123,10 @@ export default {
/> />
<div class="clearfix prepend-top-10"> <div class="clearfix prepend-top-10">
<button <button
ref="submit-button"
:disabled="disabled"
class="btn btn-success float-left" class="btn btn-success float-left"
type="submit" type="submit"
:disabled="disabled"
ref="submit-button"
> >
Submit issue Submit issue
</button> </button>
......
...@@ -21,8 +21,17 @@ window.gl = window.gl || {}; ...@@ -21,8 +21,17 @@ window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardSidebar = Vue.extend({ gl.issueBoards.BoardSidebar = Vue.extend({
components: {
assigneeTitle,
assignees,
removeBtn: gl.issueBoards.RemoveIssueBtn,
subscriptions,
},
props: { props: {
currentUser: Object currentUser: {
type: Object,
default: () => ({}),
},
}, },
data() { data() {
return { return {
...@@ -64,6 +73,26 @@ gl.issueBoards.BoardSidebar = Vue.extend({ ...@@ -64,6 +73,26 @@ gl.issueBoards.BoardSidebar = Vue.extend({
deep: true deep: true
}, },
}, },
created () {
// Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
},
beforeDestroy() {
eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
eventHub.$off('sidebar.addAssignee', this.addAssignee);
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
mounted () {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
new LabelsSelect();
new Sidebar();
},
methods: { methods: {
closeSidebar () { closeSidebar () {
this.detail.issue = {}; this.detail.issue = {};
...@@ -97,30 +126,4 @@ gl.issueBoards.BoardSidebar = Vue.extend({ ...@@ -97,30 +126,4 @@ gl.issueBoards.BoardSidebar = Vue.extend({
}); });
}, },
}, },
created () {
// Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
},
beforeDestroy() {
eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
eventHub.$off('sidebar.addAssignee', this.addAssignee);
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
mounted () {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
new LabelsSelect();
new Sidebar();
},
components: {
assigneeTitle,
assignees,
removeBtn: gl.issueBoards.RemoveIssueBtn,
subscriptions,
},
}); });
...@@ -9,6 +9,9 @@ window.gl = window.gl || {}; ...@@ -9,6 +9,9 @@ window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.IssueCardInner = Vue.extend({ gl.issueBoards.IssueCardInner = Vue.extend({
components: {
UserAvatarLink,
},
props: { props: {
issue: { issue: {
type: Object, type: Object,
...@@ -35,6 +38,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({ ...@@ -35,6 +38,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
groupId: { groupId: {
type: Number, type: Number,
required: false, required: false,
default: null,
}, },
}, },
data() { data() {
...@@ -44,9 +48,6 @@ gl.issueBoards.IssueCardInner = Vue.extend({ ...@@ -44,9 +48,6 @@ gl.issueBoards.IssueCardInner = Vue.extend({
maxCounter: 99, maxCounter: 99,
}; };
}, },
components: {
UserAvatarLink,
},
computed: { computed: {
numberOverLimit() { numberOverLimit() {
return this.issue.assignees.length - this.limitBeforeCounter; return this.issue.assignees.length - this.limitBeforeCounter;
......
...@@ -4,9 +4,6 @@ import modalMixin from '../../mixins/modal_mixins'; ...@@ -4,9 +4,6 @@ import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalEmptyState = Vue.extend({ gl.issueBoards.ModalEmptyState = Vue.extend({
mixins: [modalMixin], mixins: [modalMixin],
data() {
return ModalStore.store;
},
props: { props: {
newIssuePath: { newIssuePath: {
type: String, type: String,
...@@ -17,6 +14,9 @@ gl.issueBoards.ModalEmptyState = Vue.extend({ ...@@ -17,6 +14,9 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
required: true, required: true,
}, },
}, },
data() {
return ModalStore.store;
},
computed: { computed: {
contents() { contents() {
const obj = { const obj = {
......
...@@ -7,6 +7,9 @@ import ModalStore from '../../stores/modal_store'; ...@@ -7,6 +7,9 @@ import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalFooter = Vue.extend({ gl.issueBoards.ModalFooter = Vue.extend({
components: {
'lists-dropdown': gl.issueBoards.ModalFooterListsDropdown,
},
mixins: [modalMixin], mixins: [modalMixin],
data() { data() {
return { return {
...@@ -52,9 +55,6 @@ gl.issueBoards.ModalFooter = Vue.extend({ ...@@ -52,9 +55,6 @@ gl.issueBoards.ModalFooter = Vue.extend({
this.toggleModal(false); this.toggleModal(false);
}, },
}, },
components: {
'lists-dropdown': gl.issueBoards.ModalFooterListsDropdown,
},
template: ` template: `
<footer <footer
class="form-actions add-issues-footer"> class="form-actions add-issues-footer">
......
...@@ -5,6 +5,10 @@ import ModalStore from '../../stores/modal_store'; ...@@ -5,6 +5,10 @@ import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins'; import modalMixin from '../../mixins/modal_mixins';
gl.issueBoards.ModalHeader = Vue.extend({ gl.issueBoards.ModalHeader = Vue.extend({
components: {
'modal-tabs': gl.issueBoards.ModalTabs,
modalFilters,
},
mixins: [modalMixin], mixins: [modalMixin],
props: { props: {
projectId: { projectId: {
...@@ -42,10 +46,6 @@ gl.issueBoards.ModalHeader = Vue.extend({ ...@@ -42,10 +46,6 @@ gl.issueBoards.ModalHeader = Vue.extend({
ModalStore.toggleAll(); ModalStore.toggleAll();
}, },
}, },
components: {
'modal-tabs': gl.issueBoards.ModalTabs,
modalFilters,
},
template: ` template: `
<div> <div>
<header class="add-issues-header form-actions"> <header class="add-issues-header form-actions">
......
...@@ -10,6 +10,13 @@ import './empty_state'; ...@@ -10,6 +10,13 @@ import './empty_state';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
gl.issueBoards.IssuesModal = Vue.extend({ gl.issueBoards.IssuesModal = Vue.extend({
components: {
'modal-header': gl.issueBoards.ModalHeader,
'modal-list': gl.issueBoards.ModalList,
'modal-footer': gl.issueBoards.ModalFooter,
'empty-state': gl.issueBoards.ModalEmptyState,
loadingIcon,
},
props: { props: {
newIssuePath: { newIssuePath: {
type: String, type: String,
...@@ -43,6 +50,22 @@ gl.issueBoards.IssuesModal = Vue.extend({ ...@@ -43,6 +50,22 @@ gl.issueBoards.IssuesModal = Vue.extend({
data() { data() {
return ModalStore.store; return ModalStore.store;
}, },
computed: {
showList() {
if (this.activeTab === 'selected') {
return this.selectedIssues.length > 0;
}
return this.issuesCount > 0;
},
showEmptyState() {
if (!this.loading && this.issuesCount === 0) {
return true;
}
return this.activeTab === 'selected' && this.selectedIssues.length === 0;
},
},
watch: { watch: {
page() { page() {
this.loadIssues(); this.loadIssues();
...@@ -80,6 +103,9 @@ gl.issueBoards.IssuesModal = Vue.extend({ ...@@ -80,6 +103,9 @@ gl.issueBoards.IssuesModal = Vue.extend({
deep: true, deep: true,
}, },
}, },
created() {
this.page = 1;
},
methods: { methods: {
loadIssues(clearIssues = false) { loadIssues(clearIssues = false) {
if (!this.showAddIssuesModal) return false; if (!this.showAddIssuesModal) return false;
...@@ -112,32 +138,6 @@ gl.issueBoards.IssuesModal = Vue.extend({ ...@@ -112,32 +138,6 @@ gl.issueBoards.IssuesModal = Vue.extend({
}); });
}, },
}, },
computed: {
showList() {
if (this.activeTab === 'selected') {
return this.selectedIssues.length > 0;
}
return this.issuesCount > 0;
},
showEmptyState() {
if (!this.loading && this.issuesCount === 0) {
return true;
}
return this.activeTab === 'selected' && this.selectedIssues.length === 0;
},
},
created() {
this.page = 1;
},
components: {
'modal-header': gl.issueBoards.ModalHeader,
'modal-list': gl.issueBoards.ModalList,
'modal-footer': gl.issueBoards.ModalFooter,
'empty-state': gl.issueBoards.ModalEmptyState,
loadingIcon,
},
template: ` template: `
<div <div
class="add-issues-modal" class="add-issues-modal"
......
...@@ -3,6 +3,9 @@ import bp from '../../../breakpoints'; ...@@ -3,6 +3,9 @@ import bp from '../../../breakpoints';
import ModalStore from '../../stores/modal_store'; import ModalStore from '../../stores/modal_store';
gl.issueBoards.ModalList = Vue.extend({ gl.issueBoards.ModalList = Vue.extend({
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
},
props: { props: {
issueLinkBase: { issueLinkBase: {
type: String, type: String,
...@@ -20,13 +23,6 @@ gl.issueBoards.ModalList = Vue.extend({ ...@@ -20,13 +23,6 @@ gl.issueBoards.ModalList = Vue.extend({
data() { data() {
return ModalStore.store; return ModalStore.store;
}, },
watch: {
activeTab() {
if (this.activeTab === 'all') {
ModalStore.purgeUnselectedIssues();
}
},
},
computed: { computed: {
loopIssues() { loopIssues() {
if (this.activeTab === 'all') { if (this.activeTab === 'all') {
...@@ -50,6 +46,25 @@ gl.issueBoards.ModalList = Vue.extend({ ...@@ -50,6 +46,25 @@ gl.issueBoards.ModalList = Vue.extend({
return groups; return groups;
}, },
}, },
watch: {
activeTab() {
if (this.activeTab === 'all') {
ModalStore.purgeUnselectedIssues();
}
},
},
mounted() {
this.scrollHandlerWrapper = this.scrollHandler.bind(this);
this.setColumnCountWrapper = this.setColumnCount.bind(this);
this.setColumnCount();
this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
window.addEventListener('resize', this.setColumnCountWrapper);
},
beforeDestroy() {
this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
window.removeEventListener('resize', this.setColumnCountWrapper);
},
methods: { methods: {
scrollHandler() { scrollHandler() {
const currentPage = Math.floor(this.issues.length / this.perPage); const currentPage = Math.floor(this.issues.length / this.perPage);
...@@ -96,21 +111,6 @@ gl.issueBoards.ModalList = Vue.extend({ ...@@ -96,21 +111,6 @@ gl.issueBoards.ModalList = Vue.extend({
} }
}, },
}, },
mounted() {
this.scrollHandlerWrapper = this.scrollHandler.bind(this);
this.setColumnCountWrapper = this.setColumnCount.bind(this);
this.setColumnCount();
this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
window.addEventListener('resize', this.setColumnCountWrapper);
},
beforeDestroy() {
this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
window.removeEventListener('resize', this.setColumnCountWrapper);
},
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
},
template: ` template: `
<section <section
class="add-issues-list add-issues-list-columns" class="add-issues-list add-issues-list-columns"
......
...@@ -55,7 +55,8 @@ class List { ...@@ -55,7 +55,8 @@ class List {
entityType = 'assignee_id'; entityType = 'assignee_id';
} }
return gl.boardService.createList(this.label.id) return gl.boardService
.createList(entity.id, entityType)
.then(res => res.data) .then(res => res.data)
.then(data => { .then(data => {
this.id = data.id; this.id = data.id;
......
...@@ -125,8 +125,8 @@ ...@@ -125,8 +125,8 @@
<template> <template>
<div <div
class="gl-responsive-table-row gl-responsive-table-row-col-span"
:class="rowJsClass" :class="rowJsClass"
class="gl-responsive-table-row gl-responsive-table-row-col-span"
> >
<div <div
class="gl-responsive-table-row-layout" class="gl-responsive-table-row-layout"
...@@ -155,8 +155,8 @@ ...@@ -155,8 +155,8 @@
<slot name="description"></slot> <slot name="description"></slot>
</div> </div>
<div <div
class="table-section table-button-footer section-align-top"
:class="{ 'section-20': showManageButton, 'section-15': !showManageButton }" :class="{ 'section-20': showManageButton, 'section-15': !showManageButton }"
class="table-section table-button-footer section-align-top"
role="gridcell" role="gridcell"
> >
<div <div
...@@ -164,18 +164,18 @@ ...@@ -164,18 +164,18 @@
class="btn-group table-action-buttons" class="btn-group table-action-buttons"
> >
<a <a
class="btn"
:href="manageLink" :href="manageLink"
class="btn"
> >
{{ manageButtonLabel }} {{ manageButtonLabel }}
</a> </a>
</div> </div>
<div class="btn-group table-action-buttons"> <div class="btn-group table-action-buttons">
<loading-button <loading-button
class="js-cluster-application-install-button"
:loading="installButtonLoading" :loading="installButtonLoading"
:disabled="installButtonDisabled" :disabled="installButtonDisabled"
:label="installButtonLabel" :label="installButtonLabel"
class="js-cluster-application-install-button"
@click="installClicked" @click="installClicked"
/> />
</div> </div>
......
...@@ -152,11 +152,11 @@ export default { ...@@ -152,11 +152,11 @@ export default {
<application-row <application-row
id="helm" id="helm"
:title="applications.helm.title" :title="applications.helm.title"
title-link="https://docs.helm.sh/"
:status="applications.helm.status" :status="applications.helm.status"
:status-reason="applications.helm.statusReason" :status-reason="applications.helm.statusReason"
:request-status="applications.helm.requestStatus" :request-status="applications.helm.requestStatus"
:request-reason="applications.helm.requestReason" :request-reason="applications.helm.requestReason"
title-link="https://docs.helm.sh/"
> >
<div slot="description"> <div slot="description">
{{ s__(`ClusterIntegration|Helm streamlines installing {{ s__(`ClusterIntegration|Helm streamlines installing
...@@ -168,11 +168,11 @@ export default { ...@@ -168,11 +168,11 @@ export default {
<application-row <application-row
:id="ingressId" :id="ingressId"
:title="applications.ingress.title" :title="applications.ingress.title"
title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
:status="applications.ingress.status" :status="applications.ingress.status"
:status-reason="applications.ingress.statusReason" :status-reason="applications.ingress.statusReason"
:request-status="applications.ingress.requestStatus" :request-status="applications.ingress.requestStatus"
:request-reason="applications.ingress.requestReason" :request-reason="applications.ingress.requestReason"
title-link="https://kubernetes.io/docs/concepts/services-networking/ingress/"
> >
<div slot="description"> <div slot="description">
<p> <p>
...@@ -191,10 +191,10 @@ export default { ...@@ -191,10 +191,10 @@ export default {
class="input-group" class="input-group"
> >
<input <input
type="text"
id="ingress-ip-address" id="ingress-ip-address"
class="form-control js-ip-address"
:value="ingressExternalIp" :value="ingressExternalIp"
type="text"
class="form-control js-ip-address"
readonly readonly
/> />
<span class="input-group-append"> <span class="input-group-append">
...@@ -255,12 +255,12 @@ export default { ...@@ -255,12 +255,12 @@ export default {
<application-row <application-row
id="prometheus" id="prometheus"
:title="applications.prometheus.title" :title="applications.prometheus.title"
title-link="https://prometheus.io/docs/introduction/overview/"
:manage-link="managePrometheusPath" :manage-link="managePrometheusPath"
:status="applications.prometheus.status" :status="applications.prometheus.status"
:status-reason="applications.prometheus.statusReason" :status-reason="applications.prometheus.statusReason"
:request-status="applications.prometheus.requestStatus" :request-status="applications.prometheus.requestStatus"
:request-reason="applications.prometheus.requestReason" :request-reason="applications.prometheus.requestReason"
title-link="https://prometheus.io/docs/introduction/overview/"
> >
<div <div
slot="description" slot="description"
...@@ -271,11 +271,11 @@ export default { ...@@ -271,11 +271,11 @@ export default {
<application-row <application-row
id="runner" id="runner"
:title="applications.runner.title" :title="applications.runner.title"
title-link="https://docs.gitlab.com/runner/"
:status="applications.runner.status" :status="applications.runner.status"
:status-reason="applications.runner.statusReason" :status-reason="applications.runner.statusReason"
:request-status="applications.runner.requestStatus" :request-status="applications.runner.requestStatus"
:request-reason="applications.runner.requestReason" :request-reason="applications.runner.requestReason"
title-link="https://docs.gitlab.com/runner/"
> >
<div slot="description"> <div slot="description">
{{ s__(`ClusterIntegration|GitLab Runner connects to this {{ s__(`ClusterIntegration|GitLab Runner connects to this
...@@ -287,12 +287,12 @@ export default { ...@@ -287,12 +287,12 @@ export default {
<application-row <application-row
id="jupyter" id="jupyter"
:title="applications.jupyter.title" :title="applications.jupyter.title"
title-link="https://jupyterhub.readthedocs.io/en/stable/"
:status="applications.jupyter.status" :status="applications.jupyter.status"
:status-reason="applications.jupyter.statusReason" :status-reason="applications.jupyter.statusReason"
:request-status="applications.jupyter.requestStatus" :request-status="applications.jupyter.requestStatus"
:request-reason="applications.jupyter.requestReason" :request-reason="applications.jupyter.requestReason"
:install-application-request-params="{ hostname: applications.jupyter.hostname }" :install-application-request-params="{ hostname: applications.jupyter.hostname }"
title-link="https://jupyterhub.readthedocs.io/en/stable/"
> >
<div slot="description"> <div slot="description">
<p> <p>
...@@ -311,10 +311,10 @@ export default { ...@@ -311,10 +311,10 @@ export default {
<div class="input-group"> <div class="input-group">
<input <input
type="text"
class="form-control js-hostname"
v-model="applications.jupyter.hostname" v-model="applications.jupyter.hostname"
:readonly="jupyterInstalled" :readonly="jupyterInstalled"
type="text"
class="form-control js-hostname"
/> />
<span <span
class="input-group-btn" class="input-group-btn"
......
...@@ -77,9 +77,9 @@ ...@@ -77,9 +77,9 @@
<div class="content-list pipelines"> <div class="content-list pipelines">
<loading-icon <loading-icon
v-if="isLoading"
:label="s__('Pipelines|Loading Pipelines')" :label="s__('Pipelines|Loading Pipelines')"
size="3" size="3"
v-if="isLoading"
class="prepend-top-20" class="prepend-top-20"
/> />
...@@ -91,8 +91,8 @@ ...@@ -91,8 +91,8 @@
/> />
<div <div
class="table-holder"
v-else-if="shouldRenderTable" v-else-if="shouldRenderTable"
class="table-holder"
> >
<pipelines-table-component <pipelines-table-component
:pipelines="state.pipelines" :pipelines="state.pipelines"
......
...@@ -66,8 +66,14 @@ export default class CreateMergeRequestDropdown { ...@@ -66,8 +66,14 @@ export default class CreateMergeRequestDropdown {
} }
bindEvents() { bindEvents() {
this.createMergeRequestButton.addEventListener('click', this.onClickCreateMergeRequestButton.bind(this)); this.createMergeRequestButton.addEventListener(
this.createTargetButton.addEventListener('click', this.onClickCreateMergeRequestButton.bind(this)); 'click',
this.onClickCreateMergeRequestButton.bind(this),
);
this.createTargetButton.addEventListener(
'click',
this.onClickCreateMergeRequestButton.bind(this),
);
this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this)); this.branchInput.addEventListener('keyup', this.onChangeInput.bind(this));
this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this)); this.dropdownToggle.addEventListener('click', this.onClickSetFocusOnBranchNameInput.bind(this));
this.refInput.addEventListener('keyup', this.onChangeInput.bind(this)); this.refInput.addEventListener('keyup', this.onChangeInput.bind(this));
...@@ -77,7 +83,8 @@ export default class CreateMergeRequestDropdown { ...@@ -77,7 +83,8 @@ export default class CreateMergeRequestDropdown {
checkAbilityToCreateBranch() { checkAbilityToCreateBranch() {
this.setUnavailableButtonState(); this.setUnavailableButtonState();
axios.get(this.canCreatePath) axios
.get(this.canCreatePath)
.then(({ data }) => { .then(({ data }) => {
this.setUnavailableButtonState(false); this.setUnavailableButtonState(false);
...@@ -105,7 +112,8 @@ export default class CreateMergeRequestDropdown { ...@@ -105,7 +112,8 @@ export default class CreateMergeRequestDropdown {
createBranch() { createBranch() {
this.isCreatingBranch = true; this.isCreatingBranch = true;
return axios.post(this.createBranchPath) return axios
.post(this.createBranchPath)
.then(({ data }) => { .then(({ data }) => {
this.branchCreated = true; this.branchCreated = true;
window.location.href = data.url; window.location.href = data.url;
...@@ -116,7 +124,8 @@ export default class CreateMergeRequestDropdown { ...@@ -116,7 +124,8 @@ export default class CreateMergeRequestDropdown {
createMergeRequest() { createMergeRequest() {
this.isCreatingMergeRequest = true; this.isCreatingMergeRequest = true;
return axios.post(this.createMrPath) return axios
.post(this.createMrPath)
.then(({ data }) => { .then(({ data }) => {
this.mergeRequestCreated = true; this.mergeRequestCreated = true;
window.location.href = data.url; window.location.href = data.url;
...@@ -195,7 +204,8 @@ export default class CreateMergeRequestDropdown { ...@@ -195,7 +204,8 @@ export default class CreateMergeRequestDropdown {
getRef(ref, target = 'all') { getRef(ref, target = 'all') {
if (!ref) return false; if (!ref) return false;
return axios.get(this.refsPath + ref) return axios
.get(`${this.refsPath}${encodeURIComponent(ref)}`)
.then(({ data }) => { .then(({ data }) => {
const branches = data[Object.keys(data)[0]]; const branches = data[Object.keys(data)[0]];
const tags = data[Object.keys(data)[1]]; const tags = data[Object.keys(data)[1]];
...@@ -204,7 +214,8 @@ export default class CreateMergeRequestDropdown { ...@@ -204,7 +214,8 @@ export default class CreateMergeRequestDropdown {
if (target === 'branch') { if (target === 'branch') {
result = CreateMergeRequestDropdown.findByValue(branches, ref); result = CreateMergeRequestDropdown.findByValue(branches, ref);
} else { } else {
result = CreateMergeRequestDropdown.findByValue(branches, ref, true) || result =
CreateMergeRequestDropdown.findByValue(branches, ref, true) ||
CreateMergeRequestDropdown.findByValue(tags, ref, true); CreateMergeRequestDropdown.findByValue(tags, ref, true);
this.suggestedRef = result; this.suggestedRef = result;
} }
...@@ -255,11 +266,13 @@ export default class CreateMergeRequestDropdown { ...@@ -255,11 +266,13 @@ export default class CreateMergeRequestDropdown {
} }
isBusy() { isBusy() {
return this.isCreatingMergeRequest || return (
this.isCreatingMergeRequest ||
this.mergeRequestCreated || this.mergeRequestCreated ||
this.isCreatingBranch || this.isCreatingBranch ||
this.branchCreated || this.branchCreated ||
this.isGettingRef; this.isGettingRef
);
} }
onChangeInput(event) { onChangeInput(event) {
...@@ -271,7 +284,8 @@ export default class CreateMergeRequestDropdown { ...@@ -271,7 +284,8 @@ export default class CreateMergeRequestDropdown {
value = this.branchInput.value; value = this.branchInput.value;
} else if (event.target === this.refInput) { } else if (event.target === this.refInput) {
target = 'ref'; target = 'ref';
value = event.target.value.slice(0, event.target.selectionStart) + value =
event.target.value.slice(0, event.target.selectionStart) +
event.target.value.slice(event.target.selectionEnd); event.target.value.slice(event.target.selectionEnd);
} else { } else {
return false; return false;
...@@ -396,7 +410,8 @@ export default class CreateMergeRequestDropdown { ...@@ -396,7 +410,8 @@ export default class CreateMergeRequestDropdown {
showNotAvailableMessage(target) { showNotAvailableMessage(target) {
const { input, message } = this.getTargetData(target); const { input, message } = this.getTargetData(target);
const text = target === 'branch' ? __('Branch is already taken') : __('Source is not available'); const text =
target === 'branch' ? __('Branch is already taken') : __('Source is not available');
this.removeMessage(target); this.removeMessage(target);
input.classList.add('gl-field-error-outline'); input.classList.add('gl-field-error-outline');
...@@ -459,11 +474,15 @@ export default class CreateMergeRequestDropdown { ...@@ -459,11 +474,15 @@ export default class CreateMergeRequestDropdown {
// target - 'branch' or 'ref' // target - 'branch' or 'ref'
// ref - string - the new value to use as branch or ref // ref - string - the new value to use as branch or ref
updateCreatePaths(target, ref) { updateCreatePaths(target, ref) {
const pathReplacement = `$1${ref}`; const pathReplacement = `$1${encodeURIComponent(ref)}`;
this.createBranchPath = this.createBranchPath.replace(this.regexps[target].createBranchPath, this.createBranchPath = this.createBranchPath.replace(
pathReplacement); this.regexps[target].createBranchPath,
this.createMrPath = this.createMrPath.replace(this.regexps[target].createMrPath, pathReplacement,
pathReplacement); );
this.createMrPath = this.createMrPath.replace(
this.regexps[target].createMrPath,
pathReplacement,
);
} }
} }
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
<template> <template>
<div class="landing content-block"> <div class="landing content-block">
<button <button
:aria-label="__('Dismiss Cycle Analytics introduction box')"
class="js-ca-dismiss-button dismiss-button" class="js-ca-dismiss-button dismiss-button"
type="button" type="button"
:aria-label="__('Dismiss Cycle Analytics introduction box')"
@click="dismissOverviewDialog" @click="dismissOverviewDialog"
> >
<i <i
......
...@@ -19,14 +19,14 @@ ...@@ -19,14 +19,14 @@
class="events-info float-right" class="events-info float-right"
> >
<i <i
class="fa fa-warning"
v-tooltip v-tooltip
aria-hidden="true"
:title="n__( :title="n__(
'Limited to showing %d event at most', 'Limited to showing %d event at most',
'Limited to showing %d events at most', 'Limited to showing %d events at most',
50 50
)" )"
class="fa fa-warning"
aria-hidden="true"
data-placement="top" data-placement="top"
> >
</i> </i>
......
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
<user-avatar-image :img-src="issue.author.avatarUrl"/> <user-avatar-image :img-src="issue.author.avatarUrl"/>
<h5 class="item-title issue-title"> <h5 class="item-title issue-title">
<a <a
class="issue-title"
:href="issue.url" :href="issue.url"
class="issue-title"
> >
{{ issue.title }} {{ issue.title }}
</a> </a>
......
...@@ -74,12 +74,12 @@ ...@@ -74,12 +74,12 @@
</template> </template>
<template v-else> <template v-else>
<span <span
class="merge-request-branch"
v-if="mergeRequest.branch" v-if="mergeRequest.branch"
class="merge-request-branch"
> >
<icon <icon
name="fork"
:size="16" :size="16"
name="fork"
/> />
<a :href="mergeRequest.branch.url"> <a :href="mergeRequest.branch.url">
{{ mergeRequest.branch.name }} {{ mergeRequest.branch.name }}
......
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
<ul class="stage-event-list"> <ul class="stage-event-list">
<li <li
v-for="(build, i) in items" v-for="(build, i) in items"
class="stage-event-item item-build-component"
:key="i" :key="i"
class="stage-event-item item-build-component"
> >
<div class="item-details"> <div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility --> <!-- FIXME: Pass an alt attribute here for accessibility -->
...@@ -52,8 +52,8 @@ ...@@ -52,8 +52,8 @@
#{{ build.id }} #{{ build.id }}
</a> </a>
<icon <icon
name="fork"
:size="16" :size="16"
name="fork"
/> />
<a <a
:href="build.branch.url" :href="build.branch.url"
......
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
#{{ build.id }} #{{ build.id }}
</a> </a>
<icon <icon
name="fork"
:size="16" :size="16"
name="fork"
/> />
<a <a
:href="build.branch.url" :href="build.branch.url"
......
...@@ -40,9 +40,9 @@ export default { ...@@ -40,9 +40,9 @@ export default {
<template> <template>
<button <button
class="btn"
:class="[{ disabled: isLoading }, btnCssClass]" :class="[{ disabled: isLoading }, btnCssClass]"
:disabled="isLoading" :disabled="isLoading"
class="btn"
@click="doAction"> @click="doAction">
<slot></slot> <slot></slot>
<loading-icon <loading-icon
......
...@@ -116,8 +116,8 @@ export default { ...@@ -116,8 +116,8 @@ export default {
<div class="append-bottom-default deploy-keys"> <div class="append-bottom-default deploy-keys">
<loading-icon <loading-icon
v-if="isLoading && !hasKeys" v-if="isLoading && !hasKeys"
size="2"
:label="s__('DeployKeys|Loading deploy keys')" :label="s__('DeployKeys|Loading deploy keys')"
size="2"
/> />
<template v-else-if="hasKeys"> <template v-else-if="hasKeys">
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs"> <div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
...@@ -138,16 +138,16 @@ export default { ...@@ -138,16 +138,16 @@ export default {
<navigation-tabs <navigation-tabs
:tabs="tabs" :tabs="tabs"
@onChangeTab="onChangeTab"
scope="deployKeys" scope="deployKeys"
@onChangeTab="onChangeTab"
/> />
</div> </div>
<keys-panel <keys-panel
class="qa-project-deploy-keys"
:project-id="projectId" :project-id="projectId"
:keys="keys[currentTab]" :keys="keys[currentTab]"
:store="store" :store="store"
:endpoint="endpoint" :endpoint="endpoint"
class="qa-project-deploy-keys"
/> />
</template> </template>
</div> </div>
......
...@@ -135,9 +135,9 @@ export default { ...@@ -135,9 +135,9 @@ export default {
<div class="table-mobile-content deploy-project-list"> <div class="table-mobile-content deploy-project-list">
<template v-if="projects.length > 0"> <template v-if="projects.length > 0">
<a <a
class="label deploy-project-label"
:title="projectTooltipTitle(firstProject)"
v-tooltip v-tooltip
:title="projectTooltipTitle(firstProject)"
class="label deploy-project-label"
> >
<span> <span>
{{ firstProject.project.full_name }} {{ firstProject.project.full_name }}
...@@ -145,22 +145,22 @@ export default { ...@@ -145,22 +145,22 @@ export default {
<icon :name="firstProject.can_push ? 'lock-open' : 'lock'"/> <icon :name="firstProject.can_push ? 'lock-open' : 'lock'"/>
</a> </a>
<a <a
v-tooltip
v-if="isExpandable" v-if="isExpandable"
:title="restProjectsTooltip"
class="label deploy-project-label" class="label deploy-project-label"
@click="toggleExpanded" @click="toggleExpanded"
:title="restProjectsTooltip"
v-tooltip
> >
<span>{{ restProjectsLabel }}</span> <span>{{ restProjectsLabel }}</span>
</a> </a>
<a <a
v-else-if="isExpanded" v-tooltip
v-for="deployKeysProject in restProjects" v-for="deployKeysProject in restProjects"
v-else-if="isExpanded"
:key="deployKeysProject.project.full_path" :key="deployKeysProject.project.full_path"
class="label deploy-project-label"
:href="deployKeysProject.project.full_path" :href="deployKeysProject.project.full_path"
:title="projectTooltipTitle(deployKeysProject)" :title="projectTooltipTitle(deployKeysProject)"
v-tooltip class="label deploy-project-label"
> >
<span> <span>
{{ deployKeysProject.project.full_name }} {{ deployKeysProject.project.full_name }}
...@@ -181,8 +181,8 @@ export default { ...@@ -181,8 +181,8 @@ export default {
</div> </div>
<div class="table-mobile-content text-secondary key-created-at"> <div class="table-mobile-content text-secondary key-created-at">
<span <span
:title="tooltipTitle(deployKey.created_at)" v-tooltip
v-tooltip> :title="tooltipTitle(deployKey.created_at)">
<icon name="calendar"/> <icon name="calendar"/>
<span>{{ timeFormated(deployKey.created_at) }}</span> <span>{{ timeFormated(deployKey.created_at) }}</span>
</span> </span>
...@@ -198,34 +198,34 @@ export default { ...@@ -198,34 +198,34 @@ export default {
{{ __('Enable') }} {{ __('Enable') }}
</action-btn> </action-btn>
<a <a
v-tooltip
v-if="deployKey.can_edit" v-if="deployKey.can_edit"
class="btn btn-default text-secondary"
:href="editDeployKeyPath" :href="editDeployKeyPath"
:title="__('Edit')" :title="__('Edit')"
class="btn btn-default text-secondary"
data-container="body" data-container="body"
v-tooltip
> >
<icon name="pencil"/> <icon name="pencil"/>
</a> </a>
<action-btn <action-btn
v-tooltip
v-if="isRemovable" v-if="isRemovable"
:deploy-key="deployKey" :deploy-key="deployKey"
:title="__('Remove')"
btn-css-class="btn-danger" btn-css-class="btn-danger"
type="remove" type="remove"
:title="__('Remove')"
data-container="body" data-container="body"
v-tooltip
> >
<icon name="remove"/> <icon name="remove"/>
</action-btn> </action-btn>
<action-btn <action-btn
v-tooltip
v-else-if="isEnabled" v-else-if="isEnabled"
:deploy-key="deployKey" :deploy-key="deployKey"
:title="__('Disable')"
btn-css-class="btn-warning" btn-css-class="btn-warning"
type="disable" type="disable"
:title="__('Disable')"
data-container="body" data-container="body"
v-tooltip
> >
<icon name="cancel"/> <icon name="cancel"/>
</action-btn> </action-btn>
......
...@@ -59,8 +59,8 @@ export default { ...@@ -59,8 +59,8 @@ export default {
/> />
</template> </template>
<div <div
class="settings-message text-center"
v-else v-else
class="settings-message text-center"
> >
{{ s__('DeployKeys|No deploy keys found. Create one with the form above.') }} {{ s__('DeployKeys|No deploy keys found. Create one with the form above.') }}
</div> </div>
......
...@@ -6,7 +6,10 @@ import Vue from 'vue'; ...@@ -6,7 +6,10 @@ import Vue from 'vue';
const CommentAndResolveBtn = Vue.extend({ const CommentAndResolveBtn = Vue.extend({
props: { props: {
discussionId: String, discussionId: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
......
...@@ -7,7 +7,15 @@ import Notes from '../../notes'; ...@@ -7,7 +7,15 @@ import Notes from '../../notes';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
const DiffNoteAvatars = Vue.extend({ const DiffNoteAvatars = Vue.extend({
props: ['discussionId'], components: {
userAvatarImage,
},
props: {
discussionId: {
type: String,
required: true,
},
},
data() { data() {
return { return {
isVisible: false, isVisible: false,
...@@ -17,77 +25,6 @@ const DiffNoteAvatars = Vue.extend({ ...@@ -17,77 +25,6 @@ const DiffNoteAvatars = Vue.extend({
collapseIcon, collapseIcon,
}; };
}, },
components: {
userAvatarImage,
},
template: `
<div class="diff-comment-avatar-holders"
:class="discussionClassName"
v-show="notesCount !== 0">
<div v-if="!isVisible">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image
v-for="note in notesSubset"
:key="note.id"
class="diff-comment-avatar js-diff-comment-avatar"
@click.native="clickedAvatar($event)"
:img-src="note.authorAvatar"
:tooltip-text="getTooltipText(note)"
:data-line-type="lineType"
:size="19"
data-html="true"
/>
<span v-if="notesCount > shownAvatars"
class="diff-comments-more-count has-tooltip js-diff-comment-avatar"
data-container="body"
data-placement="top"
ref="extraComments"
role="button"
:data-line-type="lineType"
:title="extraNotesTitle"
@click="clickedAvatar($event)">{{ moreText }}</span>
</div>
<button class="diff-notes-collapse js-diff-comment-avatar"
type="button"
aria-label="Show comments"
:data-line-type="lineType"
@click="clickedAvatar($event)"
v-if="isVisible"
v-html="collapseIcon">
</button>
</div>
`,
mounted() {
this.$nextTick(() => {
this.addNoCommentClass();
this.setDiscussionVisible();
this.lineType = $(this.$el).closest('.diff-line-num').hasClass('old_line') ? 'old' : 'new';
});
$(document).on('toggle.comments', () => {
this.$nextTick(() => {
this.setDiscussionVisible();
});
});
},
beforeDestroy() {
this.addNoCommentClass();
$(document).off('toggle.comments');
},
watch: {
storeState: {
handler() {
this.$nextTick(() => {
$('.has-tooltip', this.$el).tooltip('_fixTitle');
// We need to add/remove a class to an element that is outside the Vue instance
this.addNoCommentClass();
});
},
deep: true,
},
},
computed: { computed: {
discussionClassName() { discussionClassName() {
return `js-diff-avatars-${this.discussionId}`; return `js-diff-avatars-${this.discussionId}`;
...@@ -128,6 +65,37 @@ const DiffNoteAvatars = Vue.extend({ ...@@ -128,6 +65,37 @@ const DiffNoteAvatars = Vue.extend({
return `${plusSign}${this.notesCount - this.shownAvatars}`; return `${plusSign}${this.notesCount - this.shownAvatars}`;
}, },
}, },
watch: {
storeState: {
handler() {
this.$nextTick(() => {
$('.has-tooltip', this.$el).tooltip('_fixTitle');
// We need to add/remove a class to an element that is outside the Vue instance
this.addNoCommentClass();
});
},
deep: true,
},
},
mounted() {
this.$nextTick(() => {
this.addNoCommentClass();
this.setDiscussionVisible();
this.lineType = $(this.$el).closest('.diff-line-num').hasClass('old_line') ? 'old' : 'new';
});
$(document).on('toggle.comments', () => {
this.$nextTick(() => {
this.setDiscussionVisible();
});
});
},
beforeDestroy() {
this.addNoCommentClass();
$(document).off('toggle.comments');
},
methods: { methods: {
clickedAvatar(e) { clickedAvatar(e) {
Notes.instance.onAddDiffNote(e); Notes.instance.onAddDiffNote(e);
...@@ -164,6 +132,43 @@ const DiffNoteAvatars = Vue.extend({ ...@@ -164,6 +132,43 @@ const DiffNoteAvatars = Vue.extend({
return `${note.authorName}: ${note.noteTruncated}`; return `${note.authorName}: ${note.noteTruncated}`;
}, },
}, },
template: `
<div class="diff-comment-avatar-holders"
:class="discussionClassName"
v-show="notesCount !== 0">
<div v-if="!isVisible">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image
v-for="note in notesSubset"
:key="note.id"
class="diff-comment-avatar js-diff-comment-avatar"
@click.native="clickedAvatar($event)"
:img-src="note.authorAvatar"
:tooltip-text="getTooltipText(note)"
:data-line-type="lineType"
:size="19"
data-html="true"
/>
<span v-if="notesCount > shownAvatars"
class="diff-comments-more-count has-tooltip js-diff-comment-avatar"
data-container="body"
data-placement="top"
ref="extraComments"
role="button"
:data-line-type="lineType"
:title="extraNotesTitle"
@click="clickedAvatar($event)">{{ moreText }}</span>
</div>
<button class="diff-notes-collapse js-diff-comment-avatar"
type="button"
aria-label="Show comments"
:data-line-type="lineType"
@click="clickedAvatar($event)"
v-if="isVisible"
v-html="collapseIcon">
</button>
</div>
`,
}); });
Vue.component('diff-note-avatars', DiffNoteAvatars); Vue.component('diff-note-avatars', DiffNoteAvatars);
...@@ -10,7 +10,10 @@ import '../mixins/discussion'; ...@@ -10,7 +10,10 @@ import '../mixins/discussion';
const JumpToDiscussion = Vue.extend({ const JumpToDiscussion = Vue.extend({
mixins: [DiscussionMixins], mixins: [DiscussionMixins],
props: { props: {
discussionId: String discussionId: {
type: String,
required: true,
},
}, },
data: function () { data: function () {
return { return {
...@@ -52,6 +55,9 @@ const JumpToDiscussion = Vue.extend({ ...@@ -52,6 +55,9 @@ const JumpToDiscussion = Vue.extend({
return lastId; return lastId;
} }
}, },
created() {
this.discussion = this.discussions[this.discussionId];
},
methods: { methods: {
jumpToNextUnresolvedDiscussion: function () { jumpToNextUnresolvedDiscussion: function () {
let discussionsSelector; let discussionsSelector;
...@@ -202,9 +208,6 @@ const JumpToDiscussion = Vue.extend({ ...@@ -202,9 +208,6 @@ const JumpToDiscussion = Vue.extend({
}); });
} }
}, },
created() {
this.discussion = this.discussions[this.discussionId];
},
}); });
Vue.component('jump-to-discussion', JumpToDiscussion); Vue.component('jump-to-discussion', JumpToDiscussion);
...@@ -8,14 +8,38 @@ import Flash from '../../flash'; ...@@ -8,14 +8,38 @@ import Flash from '../../flash';
const ResolveBtn = Vue.extend({ const ResolveBtn = Vue.extend({
props: { props: {
noteId: Number, noteId: {
discussionId: String, type: Number,
resolved: Boolean, required: true,
canResolve: Boolean, },
resolvedBy: String, discussionId: {
authorName: String, type: String,
authorAvatar: String, required: true,
noteTruncated: String, },
resolved: {
type: Boolean,
required: true,
},
canResolve: {
type: Boolean,
required: true,
},
resolvedBy: {
type: String,
required: true,
},
authorName: {
type: String,
required: true,
},
authorAvatar: {
type: String,
required: true,
},
noteTruncated: {
type: String,
required: true,
},
}, },
data: function () { data: function () {
return { return {
...@@ -23,12 +47,6 @@ const ResolveBtn = Vue.extend({ ...@@ -23,12 +47,6 @@ const ResolveBtn = Vue.extend({
loading: false loading: false
}; };
}, },
watch: {
'discussions': {
handler: 'updateTooltip',
deep: true
}
},
computed: { computed: {
discussion: function () { discussion: function () {
return this.discussions[this.discussionId]; return this.discussions[this.discussionId];
...@@ -56,6 +74,32 @@ const ResolveBtn = Vue.extend({ ...@@ -56,6 +74,32 @@ const ResolveBtn = Vue.extend({
return this.note.resolved_by; return this.note.resolved_by;
}, },
}, },
watch: {
'discussions': {
handler: 'updateTooltip',
deep: true
}
},
mounted: function () {
$(this.$refs.button).tooltip({
container: 'body'
});
},
beforeDestroy: function () {
CommentsStore.delete(this.discussionId, this.noteId);
},
created: function () {
CommentsStore.create({
discussionId: this.discussionId,
noteId: this.noteId,
canResolve: this.canResolve,
resolved: this.resolved,
resolvedBy: this.resolvedBy,
authorName: this.authorName,
authorAvatar: this.authorAvatar,
noteTruncated: this.noteTruncated,
});
},
methods: { methods: {
updateTooltip: function () { updateTooltip: function () {
this.$nextTick(() => { this.$nextTick(() => {
...@@ -95,26 +139,6 @@ const ResolveBtn = Vue.extend({ ...@@ -95,26 +139,6 @@ const ResolveBtn = Vue.extend({
.catch(() => new Flash('An error occurred when trying to resolve a comment. Please try again.')); .catch(() => new Flash('An error occurred when trying to resolve a comment. Please try again.'));
} }
}, },
mounted: function () {
$(this.$refs.button).tooltip({
container: 'body'
});
},
beforeDestroy: function () {
CommentsStore.delete(this.discussionId, this.noteId);
},
created: function () {
CommentsStore.create({
discussionId: this.discussionId,
noteId: this.noteId,
canResolve: this.canResolve,
resolved: this.resolved,
resolvedBy: this.resolvedBy,
authorName: this.authorName,
authorAvatar: this.authorAvatar,
noteTruncated: this.noteTruncated,
});
}
}); });
Vue.component('resolve-btn', ResolveBtn); Vue.component('resolve-btn', ResolveBtn);
...@@ -9,7 +9,10 @@ import '../mixins/discussion'; ...@@ -9,7 +9,10 @@ import '../mixins/discussion';
window.ResolveCount = Vue.extend({ window.ResolveCount = Vue.extend({
mixins: [DiscussionMixins], mixins: [DiscussionMixins],
props: { props: {
loggedOut: Boolean loggedOut: {
type: Boolean,
required: true,
},
}, },
data: function () { data: function () {
return { return {
......
...@@ -6,9 +6,18 @@ import Vue from 'vue'; ...@@ -6,9 +6,18 @@ import Vue from 'vue';
const ResolveDiscussionBtn = Vue.extend({ const ResolveDiscussionBtn = Vue.extend({
props: { props: {
discussionId: String, discussionId: {
mergeRequestId: Number, type: String,
canResolve: Boolean, required: true,
},
mergeRequestId: {
type: Number,
required: true,
},
canResolve: {
type: Boolean,
required: true,
},
}, },
data: function() { data: function() {
return { return {
...@@ -45,16 +54,16 @@ const ResolveDiscussionBtn = Vue.extend({ ...@@ -45,16 +54,16 @@ const ResolveDiscussionBtn = Vue.extend({
} }
} }
}, },
created: function () {
CommentsStore.createDiscussion(this.discussionId, this.canResolve);
this.discussion = CommentsStore.state[this.discussionId];
},
methods: { methods: {
resolve: function () { resolve: function () {
ResolveService.toggleResolveForDiscussion(this.mergeRequestId, this.discussionId); ResolveService.toggleResolveForDiscussion(this.mergeRequestId, this.discussionId);
} }
}, },
created: function () {
CommentsStore.createDiscussion(this.discussionId, this.canResolve);
this.discussion = CommentsStore.state[this.discussionId];
}
}); });
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn); Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
...@@ -43,17 +43,17 @@ ...@@ -43,17 +43,17 @@
<div class="environments-container"> <div class="environments-container">
<loading-icon <loading-icon
v-if="isLoading"
class="prepend-top-default" class="prepend-top-default"
label="Loading environments" label="Loading environments"
v-if="isLoading"
size="3" size="3"
/> />
<slot name="emptyState"></slot> <slot name="emptyState"></slot>
<div <div
class="table-holder" v-if="!isLoading && environments.length > 0"
v-if="!isLoading && environments.length > 0"> class="table-holder">
<environment-table <environment-table
:environments="environments" :environments="environments"
......
...@@ -52,18 +52,18 @@ ...@@ -52,18 +52,18 @@
role="group"> role="group">
<button <button
v-tooltip v-tooltip
:title="title"
:aria-label="title"
:disabled="isLoading"
type="button" type="button"
class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container" class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container"
data-container="body" data-container="body"
data-toggle="dropdown" data-toggle="dropdown"
:title="title"
:aria-label="title"
:disabled="isLoading"
> >
<span> <span>
<icon <icon
name="play"
:size="12" :size="12"
name="play"
/> />
<i <i
class="fa fa-caret-down" class="fa fa-caret-down"
...@@ -79,15 +79,15 @@ ...@@ -79,15 +79,15 @@
v-for="(action, i) in actions" v-for="(action, i) in actions"
:key="i"> :key="i">
<button <button
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
type="button" type="button"
class="js-manual-action-link no-btn btn" class="js-manual-action-link no-btn btn"
@click="onClickAction(action.play_path)" @click="onClickAction(action.play_path)"
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
> >
<icon <icon
name="play"
:size="12" :size="12"
name="play"
/> />
<span> <span>
{{ action.name }} {{ action.name }}
......
...@@ -29,17 +29,17 @@ ...@@ -29,17 +29,17 @@
<template> <template>
<a <a
v-tooltip v-tooltip
:title="title"
:aria-label="title"
:href="externalUrl"
class="btn external-url" class="btn external-url"
data-container="body" data-container="body"
target="_blank" target="_blank"
rel="noopener noreferrer nofollow" rel="noopener noreferrer nofollow"
:title="title"
:aria-label="title"
:href="externalUrl"
> >
<icon <icon
name="external-link"
:size="12" :size="12"
name="external-link"
/> />
</a> </a>
</template> </template>
...@@ -427,11 +427,11 @@ ...@@ -427,11 +427,11 @@
</script> </script>
<template> <template>
<div <div
class="gl-responsive-table-row"
:class="{ :class="{
'js-child-row environment-child-row': model.isChildren, 'js-child-row environment-child-row': model.isChildren,
'folder-row': model.isFolder, 'folder-row': model.isFolder,
}" }"
class="gl-responsive-table-row"
role="row"> role="row">
<div <div
class="table-section section-10" class="table-section section-10"
...@@ -446,19 +446,19 @@ ...@@ -446,19 +446,19 @@
</div> </div>
<a <a
v-if="!model.isFolder" v-if="!model.isFolder"
class="environment-name flex-truncate-parent table-mobile-content" :href="environmentPath"
:href="environmentPath"> class="environment-name flex-truncate-parent table-mobile-content">
<span <span
class="flex-truncate-child"
v-tooltip v-tooltip
:title="model.name" :title="model.name"
class="flex-truncate-child"
>{{ model.name }}</span> >{{ model.name }}</span>
</a> </a>
<span <span
v-else v-else
class="folder-name" class="folder-name"
@click="onClickFolder" role="button"
role="button"> @click="onClickFolder">
<span class="folder-icon"> <span class="folder-icon">
<i <i
...@@ -503,11 +503,11 @@ ...@@ -503,11 +503,11 @@
<span v-if="!model.isFolder && deploymentHasUser"> <span v-if="!model.isFolder && deploymentHasUser">
by by
<user-avatar-link <user-avatar-link
class="js-deploy-user-container"
:link-href="deploymentUser.web_url" :link-href="deploymentUser.web_url"
:img-src="deploymentUser.avatar_url" :img-src="deploymentUser.avatar_url"
:img-alt="userImageAltDescription" :img-alt="userImageAltDescription"
:tooltip-text="deploymentUser.username" :tooltip-text="deploymentUser.username"
class="js-deploy-user-container"
/> />
</span> </span>
</div> </div>
...@@ -518,8 +518,8 @@ ...@@ -518,8 +518,8 @@
> >
<a <a
v-if="shouldRenderBuildName" v-if="shouldRenderBuildName"
class="build-link flex-truncate-parent"
:href="buildPath" :href="buildPath"
class="build-link flex-truncate-parent"
> >
<span class="flex-truncate-child">{{ buildName }}</span> <span class="flex-truncate-child">{{ buildName }}</span>
</a> </a>
......
...@@ -28,16 +28,16 @@ ...@@ -28,16 +28,16 @@
<template> <template>
<a <a
v-tooltip v-tooltip
class="btn monitoring-url d-none d-sm-none d-md-block"
data-container="body"
rel="noopener noreferrer nofollow"
:href="monitoringUrl" :href="monitoringUrl"
:title="title" :title="title"
:aria-label="title" :aria-label="title"
class="btn monitoring-url d-none d-sm-none d-md-block"
data-container="body"
rel="noopener noreferrer nofollow"
> >
<icon <icon
name="chart"
:size="12" :size="12"
name="chart"
/> />
</a> </a>
</template> </template>
...@@ -39,10 +39,10 @@ ...@@ -39,10 +39,10 @@
</script> </script>
<template> <template>
<button <button
:disabled="isLoading"
type="button" type="button"
class="btn d-none d-sm-none d-md-block" class="btn d-none d-sm-none d-md-block"
@click="onClick" @click="onClick"
:disabled="isLoading"
> >
<span v-if="isLastDeployment"> <span v-if="isLastDeployment">
......
...@@ -54,13 +54,13 @@ ...@@ -54,13 +54,13 @@
<template> <template>
<button <button
v-tooltip v-tooltip
:disabled="isLoading"
:title="title"
:aria-label="title"
type="button" type="button"
class="btn stop-env-link d-none d-sm-none d-md-block" class="btn stop-env-link d-none d-sm-none d-md-block"
data-container="body" data-container="body"
@click="onClick" @click="onClick"
:disabled="isLoading"
:title="title"
:aria-label="title"
> >
<i <i
class="fa fa-stop stop-env-icon" class="fa fa-stop stop-env-icon"
......
...@@ -30,15 +30,15 @@ ...@@ -30,15 +30,15 @@
<template> <template>
<a <a
v-tooltip v-tooltip
class="btn terminal-button d-none d-sm-none d-md-block"
data-container="body"
:title="title" :title="title"
:aria-label="title" :aria-label="title"
:href="terminalPath" :href="terminalPath"
class="btn terminal-button d-none d-sm-none d-md-block"
data-container="body"
> >
<icon <icon
name="terminal"
:size="12" :size="12"
name="terminal"
/> />
</a> </a>
</template> </template>
...@@ -93,8 +93,8 @@ ...@@ -93,8 +93,8 @@
<div class="top-area"> <div class="top-area">
<tabs <tabs
:tabs="tabs" :tabs="tabs"
@onChangeTab="onChangeTab"
scope="environments" scope="environments"
@onChangeTab="onChangeTab"
/> />
<div <div
...@@ -119,8 +119,8 @@ ...@@ -119,8 +119,8 @@
@onChangePage="onChangePage" @onChangePage="onChangePage"
> >
<empty-state <empty-state
slot="emptyState"
v-if="!isLoading && state.environments.length === 0" v-if="!isLoading && state.environments.length === 0"
slot="emptyState"
:new-path="newEnvironmentPath" :new-path="newEnvironmentPath"
:help-path="helpPagePath" :help-path="helpPagePath"
:can-create-environment="canCreateEnvironment" :can-create-environment="canCreateEnvironment"
......
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
<template> <template>
<div :class="cssContainerClass"> <div :class="cssContainerClass">
<div <div
class="top-area"
v-if="!isLoading" v-if="!isLoading"
class="top-area"
> >
<h4 class="js-folder-name environments-folder-name"> <h4 class="js-folder-name environments-folder-name">
...@@ -49,8 +49,8 @@ ...@@ -49,8 +49,8 @@
<tabs <tabs
:tabs="tabs" :tabs="tabs"
@onChangeTab="onChangeTab"
scope="environments" scope="environments"
@onChangeTab="onChangeTab"
/> />
</div> </div>
......
...@@ -72,9 +72,9 @@ export default { ...@@ -72,9 +72,9 @@ export default {
@click="onItemActivated(item.text)"> @click="onItemActivated(item.text)">
<span> <span>
<span <span
class="filtered-search-history-dropdown-token"
v-for="(token, index) in item.tokens" v-for="(token, index) in item.tokens"
:key="`dropdown-token-${index}`" :key="`dropdown-token-${index}`"
class="filtered-search-history-dropdown-token"
> >
<span class="name">{{ token.prefix }}</span> <span class="name">{{ token.prefix }}</span>
<span class="value">{{ token.suffix }}</span> <span class="value">{{ token.suffix }}</span>
......
...@@ -216,10 +216,10 @@ export default { ...@@ -216,10 +216,10 @@ export default {
<template> <template>
<div> <div>
<loading-icon <loading-icon
class="loading-animation prepend-top-20"
size="2"
v-if="isLoading" v-if="isLoading"
:label="s__('GroupsTree|Loading groups')" :label="s__('GroupsTree|Loading groups')"
class="loading-animation prepend-top-20"
size="2"
/> />
<groups-component <groups-component
v-if="!isLoading" v-if="!isLoading"
...@@ -230,10 +230,10 @@ export default { ...@@ -230,10 +230,10 @@ export default {
/> />
<deprecated-modal <deprecated-modal
v-show="showModal" v-show="showModal"
kind="warning"
:primary-button-label="__('Leave')" :primary-button-label="__('Leave')"
:title="__('Are you sure?')" :title="__('Are you sure?')"
:text="groupLeaveConfirmationMessage" :text="groupLeaveConfirmationMessage"
kind="warning"
@cancel="hideLeaveGroupModal" @cancel="hideLeaveGroupModal"
@submit="leaveGroup" @submit="leaveGroup"
/> />
......
...@@ -71,14 +71,14 @@ export default { ...@@ -71,14 +71,14 @@ export default {
<template> <template>
<li <li
@click.stop="onClickRowGroup"
:id="groupDomId" :id="groupDomId"
:class="rowClass" :class="rowClass"
class="group-row" class="group-row"
@click.stop="onClickRowGroup"
> >
<div <div
class="group-row-contents" :class="{ 'project-row-contents': !isGroup }"
:class="{ 'project-row-contents': !isGroup }"> class="group-row-contents">
<item-actions <item-actions
v-if="isGroup" v-if="isGroup"
:group="group" :group="group"
...@@ -99,8 +99,8 @@ export default { ...@@ -99,8 +99,8 @@ export default {
/> />
</div> </div>
<div <div
class="avatar-container prepend-top-8 prepend-left-5 s24 d-none d-sm-block"
:class="{ 'content-loading': group.isChildrenLoading }" :class="{ 'content-loading': group.isChildrenLoading }"
class="avatar-container prepend-top-8 prepend-left-5 s24 d-none d-sm-block"
> >
<a <a
:href="group.relativePath" :href="group.relativePath"
...@@ -108,14 +108,14 @@ export default { ...@@ -108,14 +108,14 @@ export default {
> >
<img <img
v-if="hasAvatar" v-if="hasAvatar"
class="avatar s24"
:src="group.avatarUrl" :src="group.avatarUrl"
class="avatar s24"
/> />
<identicon <identicon
v-else v-else
size-class="s24"
:entity-id="group.id" :entity-id="group.id"
:entity-name="group.name" :entity-name="group.name"
size-class="s24"
/> />
</a> </a>
</div> </div>
......
...@@ -54,13 +54,13 @@ export default { ...@@ -54,13 +54,13 @@ export default {
<a <a
v-tooltip v-tooltip
v-if="group.canLeave" v-if="group.canLeave"
@click.prevent="onLeaveGroup"
:href="group.leavePath" :href="group.leavePath"
:title="leaveBtnTitle" :title="leaveBtnTitle"
:aria-label="leaveBtnTitle" :aria-label="leaveBtnTitle"
data-container="body" data-container="body"
data-placement="bottom" data-placement="bottom"
class="leave-group btn no-expand"> class="leave-group btn no-expand"
@click.prevent="onLeaveGroup">
<icon name="leave"/> <icon name="leave"/>
</a> </a>
</div> </div>
......
...@@ -45,44 +45,44 @@ ...@@ -45,44 +45,44 @@
<div class="stats"> <div class="stats">
<item-stats-value <item-stats-value
v-if="isGroup" v-if="isGroup"
css-class="number-subgroups"
icon-name="folder"
:title="__('Subgroups')" :title="__('Subgroups')"
:value="item.subgroupCount" :value="item.subgroupCount"
css-class="number-subgroups"
icon-name="folder"
/> />
<item-stats-value <item-stats-value
v-if="isGroup" v-if="isGroup"
css-class="number-projects"
icon-name="bookmark"
:title="__('Projects')" :title="__('Projects')"
:value="item.projectCount" :value="item.projectCount"
css-class="number-projects"
icon-name="bookmark"
/> />
<item-stats-value <item-stats-value
v-if="isGroup" v-if="isGroup"
css-class="number-users"
icon-name="users"
:title="__('Members')" :title="__('Members')"
:value="item.memberCount" :value="item.memberCount"
css-class="number-users"
icon-name="users"
/> />
<item-stats-value <item-stats-value
v-if="isProject" v-if="isProject"
:value="item.starCount"
css-class="project-stars" css-class="project-stars"
icon-name="star" icon-name="star"
:value="item.starCount"
/> />
<item-stats-value <item-stats-value
css-class="item-visibility"
tooltip-placement="left"
:icon-name="visibilityIcon" :icon-name="visibilityIcon"
:title="visibilityTooltip" :title="visibilityTooltip"
css-class="item-visibility"
tooltip-placement="left"
/> />
<div <div
class="last-updated"
v-if="isProject" v-if="isProject"
class="last-updated"
> >
<time-ago-tooltip <time-ago-tooltip
tooltip-placement="bottom"
:time="item.updatedAt" :time="item.updatedAt"
tooltip-placement="bottom"
/> />
</div> </div>
</div> </div>
......
...@@ -52,10 +52,10 @@ ...@@ -52,10 +52,10 @@
<template> <template>
<span <span
v-tooltip v-tooltip
data-container="body"
:data-placement="tooltipPlacement" :data-placement="tooltipPlacement"
:class="cssClass" :class="cssClass"
:title="title" :title="title"
data-container="body"
> >
<icon :name="iconName" /> <icon :name="iconName" />
<span <span
......
...@@ -39,12 +39,12 @@ export default { ...@@ -39,12 +39,12 @@ export default {
<li v-once> <li v-once>
<a <a
v-tooltip v-tooltip
data-container="body"
data-placement="right"
:href="goBackUrl" :href="goBackUrl"
class="ide-sidebar-link"
:title="s__('IDE|Go back')" :title="s__('IDE|Go back')"
:aria-label="s__('IDE|Go back')" :aria-label="s__('IDE|Go back')"
data-container="body"
data-placement="right"
class="ide-sidebar-link"
> >
<icon <icon
:size="16" :size="16"
...@@ -55,16 +55,16 @@ export default { ...@@ -55,16 +55,16 @@ export default {
<li> <li>
<button <button
v-tooltip v-tooltip
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.edit active: currentActivityView === $options.activityBarViews.edit
}" }"
@click.prevent="changedActivityView($event, $options.activityBarViews.edit)"
:title="s__('IDE|Edit')" :title="s__('IDE|Edit')"
:aria-label="s__('IDE|Edit')" :aria-label="s__('IDE|Edit')"
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
@click.prevent="changedActivityView($event, $options.activityBarViews.edit)"
> >
<icon <icon
name="code" name="code"
...@@ -74,16 +74,16 @@ export default { ...@@ -74,16 +74,16 @@ export default {
<li> <li>
<button <button
v-tooltip v-tooltip
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-review-mode"
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.review active: currentActivityView === $options.activityBarViews.review
}" }"
@click.prevent="changedActivityView($event, $options.activityBarViews.review)"
:title="s__('IDE|Review')" :title="s__('IDE|Review')"
:aria-label="s__('IDE|Review')" :aria-label="s__('IDE|Review')"
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.activityBarViews.review)"
> >
<icon <icon
name="file-modified" name="file-modified"
...@@ -93,16 +93,16 @@ export default { ...@@ -93,16 +93,16 @@ export default {
<li v-show="hasChanges"> <li v-show="hasChanges">
<button <button
v-tooltip v-tooltip
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-commit-mode"
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.commit active: currentActivityView === $options.activityBarViews.commit
}" }"
@click.prevent="changedActivityView($event, $options.activityBarViews.commit)"
:title="s__('IDE|Commit')" :title="s__('IDE|Commit')"
:aria-label="s__('IDE|Commit')" :aria-label="s__('IDE|Commit')"
data-container="body"
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-commit-mode"
@click.prevent="changedActivityView($event, $options.activityBarViews.commit)"
> >
<icon <icon
name="commit" name="commit"
......
...@@ -91,7 +91,6 @@ export default { ...@@ -91,7 +91,6 @@ export default {
<template> <template>
<div <div
class="multi-file-commit-form"
:class="{ :class="{
'is-compact': isCompact, 'is-compact': isCompact,
'is-full': !isCompact 'is-full': !isCompact
...@@ -99,6 +98,7 @@ export default { ...@@ -99,6 +98,7 @@ export default {
:style="{ :style="{
height: componentHeight ? `${componentHeight}px` : null, height: componentHeight ? `${componentHeight}px` : null,
}" }"
class="multi-file-commit-form"
> >
<transition <transition
name="commit-form-slide-up" name="commit-form-slide-up"
...@@ -108,12 +108,12 @@ export default { ...@@ -108,12 +108,12 @@ export default {
> >
<div <div
v-if="isCompact" v-if="isCompact"
class="commit-form-compact"
ref="compactEl" ref="compactEl"
class="commit-form-compact"
> >
<button <button
type="button"
:disabled="!hasChanges" :disabled="!hasChanges"
type="button"
class="btn btn-primary btn-sm btn-block" class="btn btn-primary btn-sm btn-block"
@click="toggleIsSmall" @click="toggleIsSmall"
> >
...@@ -126,8 +126,8 @@ export default { ...@@ -126,8 +126,8 @@ export default {
</div> </div>
<form <form
v-if="!isCompact" v-if="!isCompact"
@submit.prevent.stop="commitChanges"
ref="formEl" ref="formEl"
@submit.prevent.stop="commitChanges"
> >
<transition name="fade"> <transition name="fade">
<success-message <success-message
...@@ -143,8 +143,8 @@ export default { ...@@ -143,8 +143,8 @@ export default {
<loading-button <loading-button
:loading="submitCommitLoading" :loading="submitCommitLoading"
:disabled="commitButtonDisabled" :disabled="commitButtonDisabled"
container-class="btn btn-success btn-sm float-left"
:label="__('Commit')" :label="__('Commit')"
container-class="btn btn-success btn-sm float-left"
@click="commitChanges" @click="commitChanges"
/> />
<button <button
......
...@@ -43,6 +43,15 @@ export default { ...@@ -43,6 +43,15 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
activeFileKey: {
type: String,
required: false,
default: null,
},
keyPrefix: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
...@@ -113,8 +122,9 @@ export default { ...@@ -113,8 +122,9 @@ export default {
<list-item <list-item
:file="file" :file="file"
:action-component="itemActionComponent" :action-component="itemActionComponent"
:key-prefix="title" :key-prefix="keyPrefix"
:staged-list="stagedList" :staged-list="stagedList"
:active-file-key="activeFileKey"
/> />
</li> </li>
</ul> </ul>
......
...@@ -30,6 +30,11 @@ export default { ...@@ -30,6 +30,11 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
activeFileKey: {
type: String,
required: false,
default: null,
},
}, },
computed: { computed: {
iconName() { iconName() {
...@@ -39,6 +44,12 @@ export default { ...@@ -39,6 +44,12 @@ export default {
iconClass() { iconClass() {
return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`; return `multi-file-${this.file.tempFile ? 'addition' : 'modified'} append-right-8`;
}, },
fullKey() {
return `${this.keyPrefix}-${this.file.key}`;
},
isActive() {
return this.activeFileKey === this.fullKey;
},
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -51,7 +62,7 @@ export default { ...@@ -51,7 +62,7 @@ export default {
openFileInEditor() { openFileInEditor() {
return this.openPendingTab({ return this.openPendingTab({
file: this.file, file: this.file,
keyPrefix: this.keyPrefix.toLowerCase(), keyPrefix: this.keyPrefix,
}).then(changeViewer => { }).then(changeViewer => {
if (changeViewer) { if (changeViewer) {
this.updateViewer(viewerTypes.diff); this.updateViewer(viewerTypes.diff);
...@@ -70,7 +81,12 @@ export default { ...@@ -70,7 +81,12 @@ export default {
</script> </script>
<template> <template>
<div class="multi-file-commit-list-item"> <div
:class="{
'is-active': isActive
}"
class="multi-file-commit-list-item"
>
<button <button
type="button" type="button"
class="multi-file-commit-list-path" class="multi-file-commit-list-path"
......
...@@ -66,10 +66,10 @@ export default { ...@@ -66,10 +66,10 @@ export default {
<template> <template>
<fieldset class="common-note-form ide-commit-message-field"> <fieldset class="common-note-form ide-commit-message-field">
<div <div
class="md-area"
:class="{ :class="{
'is-focused': isFocused 'is-focused': isFocused
}" }"
class="md-area"
> >
<div <div
v-once v-once
...@@ -92,10 +92,10 @@ export default { ...@@ -92,10 +92,10 @@ export default {
<div class="ide-commit-message-textarea-container"> <div class="ide-commit-message-textarea-container">
<div class="ide-commit-message-highlights-container"> <div class="ide-commit-message-highlights-container">
<div <div
class="note-textarea highlights monospace"
:style="{ :style="{
transform: `translate3d(0, ${-scrollTop}px, 0)` transform: `translate3d(0, ${-scrollTop}px, 0)`
}" }"
class="note-textarea highlights monospace"
> >
<div <div
v-for="(line, index) in allLines" v-for="(line, index) in allLines"
...@@ -113,15 +113,15 @@ export default { ...@@ -113,15 +113,15 @@ export default {
</div> </div>
</div> </div>
<textarea <textarea
class="note-textarea ide-commit-message-textarea" ref="textarea"
name="commit-message"
:placeholder="__('Write a commit message...')" :placeholder="__('Write a commit message...')"
:value="text" :value="text"
class="note-textarea ide-commit-message-textarea"
name="commit-message"
@scroll="handleScroll" @scroll="handleScroll"
@input="onInput" @input="onInput"
@focus="updateIsFocused(true)" @focus="updateIsFocused(true)"
@blur="updateIsFocused(false)" @blur="updateIsFocused(false)"
ref="textarea"
> >
</textarea> </textarea>
</div> </div>
......
...@@ -58,12 +58,12 @@ export default { ...@@ -58,12 +58,12 @@ export default {
}" }"
> >
<input <input
type="radio"
name="commit-action"
:value="value" :value="value"
@change="updateCommitAction($event.target.value)"
:checked="commitAction === value" :checked="commitAction === value"
:disabled="disabled" :disabled="disabled"
type="radio"
name="commit-action"
@change="updateCommitAction($event.target.value)"
/> />
<span class="prepend-left-10"> <span class="prepend-left-10">
<span <span
...@@ -80,9 +80,9 @@ export default { ...@@ -80,9 +80,9 @@ export default {
class="ide-commit-new-branch" class="ide-commit-new-branch"
> >
<input <input
:placeholder="newBranchName"
type="text" type="text"
class="form-control monospace" class="form-control monospace"
:placeholder="newBranchName"
@input="updateBranchName($event.target.value)" @input="updateBranchName($event.target.value)"
/> />
</div> </div>
......
...@@ -29,30 +29,30 @@ export default { ...@@ -29,30 +29,30 @@ export default {
> >
<button <button
v-tooltip v-tooltip
type="button"
class="btn btn-blank append-right-5"
:aria-label="__('Stage changes')" :aria-label="__('Stage changes')"
:title="__('Stage changes')" :title="__('Stage changes')"
type="button"
class="btn btn-blank append-right-5"
data-container="body" data-container="body"
@click.stop="stageChange(path)" @click.stop="stageChange(path)"
> >
<icon <icon
name="mobile-issue-close"
:size="12" :size="12"
name="mobile-issue-close"
/> />
</button> </button>
<button <button
v-tooltip v-tooltip
type="button"
class="btn btn-blank"
:aria-label="__('Discard changes')" :aria-label="__('Discard changes')"
:title="__('Discard changes')" :title="__('Discard changes')"
type="button"
class="btn btn-blank"
data-container="body" data-container="body"
@click.stop="discardFileChanges(path)" @click.stop="discardFileChanges(path)"
> >
<icon <icon
name="remove"
:size="12" :size="12"
name="remove"
/> />
</button> </button>
</div> </div>
......
...@@ -29,16 +29,16 @@ export default { ...@@ -29,16 +29,16 @@ export default {
> >
<button <button
v-tooltip v-tooltip
type="button"
class="btn btn-blank"
:aria-label="__('Unstage changes')" :aria-label="__('Unstage changes')"
:title="__('Unstage changes')" :title="__('Unstage changes')"
type="button"
class="btn btn-blank"
data-container="body" data-container="body"
@click="unstageChange(path)" @click="unstageChange(path)"
> >
<icon <icon
name="history"
:size="12" :size="12"
name="history"
/> />
</button> </button>
</div> </div>
......
...@@ -44,11 +44,11 @@ export default { ...@@ -44,11 +44,11 @@ export default {
<ul> <ul>
<li> <li>
<a <a
href="#"
@click.prevent="changeMode($options.viewerTypes.mr)"
:class="{ :class="{
'is-active': viewer === $options.viewerTypes.mr, 'is-active': viewer === $options.viewerTypes.mr,
}" }"
href="#"
@click.prevent="changeMode($options.viewerTypes.mr)"
> >
<strong class="dropdown-menu-inner-title"> <strong class="dropdown-menu-inner-title">
{{ mergeReviewLine }} {{ mergeReviewLine }}
...@@ -60,11 +60,11 @@ export default { ...@@ -60,11 +60,11 @@ export default {
</li> </li>
<li> <li>
<a <a
href="#"
@click.prevent="changeMode($options.viewerTypes.diff)"
:class="{ :class="{
'is-active': viewer === $options.viewerTypes.diff, 'is-active': viewer === $options.viewerTypes.diff,
}" }"
href="#"
@click.prevent="changeMode($options.viewerTypes.diff)"
> >
<strong class="dropdown-menu-inner-title">{{ __('Reviewing') }}</strong> <strong class="dropdown-menu-inner-title">{{ __('Reviewing') }}</strong>
<span class="dropdown-menu-inner-content"> <span class="dropdown-menu-inner-content">
......
...@@ -26,15 +26,15 @@ export default { ...@@ -26,15 +26,15 @@ export default {
> >
<a <a
:href="file.permalink" :href="file.permalink"
target="_blank"
:title="s__('IDE|Open in file view')" :title="s__('IDE|Open in file view')"
target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<span class="vertical-align-middle">Open in file view</span> <span class="vertical-align-middle">Open in file view</span>
<icon <icon
:size="16"
name="external-link" name="external-link"
css-classes="vertical-align-middle space-right" css-classes="vertical-align-middle space-right"
:size="16"
/> />
</a> </a>
</div> </div>
......
...@@ -173,38 +173,38 @@ export default { ...@@ -173,38 +173,38 @@ export default {
> >
<div class="dropdown-input"> <div class="dropdown-input">
<input <input
ref="searchInput"
:placeholder="__('Search files')"
v-model="searchText"
type="search" type="search"
class="dropdown-input-field" class="dropdown-input-field"
:placeholder="__('Search files')"
autocomplete="off" autocomplete="off"
v-model="searchText"
ref="searchInput"
@keydown="onKeydown($event)" @keydown="onKeydown($event)"
@keyup="onKeyup($event)" @keyup="onKeyup($event)"
/> />
<i <i
aria-hidden="true"
class="fa fa-search dropdown-input-search"
:class="{ :class="{
hidden: showClearInputButton hidden: showClearInputButton
}" }"
aria-hidden="true"
class="fa fa-search dropdown-input-search"
></i> ></i>
<i <i
role="button"
:aria-label="__('Clear search input')" :aria-label="__('Clear search input')"
class="fa fa-times dropdown-input-clear"
:class="{ :class="{
show: showClearInputButton show: showClearInputButton
}" }"
role="button"
class="fa fa-times dropdown-input-clear"
@click="clearSearchInput" @click="clearSearchInput"
></i> ></i>
</div> </div>
<div> <div>
<virtual-list <virtual-list
ref="virtualScrollList"
:size="listHeight" :size="listHeight"
:remain="listShowCount" :remain="listShowCount"
wtag="ul" wtag="ul"
ref="virtualScrollList"
> >
<template v-if="filteredBlobsLength"> <template v-if="filteredBlobsLength">
<li <li
...@@ -212,11 +212,11 @@ export default { ...@@ -212,11 +212,11 @@ export default {
:key="file.key" :key="file.key"
> >
<item <item
class="disable-hover"
:file="file" :file="file"
:search-text="searchText" :search-text="searchText"
:focused="index === focusedIndex" :focused="index === focusedIndex"
:index="index" :index="index"
class="disable-hover"
@click="openFile" @click="openFile"
@mouseover="onMouseOver" @mouseover="onMouseOver"
@mousemove="onMouseMove" @mousemove="onMouseMove"
......
...@@ -59,11 +59,11 @@ export default { ...@@ -59,11 +59,11 @@ export default {
<template> <template>
<button <button
type="button"
class="diff-changed-file"
:class="{ :class="{
'is-focused': focused, 'is-focused': focused,
}" }"
type="button"
class="diff-changed-file"
@click.prevent="clickRow" @click.prevent="clickRow"
@mouseover="mouseOverRow" @mouseover="mouseOverRow"
@mousemove="mouseMove" @mousemove="mouseMove"
......
...@@ -93,8 +93,8 @@ export default { ...@@ -93,8 +93,8 @@ export default {
:merge-request-id="currentMergeRequestId" :merge-request-id="currentMergeRequestId"
/> />
<repo-editor <repo-editor
class="multi-file-edit-pane-content"
:file="activeFile" :file="activeFile"
class="multi-file-edit-pane-content"
/> />
</template> </template>
<template <template
......
...@@ -36,8 +36,8 @@ export default { ...@@ -36,8 +36,8 @@ export default {
<template> <template>
<ide-tree-list <ide-tree-list
:viewer-type="viewer" :viewer-type="viewer"
header-class="ide-review-header"
:disable-action-dropdown="true" :disable-action-dropdown="true"
header-class="ide-review-header"
> >
<template <template
slot="header" slot="header"
......
...@@ -115,17 +115,17 @@ export default { ...@@ -115,17 +115,17 @@ export default {
<div class="multi-file-commit-panel-inner"> <div class="multi-file-commit-panel-inner">
<template v-if="loading"> <template v-if="loading">
<div <div
class="multi-file-loading-container"
v-for="n in 3" v-for="n in 3"
:key="n" :key="n"
class="multi-file-loading-container"
> >
<skeleton-loading-container /> <skeleton-loading-container />
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div <div
class="context-header ide-context-header dropdown"
ref="mergeRequestDropdown" ref="mergeRequestDropdown"
class="context-header ide-context-header dropdown"
> >
<button <button
type="button" type="button"
...@@ -136,18 +136,18 @@ export default { ...@@ -136,18 +136,18 @@ export default {
class="avatar-container s40 project-avatar" class="avatar-container s40 project-avatar"
> >
<project-avatar-image <project-avatar-image
class="avatar-container project-avatar"
:link-href="currentProject.path" :link-href="currentProject.path"
:img-src="currentProject.avatar_url" :img-src="currentProject.avatar_url"
:img-alt="currentProject.name" :img-alt="currentProject.name"
:img-size="40" :img-size="40"
class="avatar-container project-avatar"
/> />
</div> </div>
<identicon <identicon
v-else v-else
size-class="s40"
:entity-id="currentProject.id" :entity-id="currentProject.id"
:entity-name="currentProject.name" :entity-name="currentProject.name"
size-class="s40"
/> />
<div class="ide-sidebar-project-title"> <div class="ide-sidebar-project-title">
<div class="sidebar-context-title"> <div class="sidebar-context-title">
...@@ -155,11 +155,11 @@ export default { ...@@ -155,11 +155,11 @@ export default {
</div> </div>
<div class="d-flex"> <div class="d-flex">
<div <div
v-tooltip
v-if="currentBranchId" v-if="currentBranchId"
class="sidebar-context-title ide-sidebar-branch-title"
ref="branchId" ref="branchId"
v-tooltip
:title="branchTooltipTitle" :title="branchTooltipTitle"
class="sidebar-context-title ide-sidebar-branch-title"
> >
<icon <icon
name="branch" name="branch"
...@@ -168,10 +168,10 @@ export default { ...@@ -168,10 +168,10 @@ export default {
</div> </div>
<div <div
v-if="currentMergeRequestId" v-if="currentMergeRequestId"
class="sidebar-context-title ide-sidebar-branch-title"
:class="{ :class="{
'prepend-left-8': currentBranchId 'prepend-left-8': currentBranchId
}" }"
class="sidebar-context-title ide-sidebar-branch-title"
> >
<icon <icon
name="git-merge" name="git-merge"
......
...@@ -75,22 +75,22 @@ export default { ...@@ -75,22 +75,22 @@ export default {
<template> <template>
<footer class="ide-status-bar"> <footer class="ide-status-bar">
<div <div
class="ide-status-branch"
v-if="lastCommit && lastCommitFormatedAge" v-if="lastCommit && lastCommitFormatedAge"
class="ide-status-branch"
> >
<span <span
class="ide-status-pipeline"
v-if="latestPipeline && latestPipeline.details" v-if="latestPipeline && latestPipeline.details"
class="ide-status-pipeline"
> >
<ci-icon <ci-icon
:status="latestPipeline.details.status"
v-tooltip v-tooltip
:status="latestPipeline.details.status"
:title="latestPipeline.details.status.text" :title="latestPipeline.details.status.text"
/> />
Pipeline Pipeline
<a <a
class="monospace" :href="latestPipeline.details.status.details_path"
:href="latestPipeline.details.status.details_path">#{{ latestPipeline.id }}</a> class="monospace">#{{ latestPipeline.id }}</a>
{{ latestPipeline.details.status.text }} {{ latestPipeline.details.status.text }}
for for
</span> </span>
...@@ -100,18 +100,18 @@ export default { ...@@ -100,18 +100,18 @@ export default {
/> />
<a <a
v-tooltip v-tooltip
class="commit-sha"
:title="lastCommit.message" :title="lastCommit.message"
:href="getCommitPath(lastCommit.short_id)" :href="getCommitPath(lastCommit.short_id)"
class="commit-sha"
>{{ lastCommit.short_id }}</a> >{{ lastCommit.short_id }}</a>
by by
{{ lastCommit.author_name }} {{ lastCommit.author_name }}
<time <time
v-tooltip v-tooltip
data-placement="top"
data-container="body"
:datetime="lastCommit.committed_date" :datetime="lastCommit.committed_date"
:title="tooltipTitle(lastCommit.committed_date)" :title="tooltipTitle(lastCommit.committed_date)"
data-placement="top"
data-container="body"
> >
{{ lastCommitFormatedAge }} {{ lastCommitFormatedAge }}
</time> </time>
...@@ -129,8 +129,8 @@ export default { ...@@ -129,8 +129,8 @@ export default {
{{ file.eol }} {{ file.eol }}
</div> </div>
<div <div
class="ide-status-file" v-if="file && !file.binary"
v-if="file && !file.binary"> class="ide-status-file">
{{ file.editorRow }}:{{ file.editorColumn }} {{ file.editorRow }}:{{ file.editorColumn }}
</div> </div>
<div <div
......
...@@ -50,17 +50,17 @@ export default { ...@@ -50,17 +50,17 @@ export default {
> >
<template v-if="showLoading"> <template v-if="showLoading">
<div <div
class="multi-file-loading-container"
v-for="n in 3" v-for="n in 3"
:key="n" :key="n"
class="multi-file-loading-container"
> >
<skeleton-loading-container /> <skeleton-loading-container />
</div> </div>
</template> </template>
<template v-else> <template v-else>
<header <header
class="ide-tree-header"
:class="headerClass" :class="headerClass"
class="ide-tree-header"
> >
<slot name="header"></slot> <slot name="header"></slot>
</header> </header>
......
...@@ -93,10 +93,10 @@ export default { ...@@ -93,10 +93,10 @@ export default {
<a <a
v-tooltip v-tooltip
:title="__('Show complete raw log')" :title="__('Show complete raw log')"
:href="detailJob.rawPath"
data-placement="top" data-placement="top"
data-container="body" data-container="body"
class="controllers-buttons" class="controllers-buttons"
:href="detailJob.rawPath"
target="_blank" target="_blank"
> >
<i <i
...@@ -105,23 +105,24 @@ export default { ...@@ -105,23 +105,24 @@ export default {
></i> ></i>
</a> </a>
<scroll-button <scroll-button
direction="up"
:disabled="isScrolledToTop" :disabled="isScrolledToTop"
direction="up"
@click="scrollUp" @click="scrollUp"
/> />
<scroll-button <scroll-button
direction="down"
:disabled="isScrolledToBottom" :disabled="isScrolledToBottom"
direction="down"
@click="scrollDown" @click="scrollDown"
/> />
</div> </div>
</div> </div>
<pre <pre
class="build-trace mb-0 h-100"
ref="buildTrace" ref="buildTrace"
class="build-trace mb-0 h-100"
@scroll="scrollBuildLog" @scroll="scrollBuildLog"
> >
<code <code
v-show="!detailJob.isLoading"
class="bash" class="bash"
v-html="jobOutput" v-html="jobOutput"
> >
......
...@@ -24,10 +24,10 @@ export default { ...@@ -24,10 +24,10 @@ export default {
<template> <template>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<ci-icon <ci-icon
class="d-flex"
:status="job.status" :status="job.status"
:borderless="true" :borderless="true"
:size="24" :size="24"
class="d-flex"
/> />
<span class="prepend-left-8"> <span class="prepend-left-8">
{{ job.name }} {{ job.name }}
...@@ -38,8 +38,8 @@ export default { ...@@ -38,8 +38,8 @@ export default {
> >
{{ jobId }} {{ jobId }}
<icon <icon
name="external-link"
:size="12" :size="12"
name="external-link"
/> />
</a> </a>
</span> </span>
......
...@@ -47,15 +47,15 @@ export default { ...@@ -47,15 +47,15 @@ export default {
<template> <template>
<div <div
v-tooltip v-tooltip
:title="tooltipTitle"
class="controllers-buttons" class="controllers-buttons"
data-container="body" data-container="body"
data-placement="top" data-placement="top"
:title="tooltipTitle"
> >
<button <button
:disabled="disabled"
class="btn-scroll btn-transparent btn-blank" class="btn-scroll btn-transparent btn-blank"
type="button" type="button"
:disabled="disabled"
@click="clickedScroll" @click="clickedScroll"
> >
<icon <icon
......
...@@ -27,8 +27,8 @@ export default { ...@@ -27,8 +27,8 @@ export default {
<template> <template>
<div class="ide-job-item"> <div class="ide-job-item">
<job-description <job-description
class="append-right-default"
:job="job" :job="job"
class="append-right-default"
/> />
<div class="ml-auto align-self-center"> <div class="ml-auto align-self-center">
<button <button
......
...@@ -60,10 +60,10 @@ export default { ...@@ -60,10 +60,10 @@ export default {
class="ide-stage card prepend-top-default" class="ide-stage card prepend-top-default"
> >
<div <div
class="card-header"
:class="{ :class="{
'border-bottom-0': stage.isCollapsed 'border-bottom-0': stage.isCollapsed
}" }"
class="card-header"
@click="toggleCollapsed" @click="toggleCollapsed"
> >
<ci-icon <ci-icon
...@@ -72,10 +72,10 @@ export default { ...@@ -72,10 +72,10 @@ export default {
/> />
<strong <strong
v-tooltip="showTooltip" v-tooltip="showTooltip"
ref="stageTitle"
:title="showTooltip ? stage.name : null" :title="showTooltip ? stage.name : null"
data-container="body" data-container="body"
class="prepend-left-8 ide-stage-title" class="prepend-left-8 ide-stage-title"
ref="stageTitle"
> >
{{ stage.name }} {{ stage.name }}
</strong> </strong>
...@@ -93,8 +93,8 @@ export default { ...@@ -93,8 +93,8 @@ export default {
/> />
</div> </div>
<div <div
class="card-body"
v-show="!stage.isCollapsed" v-show="!stage.isCollapsed"
class="card-body"
> >
<loading-icon <loading-icon
v-if="showLoadingIcon" v-if="showLoadingIcon"
......
...@@ -42,8 +42,8 @@ export default { ...@@ -42,8 +42,8 @@ export default {
</span> </span>
</template> </template>
<list <list
type="created"
:empty-text="__('You have not created any merge requests')" :empty-text="__('You have not created any merge requests')"
type="created"
/> />
</tab> </tab>
<tab> <tab>
...@@ -54,8 +54,8 @@ export default { ...@@ -54,8 +54,8 @@ export default {
</span> </span>
</template> </template>
<list <list
type="assigned"
:empty-text="__('You do not have any assigned merge requests')" :empty-text="__('You do not have any assigned merge requests')"
type="assigned"
/> />
</tab> </tab>
</tabs> </tabs>
......
...@@ -47,8 +47,8 @@ export default { ...@@ -47,8 +47,8 @@ export default {
<span class="d-flex append-right-default ide-merge-request-current-icon"> <span class="d-flex append-right-default ide-merge-request-current-icon">
<icon <icon
v-if="isActive" v-if="isActive"
name="mobile-issue-close"
:size="18" :size="18"
name="mobile-issue-close"
/> />
</span> </span>
<span> <span>
......
...@@ -80,12 +80,12 @@ export default { ...@@ -80,12 +80,12 @@ export default {
<div> <div>
<div class="dropdown-input mt-3 pb-3 mb-0 border-bottom"> <div class="dropdown-input mt-3 pb-3 mb-0 border-bottom">
<input <input
type="search" ref="searchInput"
class="dropdown-input-field"
:placeholder="__('Search merge requests')" :placeholder="__('Search merge requests')"
v-model="search" v-model="search"
type="search"
class="dropdown-input-field"
@input="searchMergeRequests" @input="searchMergeRequests"
ref="searchInput"
/> />
<i <i
aria-hidden="true" aria-hidden="true"
...@@ -94,8 +94,8 @@ export default { ...@@ -94,8 +94,8 @@ export default {
</div> </div>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex"> <div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<loading-icon <loading-icon
class="mt-3 mb-3 align-self-center ml-auto mr-auto"
v-if="isLoading" v-if="isLoading"
class="mt-3 mb-3 align-self-center ml-auto mr-auto"
size="2" size="2"
/> />
<ul <ul
......
...@@ -14,10 +14,10 @@ export default { ...@@ -14,10 +14,10 @@ export default {
<template> <template>
<icon <icon
name="git-merge"
v-tooltip v-tooltip
:title="__('Part of merge request changes')" :title="__('Part of merge request changes')"
css-classes="append-right-8"
:size="12" :size="12"
name="git-merge"
css-classes="append-right-8"
/> />
</template> </template>
...@@ -55,10 +55,10 @@ export default { ...@@ -55,10 +55,10 @@ export default {
<template> <template>
<div class="ide-new-btn"> <div class="ide-new-btn">
<div <div
class="dropdown"
:class="{ :class="{
show: dropdownOpen, show: dropdownOpen,
}" }"
class="dropdown"
> >
<button <button
type="button" type="button"
...@@ -67,19 +67,19 @@ export default { ...@@ -67,19 +67,19 @@ export default {
@click.stop="openDropdown()" @click.stop="openDropdown()"
> >
<icon <icon
name="plus"
:size="12" :size="12"
name="plus"
css-classes="float-left" css-classes="float-left"
/> />
<icon <icon
name="arrow-down"
:size="12" :size="12"
name="arrow-down"
css-classes="float-left" css-classes="float-left"
/> />
</button> </button>
<ul <ul
class="dropdown-menu dropdown-menu-right"
ref="dropdownMenu" ref="dropdownMenu"
class="dropdown-menu dropdown-menu-right"
> >
<li> <li>
<a <a
......
...@@ -71,18 +71,18 @@ export default { ...@@ -71,18 +71,18 @@ export default {
> >
<form <form
slot="body" slot="body"
@submit.prevent="createEntryInStore"
class="form-group row" class="form-group row"
@submit.prevent="createEntryInStore"
> >
<label class="label-light col-form-label col-sm-3"> <label class="label-light col-form-label col-sm-3">
{{ __('Name') }} {{ __('Name') }}
</label> </label>
<div class="col-sm-9"> <div class="col-sm-9">
<input <input
ref="fieldName"
v-model="entryName"
type="text" type="text"
class="form-control" class="form-control"
v-model="entryName"
ref="fieldName"
/> />
</div> </div>
</form> </form>
......
...@@ -67,9 +67,9 @@ ...@@ -67,9 +67,9 @@
</a> </a>
<input <input
id="file-upload" id="file-upload"
ref="fileUpload"
type="file" type="file"
class="hidden" class="hidden"
ref="fileUpload"
/> />
</div> </div>
</template> </template>
...@@ -44,10 +44,10 @@ export default { ...@@ -44,10 +44,10 @@ export default {
> >
<resizable-panel <resizable-panel
v-if="rightPane" v-if="rightPane"
class="multi-file-commit-panel-inner"
:collapsible="false" :collapsible="false"
:initial-width="350" :initial-width="350"
:min-size="350" :min-size="350"
class="multi-file-commit-panel-inner"
side="right" side="right"
> >
<component :is="rightPane" /> <component :is="rightPane" />
...@@ -57,13 +57,13 @@ export default { ...@@ -57,13 +57,13 @@ export default {
<li> <li>
<button <button
v-tooltip v-tooltip
data-container="body"
data-placement="left"
:title="__('Pipelines')" :title="__('Pipelines')"
class="ide-sidebar-link is-right"
:class="{ :class="{
active: pipelinesActive active: pipelinesActive
}" }"
data-container="body"
data-placement="left"
class="ide-sidebar-link is-right"
type="button" type="button"
@click="clickTab($event, $options.rightSidebarViews.pipelines)" @click="clickTab($event, $options.rightSidebarViews.pipelines)"
> >
......
...@@ -75,8 +75,8 @@ export default { ...@@ -75,8 +75,8 @@ export default {
> >
#{{ latestPipeline.id }} #{{ latestPipeline.id }}
<icon <icon
name="external-link"
:size="12" :size="12"
name="external-link"
/> />
</a> </a>
</span> </span>
...@@ -94,7 +94,7 @@ export default { ...@@ -94,7 +94,7 @@ export default {
<p class="append-bottom-0"> <p class="append-bottom-0">
{{ __('Found errors in your .gitlab-ci.yml:') }} {{ __('Found errors in your .gitlab-ci.yml:') }}
</p> </p>
<p class="append-bottom-0"> <p class="append-bottom-0 break-word">
{{ latestPipeline.yamlError }} {{ latestPipeline.yamlError }}
</p> </p>
<p <p
......
...@@ -6,7 +6,7 @@ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue'; ...@@ -6,7 +6,7 @@ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import CommitFilesList from './commit_sidebar/list.vue'; import CommitFilesList from './commit_sidebar/list.vue';
import EmptyState from './commit_sidebar/empty_state.vue'; import EmptyState from './commit_sidebar/empty_state.vue';
import * as consts from '../stores/modules/commit/constants'; import * as consts from '../stores/modules/commit/constants';
import { activityBarViews } from '../constants'; import { activityBarViews, stageKeys } from '../constants';
export default { export default {
components: { components: {
...@@ -27,11 +27,14 @@ export default { ...@@ -27,11 +27,14 @@ export default {
'unusedSeal', 'unusedSeal',
]), ]),
...mapState('commit', ['commitMessage', 'submitCommitLoading']), ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommitedChanges']), ...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommitedChanges', 'activeFile']),
...mapGetters('commit', ['commitButtonDisabled', 'discardDraftButtonDisabled']), ...mapGetters('commit', ['commitButtonDisabled', 'discardDraftButtonDisabled']),
showStageUnstageArea() { showStageUnstageArea() {
return !!(this.someUncommitedChanges || this.lastCommitMsg || !this.unusedSeal); return !!(this.someUncommitedChanges || this.lastCommitMsg || !this.unusedSeal);
}, },
activeFileKey() {
return this.activeFile ? this.activeFile.key : null;
},
}, },
watch: { watch: {
hasChanges() { hasChanges() {
...@@ -44,6 +47,7 @@ export default { ...@@ -44,6 +47,7 @@ export default {
if (this.lastOpenedFile) { if (this.lastOpenedFile) {
this.openPendingTab({ this.openPendingTab({
file: this.lastOpenedFile, file: this.lastOpenedFile,
keyPrefix: this.lastOpenedFile.changed ? stageKeys.unstaged : stageKeys.staged,
}) })
.then(changeViewer => { .then(changeViewer => {
if (changeViewer) { if (changeViewer) {
...@@ -62,6 +66,7 @@ export default { ...@@ -62,6 +66,7 @@ export default {
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commitChanges()); return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commitChanges());
}, },
}, },
stageKeys,
}; };
</script> </script>
...@@ -72,8 +77,8 @@ export default { ...@@ -72,8 +77,8 @@ export default {
<deprecated-modal <deprecated-modal
id="ide-create-branch-modal" id="ide-create-branch-modal"
:primary-button-label="__('Create new branch')" :primary-button-label="__('Create new branch')"
kind="success"
:title="__('Branch has changed')" :title="__('Branch has changed')"
kind="success"
@submit="forceCreateNewBranch" @submit="forceCreateNewBranch"
> >
<template slot="body"> <template slot="body">
...@@ -85,22 +90,26 @@ export default { ...@@ -85,22 +90,26 @@ export default {
v-if="showStageUnstageArea" v-if="showStageUnstageArea"
> >
<commit-files-list <commit-files-list
class="is-first"
icon-name="unstaged"
:title="__('Unstaged')" :title="__('Unstaged')"
:key-prefix="$options.stageKeys.unstaged"
:file-list="changedFiles" :file-list="changedFiles"
action="stageAllChanges"
:action-btn-text="__('Stage all')" :action-btn-text="__('Stage all')"
:active-file-key="activeFileKey"
class="is-first"
icon-name="unstaged"
action="stageAllChanges"
item-action-component="stage-button" item-action-component="stage-button"
/> />
<commit-files-list <commit-files-list
icon-name="staged"
:title="__('Staged')" :title="__('Staged')"
:key-prefix="$options.stageKeys.staged"
:file-list="stagedFiles" :file-list="stagedFiles"
action="unstageAllChanges"
:action-btn-text="__('Unstage all')" :action-btn-text="__('Unstage all')"
item-action-component="unstage-button"
:staged-list="true" :staged-list="true"
:active-file-key="activeFileKey"
icon-name="staged"
action="unstageAllChanges"
item-action-component="unstage-button"
/> />
</template> </template>
<empty-state <empty-state
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import flash from '~/flash'; import flash from '~/flash';
import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue'; import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import { activityBarViews, viewerTypes } from '../constants'; import { activityBarViews, viewerTypes } from '../constants';
import Editor from '../lib/editor'; import Editor from '../lib/editor';
import ExternalLink from './external_link.vue'; import ExternalLink from './external_link.vue';
...@@ -9,6 +10,7 @@ import ExternalLink from './external_link.vue'; ...@@ -9,6 +10,7 @@ import ExternalLink from './external_link.vue';
export default { export default {
components: { components: {
ContentViewer, ContentViewer,
DiffViewer,
ExternalLink, ExternalLink,
}, },
props: { props: {
...@@ -18,7 +20,13 @@ export default { ...@@ -18,7 +20,13 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['rightPanelCollapsed', 'viewer', 'panelResizing', 'currentActivityView']), ...mapState([
'rightPanelCollapsed',
'viewer',
'panelResizing',
'currentActivityView',
'rightPane',
]),
...mapGetters([ ...mapGetters([
'currentMergeRequest', 'currentMergeRequest',
'getStagedFile', 'getStagedFile',
...@@ -29,9 +37,18 @@ export default { ...@@ -29,9 +37,18 @@ export default {
shouldHideEditor() { shouldHideEditor() {
return this.file && this.file.binary && !this.file.content; return this.file && this.file.binary && !this.file.content;
}, },
showContentViewer() {
return (
(this.shouldHideEditor || this.file.viewMode === 'preview') &&
(this.viewer !== viewerTypes.mr || !this.file.mrChange)
);
},
showDiffViewer() {
return this.shouldHideEditor && this.file.mrChange && this.viewer === viewerTypes.mr;
},
editTabCSS() { editTabCSS() {
return { return {
active: this.file.viewMode === 'edit', active: this.file.viewMode === 'editor',
}; };
}, },
previewTabCSS() { previewTabCSS() {
...@@ -53,7 +70,7 @@ export default { ...@@ -53,7 +70,7 @@ export default {
if (this.currentActivityView !== activityBarViews.edit) { if (this.currentActivityView !== activityBarViews.edit) {
this.setFileViewMode({ this.setFileViewMode({
file: this.file, file: this.file,
viewMode: 'edit', viewMode: 'editor',
}); });
} }
} }
...@@ -62,7 +79,7 @@ export default { ...@@ -62,7 +79,7 @@ export default {
if (this.currentActivityView !== activityBarViews.edit) { if (this.currentActivityView !== activityBarViews.edit) {
this.setFileViewMode({ this.setFileViewMode({
file: this.file, file: this.file,
viewMode: 'edit', viewMode: 'editor',
}); });
} }
}, },
...@@ -77,6 +94,9 @@ export default { ...@@ -77,6 +94,9 @@ export default {
this.editor.updateDimensions(); this.editor.updateDimensions();
} }
}, },
rightPane() {
this.editor.updateDimensions();
},
}, },
beforeDestroy() { beforeDestroy() {
this.editor.dispose(); this.editor.dispose();
...@@ -190,14 +210,14 @@ export default { ...@@ -190,14 +210,14 @@ export default {
> >
<div class="ide-mode-tabs clearfix" > <div class="ide-mode-tabs clearfix" >
<ul <ul
class="nav-links float-left"
v-if="!shouldHideEditor && isEditModeActive" v-if="!shouldHideEditor && isEditModeActive"
class="nav-links float-left"
> >
<li :class="editTabCSS"> <li :class="editTabCSS">
<a <a
href="javascript:void(0);" href="javascript:void(0);"
role="button" role="button"
@click.prevent="setFileViewMode({ file, viewMode: 'edit' })"> @click.prevent="setFileViewMode({ file, viewMode: 'editor' })">
<template v-if="viewer === $options.viewerTypes.edit"> <template v-if="viewer === $options.viewerTypes.edit">
{{ __('Edit') }} {{ __('Edit') }}
</template> </template>
...@@ -222,19 +242,27 @@ export default { ...@@ -222,19 +242,27 @@ export default {
/> />
</div> </div>
<div <div
v-show="!shouldHideEditor && file.viewMode === 'edit'" v-show="!shouldHideEditor && file.viewMode ==='editor'"
ref="editor" ref="editor"
class="multi-file-editor-holder"
:class="{ :class="{
'is-readonly': isCommitModeActive, 'is-readonly': isCommitModeActive,
}" }"
class="multi-file-editor-holder"
> >
</div> </div>
<content-viewer <content-viewer
v-if="shouldHideEditor || file.viewMode === 'preview'" v-if="showContentViewer"
:content="file.content || file.raw" :content="file.content || file.raw"
:path="file.rawPath || file.path" :path="file.rawPath || file.path"
:file-size="file.size" :file-size="file.size"
:project-path="file.projectId"/> :project-path="file.projectId"/>
<diff-viewer
v-if="showDiffViewer"
:diff-mode="file.mrChange.diffMode"
:new-path="file.mrChange.new_path"
:new-sha="currentMergeRequest.sha"
:old-path="file.mrChange.old_path"
:old-sha="currentMergeRequest.baseCommitSha"
:project-path="file.projectId"/>
</div> </div>
</template> </template>
...@@ -120,17 +120,17 @@ export default { ...@@ -120,17 +120,17 @@ export default {
<template> <template>
<div> <div>
<div <div
class="file"
:class="fileClass" :class="fileClass"
@click="clickFile" class="file"
role="button" role="button"
@click="clickFile"
> >
<div <div
class="file-name" class="file-name"
> >
<span <span
class="ide-file-name str-truncated"
:style="levelIndentation" :style="levelIndentation"
class="ide-file-name str-truncated"
> >
<file-icon <file-icon
:file-name="file.name" :file-name="file.name"
...@@ -156,10 +156,10 @@ export default { ...@@ -156,10 +156,10 @@ export default {
<icon <icon
v-tooltip v-tooltip
:title="folderChangesTooltip" :title="folderChangesTooltip"
:size="12"
data-container="body" data-container="body"
data-placement="right" data-placement="right"
name="file-modified" name="file-modified"
:size="12"
css-classes="prepend-left-5 multi-file-modified" css-classes="prepend-left-5 multi-file-modified"
/> />
</span> </span>
......
...@@ -26,8 +26,8 @@ export default { ...@@ -26,8 +26,8 @@ export default {
<template> <template>
<span <span
v-if="file.file_lock"
v-tooltip v-tooltip
v-if="file.file_lock"
:title="lockTooltip" :title="lockTooltip"
data-container="body" data-container="body"
> >
......
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
<td class="d-none d-sm-block"> <td class="d-none d-sm-block">
<skeleton-loading-container <skeleton-loading-container
class="animation-container-right"
:small="true" :small="true"
class="animation-container-right"
/> />
</td> </td>
</template> </template>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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