Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2017-11-06 16:44:57 +0300
committerLin Jen-Shin <godfat@godfat.org>2017-11-06 16:44:57 +0300
commitfc6aad0b4442c58fde1ac924cb2dd73823273537 (patch)
tree3f4a46a5b649cf623ab5e8e42eaa2e06cb2b20cf /app/assets/javascripts/sidebar/components
parent239332eed3fa870fd41be83864882c0f389840d8 (diff)
parentcfc932cad10b1d6c494222e9d91aa75583b56145 (diff)
Merge remote-tracking branch 'upstream/master' into no-ivar-in-modules
* upstream/master: (1723 commits) Resolve "Editor icons" Refactor issuable destroy action Ignore routes matching legacy_*_redirect in route specs Gitlab::Git::RevList and LfsChanges use lazy popen Gitlab::Git::Popen can lazily hand output to a block Merge branch 'master-i18n' into 'master' Remove unique validation from external_url in Environment Expose `duration` in Job API entity Add TimeCop freeze for DST and Regular time Harcode project visibility update a changelog Put a condition to old migration that adds fast_forward column to MRs Expose project visibility as CI variable fix flaky tests by removing unneeded clicks and focus actions fix flaky test in gfm_autocomplete_spec.rb Use Gitlab::Git operations for repository mirroring Encapsulate git operations for mirroring in Gitlab::Git Create a Wiki Repository's raw_repository properly Add `Gitlab::Git::Repository#fetch` command Fix Gitlab::Metrics::System#real_time and #monotonic_time doc ...
Diffstat (limited to 'app/assets/javascripts/sidebar/components')
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js3
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue16
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form.vue9
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form.vue61
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue50
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue120
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue125
-rw-r--r--app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue26
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue45
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue60
11 files changed, 504 insertions, 17 deletions
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
index f83c3b037ed..74c17bc14a2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
@@ -1,5 +1,4 @@
-/* global Flash */
-
+import Flash from '../../../flash';
import AssigneeTitle from './assignee_title';
import Assignees from './assignees';
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 8e7abdbffef..22a9a34dda3 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -1,5 +1,5 @@
<script>
-/* global Flash */
+import Flash from '../../../flash';
import editForm from './edit_form.vue';
export default {
@@ -47,9 +47,9 @@ export default {
</script>
<template>
- <div class="block confidentiality">
+ <div class="block issuable-sidebar-item confidentiality">
<div class="sidebar-collapsed-icon">
- <i class="fa" :class="faEye" aria-hidden="true" data-hidden="true"></i>
+ <i class="fa" :class="faEye" aria-hidden="true"></i>
</div>
<div class="title hide-collapsed">
Confidentiality
@@ -62,19 +62,19 @@ export default {
Edit
</a>
</div>
- <div class="value confidential-value hide-collapsed">
+ <div class="value sidebar-item-value hide-collapsed">
<editForm
v-if="edit"
:toggle-form="toggleForm"
:is-confidential="isConfidential"
:update-confidential-attribute="updateConfidentialAttribute"
/>
- <div v-if="!isConfidential" class="no-value confidential-value">
- <i class="fa fa-eye is-not-confidential"></i>
+ <div v-if="!isConfidential" class="no-value sidebar-item-value">
+ <i class="fa fa-eye sidebar-item-icon"></i>
Not confidential
</div>
- <div v-else class="value confidential-value hide-collapsed">
- <i aria-hidden="true" data-hidden="true" class="fa fa-eye-slash is-confidential"></i>
+ <div v-else class="value sidebar-item-value hide-collapsed">
+ <i aria-hidden="true" class="fa fa-eye-slash sidebar-item-icon is-active"></i>
This issue is confidential
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
index d578b663a54..dd17b5abd46 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
@@ -2,9 +2,6 @@
import editFormButtons from './edit_form_buttons.vue';
export default {
- components: {
- editFormButtons,
- },
props: {
isConfidential: {
required: true,
@@ -19,12 +16,16 @@ export default {
type: Function,
},
},
+
+ components: {
+ editFormButtons,
+ },
};
</script>
<template>
<div class="dropdown open">
- <div class="dropdown-menu confidential-warning-message">
+ <div class="dropdown-menu sidebar-item-warning-message">
<div>
<p v-if="!isConfidential">
You are going to turn on the confidentiality. This means that only team members with
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index 97af4a3f505..7ed0619ee6b 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -15,7 +15,7 @@ export default {
},
},
computed: {
- onOrOff() {
+ toggleButtonText() {
return this.isConfidential ? 'Turn Off' : 'Turn On';
},
updateConfidentialBool() {
@@ -26,7 +26,7 @@ export default {
</script>
<template>
- <div class="confidential-warning-message-actions">
+ <div class="sidebar-item-warning-message-actions">
<button
type="button"
class="btn btn-default append-right-10"
@@ -39,7 +39,7 @@ export default {
class="btn btn-close"
@click.prevent="updateConfidentialAttribute(updateConfidentialBool)"
>
- {{ onOrOff }}
+ {{ toggleButtonText }}
</button>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form.vue b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
new file mode 100644
index 00000000000..c7a6edc7c70
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
@@ -0,0 +1,61 @@
+<script>
+import editFormButtons from './edit_form_buttons.vue';
+import issuableMixin from '../../../vue_shared/mixins/issuable';
+
+export default {
+ props: {
+ isLocked: {
+ required: true,
+ type: Boolean,
+ },
+
+ toggleForm: {
+ required: true,
+ type: Function,
+ },
+
+ updateLockedAttribute: {
+ required: true,
+ type: Function,
+ },
+
+ issuableType: {
+ required: true,
+ type: String,
+ },
+ },
+
+ mixins: [
+ issuableMixin,
+ ],
+
+ components: {
+ editFormButtons,
+ },
+};
+</script>
+
+<template>
+ <div class="dropdown open">
+ <div class="dropdown-menu sidebar-item-warning-message">
+ <p class="text" v-if="isLocked">
+ Unlock this {{ issuableDisplayName(issuableType) }}?
+ <strong>Everyone</strong>
+ will be able to comment.
+ </p>
+
+ <p class="text" v-else>
+ Lock this {{ issuableDisplayName(issuableType) }}?
+ Only
+ <strong>project members</strong>
+ will be able to comment.
+ </p>
+
+ <edit-form-buttons
+ :is-locked="isLocked"
+ :toggle-form="toggleForm"
+ :update-locked-attribute="updateLockedAttribute"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
new file mode 100644
index 00000000000..c3a553a7605
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -0,0 +1,50 @@
+<script>
+export default {
+ props: {
+ isLocked: {
+ required: true,
+ type: Boolean,
+ },
+
+ toggleForm: {
+ required: true,
+ type: Function,
+ },
+
+ updateLockedAttribute: {
+ required: true,
+ type: Function,
+ },
+ },
+
+ computed: {
+ buttonText() {
+ return this.isLocked ? this.__('Unlock') : this.__('Lock');
+ },
+
+ toggleLock() {
+ return !this.isLocked;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="sidebar-item-warning-message-actions">
+ <button
+ type="button"
+ class="btn btn-default append-right-10"
+ @click="toggleForm"
+ >
+ {{ __('Cancel') }}
+ </button>
+
+ <button
+ type="button"
+ class="btn btn-close"
+ @click.prevent="updateLockedAttribute(toggleLock)"
+ >
+ {{ buttonText }}
+ </button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
new file mode 100644
index 00000000000..c4b2900e020
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -0,0 +1,120 @@
+<script>
+/* global Flash */
+import editForm from './edit_form.vue';
+import issuableMixin from '../../../vue_shared/mixins/issuable';
+
+export default {
+ props: {
+ isLocked: {
+ required: true,
+ type: Boolean,
+ },
+
+ isEditable: {
+ required: true,
+ type: Boolean,
+ },
+
+ mediator: {
+ required: true,
+ type: Object,
+ validator(mediatorObject) {
+ return mediatorObject.service && mediatorObject.service.update && mediatorObject.store;
+ },
+ },
+
+ issuableType: {
+ required: true,
+ type: String,
+ },
+ },
+
+ mixins: [
+ issuableMixin,
+ ],
+
+ components: {
+ editForm,
+ },
+
+ computed: {
+ lockIconClass() {
+ return this.isLocked ? 'fa-lock' : 'fa-unlock';
+ },
+
+ isLockDialogOpen() {
+ return this.mediator.store.isLockDialogOpen;
+ },
+ },
+
+ methods: {
+ toggleForm() {
+ this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
+ },
+
+ updateLockedAttribute(locked) {
+ this.mediator.service.update(this.issuableType, {
+ discussion_locked: locked,
+ })
+ .then(() => location.reload())
+ .catch(() => Flash(this.__(`Something went wrong trying to change the locked state of this ${this.issuableDisplayName(this.issuableType)}`)));
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="block issuable-sidebar-item lock">
+ <div class="sidebar-collapsed-icon">
+ <i
+ class="fa"
+ :class="lockIconClass"
+ aria-hidden="true"
+ ></i>
+ </div>
+
+ <div class="title hide-collapsed">
+ Lock {{issuableDisplayName(issuableType) }}
+ <button
+ v-if="isEditable"
+ class="pull-right lock-edit btn btn-blank"
+ type="button"
+ @click.prevent="toggleForm"
+ >
+ {{ __('Edit') }}
+ </button>
+ </div>
+
+ <div class="value sidebar-item-value hide-collapsed">
+ <edit-form
+ v-if="isLockDialogOpen"
+ :toggle-form="toggleForm"
+ :is-locked="isLocked"
+ :update-locked-attribute="updateLockedAttribute"
+ :issuable-type="issuableType"
+ />
+
+ <div
+ v-if="isLocked"
+ class="value sidebar-item-value"
+ >
+ <i
+ aria-hidden="true"
+ class="fa fa-lock sidebar-item-icon is-active"
+ ></i>
+ {{ __('Locked') }}
+ </div>
+
+ <div
+ v-else
+ class="no-value sidebar-item-value hide-collapsed"
+ >
+ <i
+ aria-hidden="true"
+ class="fa fa-unlock sidebar-item-icon"
+ ></i>
+ {{ __('Unlocked') }}
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
new file mode 100644
index 00000000000..b8510a6ce3a
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -0,0 +1,125 @@
+<script>
+import { __, n__, sprintf } from '../../../locale';
+import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
+import userAvatarImage from '../../../vue_shared/components/user_avatar/user_avatar_image.vue';
+
+export default {
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ participants: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ numberOfLessParticipants: {
+ type: Number,
+ required: false,
+ default: 7,
+ },
+ },
+ data() {
+ return {
+ isShowingMoreParticipants: false,
+ };
+ },
+ components: {
+ loadingIcon,
+ userAvatarImage,
+ },
+ computed: {
+ lessParticipants() {
+ return this.participants.slice(0, this.numberOfLessParticipants);
+ },
+ visibleParticipants() {
+ return this.isShowingMoreParticipants ? this.participants : this.lessParticipants;
+ },
+ hasMoreParticipants() {
+ return this.participants.length > this.numberOfLessParticipants;
+ },
+ toggleLabel() {
+ let label = '';
+ if (this.isShowingMoreParticipants) {
+ label = __('- show less');
+ } else {
+ label = sprintf(__('+ %{moreCount} more'), {
+ moreCount: this.participants.length - this.numberOfLessParticipants,
+ });
+ }
+
+ return label;
+ },
+ participantLabel() {
+ return sprintf(
+ n__('%{count} participant', '%{count} participants', this.participants.length),
+ { count: this.loading ? '' : this.participantCount },
+ );
+ },
+ participantCount() {
+ return this.participants.length;
+ },
+ },
+ methods: {
+ toggleMoreParticipants() {
+ this.isShowingMoreParticipants = !this.isShowingMoreParticipants;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="sidebar-collapsed-icon">
+ <i
+ class="fa fa-users"
+ aria-hidden="true">
+ </i>
+ <loading-icon
+ v-if="loading"
+ class="js-participants-collapsed-loading-icon" />
+ <span
+ v-else
+ class="js-participants-collapsed-count">
+ {{ participantCount }}
+ </span>
+ </div>
+ <div class="title hide-collapsed">
+ <loading-icon
+ v-if="loading"
+ :inline="true"
+ class="js-participants-expanded-loading-icon" />
+ {{ participantLabel }}
+ </div>
+ <div class="participants-list hide-collapsed">
+ <div
+ v-for="participant in visibleParticipants"
+ :key="participant.id"
+ class="participants-author js-participants-author">
+ <a
+ class="author_link"
+ :href="participant.web_url">
+ <user-avatar-image
+ :lazy="true"
+ :img-src="participant.avatar_url"
+ css-classes="avatar-inline"
+ :size="24"
+ :tooltip-text="participant.name"
+ tooltip-placement="bottom" />
+ </a>
+ </div>
+ </div>
+ <div
+ v-if="hasMoreParticipants"
+ class="participants-more hide-collapsed">
+ <button
+ type="button"
+ class="btn-transparent btn-blank js-toggle-participants-button"
+ @click="toggleMoreParticipants">
+ {{ toggleLabel }}
+ </button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue b/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
new file mode 100644
index 00000000000..c1296b28db7
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
@@ -0,0 +1,26 @@
+<script>
+import Store from '../../stores/sidebar_store';
+import Mediator from '../../sidebar_mediator';
+import participants from './participants.vue';
+
+export default {
+ data() {
+ return {
+ mediator: new Mediator(),
+ store: new Store(),
+ };
+ },
+ components: {
+ participants,
+ },
+};
+</script>
+
+<template>
+ <div class="block participants">
+ <participants
+ :loading="store.isFetching.participants"
+ :participants="store.participants"
+ :number-of-less-participants="7" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
new file mode 100644
index 00000000000..4ad3d469f25
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
@@ -0,0 +1,45 @@
+<script>
+import Store from '../../stores/sidebar_store';
+import Mediator from '../../sidebar_mediator';
+import eventHub from '../../event_hub';
+import Flash from '../../../flash';
+import subscriptions from './subscriptions.vue';
+
+export default {
+ data() {
+ return {
+ mediator: new Mediator(),
+ store: new Store(),
+ };
+ },
+
+ components: {
+ subscriptions,
+ },
+
+ methods: {
+ onToggleSubscription() {
+ this.mediator.toggleSubscription()
+ .catch(() => {
+ Flash('Error occurred when toggling the notification subscription');
+ });
+ },
+ },
+
+ created() {
+ eventHub.$on('toggleSubscription', this.onToggleSubscription);
+ },
+
+ beforeDestroy() {
+ eventHub.$off('toggleSubscription', this.onToggleSubscription);
+ },
+};
+</script>
+
+<template>
+ <div class="block subscriptions">
+ <subscriptions
+ :loading="store.isFetching.subscriptions"
+ :subscribed="store.subscribed" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
new file mode 100644
index 00000000000..a3a8213d63a
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -0,0 +1,60 @@
+<script>
+import { __ } from '../../../locale';
+import eventHub from '../../event_hub';
+import loadingButton from '../../../vue_shared/components/loading_button.vue';
+
+export default {
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ subscribed: {
+ type: Boolean,
+ required: false,
+ },
+ },
+ components: {
+ loadingButton,
+ },
+ computed: {
+ buttonLabel() {
+ let label;
+ if (this.subscribed === false) {
+ label = __('Subscribe');
+ } else if (this.subscribed === true) {
+ label = __('Unsubscribe');
+ }
+
+ return label;
+ },
+ },
+ methods: {
+ toggleSubscription() {
+ eventHub.$emit('toggleSubscription');
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="sidebar-collapsed-icon">
+ <i
+ class="fa fa-rss"
+ aria-hidden="true">
+ </i>
+ </div>
+ <span class="issuable-header-text hide-collapsed pull-left">
+ {{ __('Notifications') }}
+ </span>
+ <loading-button
+ ref="loadingButton"
+ class="btn btn-default pull-right hide-collapsed js-issuable-subscribe-button"
+ :loading="loading"
+ :label="buttonLabel"
+ @click="toggleSubscription"
+ />
+ </div>
+</template>