summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2018-07-31 08:57:00 -0700
committerStan Hu <stanhu@gmail.com>2018-07-31 08:57:00 -0700
commitfe16ce0acb9b69b1b18afc009df8d63f7648b05e (patch)
tree7d755c3a76cd64b1d901f4bb272e9145f0bce841 /app/assets
parent3cda8c93d879282af2ab5b21ca2d89daf0238f17 (diff)
parent1a95603510accdcdb233fa00f101da119eb1fa5c (diff)
downloadgitlab-ce-fe16ce0acb9b69b1b18afc009df8d63f7648b05e.tar.gz
Merge branch 'master' into sh-support-bitbucket-server-import
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/boards/components/board.js13
-rw-r--r--app/assets/javascripts/boards/models/list.js2
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js10
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue7
-rw-r--r--app/assets/javascripts/diffs/store/getters.js8
-rw-r--r--app/assets/javascripts/ide/components/ide.vue24
-rw-r--r--app/assets/javascripts/lib/utils/http_status.js27
-rw-r--r--app/assets/javascripts/lib/utils/poll.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue15
-rw-r--r--app/assets/stylesheets/framework/typography.scss2
-rw-r--r--app/assets/stylesheets/pages/boards.scss2
-rw-r--r--app/assets/stylesheets/pages/issues/issue_count_badge.scss26
12 files changed, 98 insertions, 42 deletions
diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js
index a2355d7fd5c..9ad451fa375 100644
--- a/app/assets/javascripts/boards/components/board.js
+++ b/app/assets/javascripts/boards/components/board.js
@@ -2,6 +2,9 @@
import Sortable from 'sortablejs';
import Vue from 'vue';
+import { n__ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+import Tooltip from '~/vue_shared/directives/tooltip';
import AccessorUtilities from '../../lib/utils/accessor';
import boardList from './board_list.vue';
import BoardBlankState from './board_blank_state.vue';
@@ -17,6 +20,10 @@ gl.issueBoards.Board = Vue.extend({
boardList,
'board-delete': gl.issueBoards.BoardDelete,
BoardBlankState,
+ Icon,
+ },
+ directives: {
+ Tooltip,
},
props: {
list: {
@@ -46,6 +53,12 @@ gl.issueBoards.Board = Vue.extend({
filter: Store.filter,
};
},
+ computed: {
+ counterTooltip() {
+ const { issuesSize } = this.list;
+ return `${n__('%d issue', '%d issues', issuesSize)}`;
+ },
+ },
watch: {
filter: {
handler() {
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index 4f05a0e4282..050cbd8db48 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -136,6 +136,8 @@ class List {
}
this.createIssues(data.issues);
+
+ return data;
});
}
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 333338489bc..76467564608 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -125,11 +125,17 @@ gl.issueBoards.BoardsStore = {
} else if (listTo.type === 'backlog' && listFrom.type === 'assignee') {
issue.removeAssignee(listFrom.assignee);
listFrom.removeIssue(issue);
- } else if ((listTo.type !== 'label' && listFrom.type === 'assignee') ||
- (listTo.type !== 'assignee' && listFrom.type === 'label')) {
+ } else if (this.shouldRemoveIssue(listFrom, listTo)) {
listFrom.removeIssue(issue);
}
},
+ shouldRemoveIssue(listFrom, listTo) {
+ return (
+ (listTo.type !== 'label' && listFrom.type === 'assignee') ||
+ (listTo.type !== 'assignee' && listFrom.type === 'label') ||
+ (listFrom.type === 'backlog')
+ );
+ },
moveIssueInList (list, issue, oldIndex, newIndex, idArray) {
const beforeId = parseInt(idArray[newIndex - 1], 10) || null;
const afterId = parseInt(idArray[newIndex + 1], 10) || null;
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index c494d3bcd3e..d3ffbe0415a 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -50,7 +50,7 @@ export default {
};
},
computed: {
- ...mapGetters('diffs', ['diffHasExpandedDiscussions']),
+ ...mapGetters('diffs', ['diffHasExpandedDiscussions', 'diffHasDiscussions']),
hasExpandedDiscussions() {
return this.diffHasExpandedDiscussions(this.diffFile);
},
@@ -108,6 +108,9 @@ export default {
false,
);
},
+ gfmCopyText() {
+ return `\`${this.diffFile.filePath}\``;
+ },
},
methods: {
...mapActions('diffs', ['toggleFileDiscussions']),
@@ -191,6 +194,7 @@ export default {
<clipboard-button
:title="__('Copy file path to clipboard')"
:text="diffFile.filePath"
+ :gfm="gfmCopyText"
css-class="btn-default btn-transparent btn-clipboard"
/>
@@ -217,6 +221,7 @@ export default {
v-if="diffFile.blob && diffFile.blob.readableText"
>
<button
+ :disabled="!diffHasDiscussions(diffFile)"
:class="{ active: hasExpandedDiscussions }"
:title="s__('MergeRequests|Toggle comments for this file')"
class="js-btn-vue-toggle-comments btn"
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index c7b9b1a16e6..fc1d15b8d54 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -48,6 +48,14 @@ export const diffHasExpandedDiscussions = (state, getters) => diff => {
};
/**
+ * Checks if the diff has any discussion
+ * @param {Boolean} diff
+ * @returns {Boolean}
+ */
+export const diffHasDiscussions = (state, getters) => diff =>
+ getters.getDiffFileDiscussions(diff).length > 0;
+
+/**
* Returns an array with the discussions of the given diff
* @param {Object} diff
* @returns {Array}
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 257a7432c20..2c8305aa0cc 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,6 +1,7 @@
<script>
import Mousetrap from 'mousetrap';
import { mapActions, mapState, mapGetters } from 'vuex';
+import { __ } from '~/locale';
import NewModal from './new_dropdown/modal.vue';
import IdeSidebar from './ide_side_bar.vue';
import RepoTabs from './repo_tabs.vue';
@@ -25,7 +26,6 @@ export default {
},
computed: {
...mapState([
- 'changedFiles',
'openFiles',
'viewer',
'currentMergeRequestId',
@@ -34,18 +34,10 @@ export default {
'currentProjectId',
'errorMessage',
]),
- ...mapGetters(['activeFile', 'hasChanges']),
+ ...mapGetters(['activeFile', 'hasChanges', 'someUncommitedChanges']),
},
mounted() {
- const returnValue = 'Are you sure you want to lose unsaved changes?';
- window.onbeforeunload = e => {
- if (!this.changedFiles.length) return undefined;
-
- Object.assign(e, {
- returnValue,
- });
- return returnValue;
- };
+ window.onbeforeunload = e => this.onBeforeUnload(e);
Mousetrap.bind(['t', 'command+p', 'ctrl+p'], e => {
if (e.preventDefault) {
@@ -59,6 +51,16 @@ export default {
},
methods: {
...mapActions(['toggleFileFinder']),
+ onBeforeUnload(e = {}) {
+ const returnValue = __('Are you sure you want to lose unsaved changes?');
+
+ if (!this.someUncommitedChanges) return undefined;
+
+ Object.assign(e, {
+ returnValue,
+ });
+ return returnValue;
+ },
mousetrapStopCallback(e, el, combo) {
if (
(combo === 't' && el.classList.contains('dropdown-input-field')) ||
diff --git a/app/assets/javascripts/lib/utils/http_status.js b/app/assets/javascripts/lib/utils/http_status.js
index 229d53b18b0..e4852c85378 100644
--- a/app/assets/javascripts/lib/utils/http_status.js
+++ b/app/assets/javascripts/lib/utils/http_status.js
@@ -2,11 +2,34 @@
* exports HTTP status codes
*/
-export default {
+const httpStatusCodes = {
ABORTED: 0,
- NO_CONTENT: 204,
OK: 200,
+ CREATED: 201,
+ ACCEPTED: 202,
+ NON_AUTHORITATIVE_INFORMATION: 203,
+ NO_CONTENT: 204,
+ RESET_CONTENT: 205,
+ PARTIAL_CONTENT: 206,
+ MULTI_STATUS: 207,
+ ALREADY_REPORTED: 208,
+ IM_USED: 226,
MULTIPLE_CHOICES: 300,
BAD_REQUEST: 400,
NOT_FOUND: 404,
};
+
+export const successCodes = [
+ httpStatusCodes.OK,
+ httpStatusCodes.CREATED,
+ httpStatusCodes.ACCEPTED,
+ httpStatusCodes.NON_AUTHORITATIVE_INFORMATION,
+ httpStatusCodes.NO_CONTENT,
+ httpStatusCodes.RESET_CONTENT,
+ httpStatusCodes.PARTIAL_CONTENT,
+ httpStatusCodes.MULTI_STATUS,
+ httpStatusCodes.ALREADY_REPORTED,
+ httpStatusCodes.IM_USED,
+];
+
+export default httpStatusCodes;
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 91d8c30744f..04a6948f1f1 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -1,4 +1,4 @@
-import httpStatusCodes from './http_status';
+import httpStatusCodes, { successCodes } from './http_status';
import { normalizeHeaders } from './common_utils';
/**
@@ -62,7 +62,7 @@ export default class Poll {
checkConditions(response) {
const headers = normalizeHeaders(response.headers);
const pollInterval = parseInt(headers[this.intervalHeader], 10);
- if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) {
+ if (pollInterval > 0 && successCodes.indexOf(response.status) !== -1 && this.canPoll) {
clearTimeout(this.timeoutID);
this.timeoutID = setTimeout(() => {
this.makeRequest();
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index d272bf3f55f..945a33d9622 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -31,6 +31,11 @@ export default {
type: String,
required: true,
},
+ gfm: {
+ type: String,
+ required: false,
+ default: null,
+ },
title: {
type: String,
required: true,
@@ -51,6 +56,14 @@ export default {
default: 'btn-default',
},
},
+ computed: {
+ clipboardText() {
+ if (this.gfm !== null) {
+ return JSON.stringify({ text: this.text, gfm: this.gfm });
+ }
+ return this.text;
+ },
+ },
};
</script>
@@ -59,7 +72,7 @@ export default {
v-tooltip
:class="cssClass"
:title="title"
- :data-clipboard-text="text"
+ :data-clipboard-text="clipboardText"
:data-container="tooltipContainer"
:data-placement="tooltipPlacement"
type="button"
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index a2789021ab4..473ca408c04 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -444,3 +444,5 @@ textarea {
color: $placeholder-text-color;
}
}
+
+.lh-100 { line-height: 1; }
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 7347da2ae61..a68b47b1d02 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -205,7 +205,7 @@
.board-title {
margin: 0;
- padding: 12px $gl-padding;
+ padding: $gl-padding-8 $gl-padding;
font-size: 1em;
border-bottom: 1px solid $border-color;
display: flex;
diff --git a/app/assets/stylesheets/pages/issues/issue_count_badge.scss b/app/assets/stylesheets/pages/issues/issue_count_badge.scss
index ccb62bfed18..4fba89e956b 100644
--- a/app/assets/stylesheets/pages/issues/issue_count_badge.scss
+++ b/app/assets/stylesheets/pages/issues/issue_count_badge.scss
@@ -1,29 +1,11 @@
.issue-count-badge {
display: inline-flex;
- align-items: stretch;
- height: 24px;
-}
-
-.issue-count-badge-count {
- display: flex;
- align-items: center;
- padding-right: 10px;
- padding-left: 10px;
- border: 1px solid $border-color;
border-radius: $border-radius-base;
- line-height: 1;
-
- &.has-btn {
- border-right: 0;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- }
+ border: 1px solid $border-color;
+ padding: 5px $gl-padding-8;
}
-.issue-count-badge-add-button {
- display: flex;
+.issue-count-badge-count {
+ display: inline-flex;
align-items: center;
- border: 1px solid $border-color;
- border-radius: 0 $border-radius-base $border-radius-base 0;
- line-height: 1;
}