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:
authorDennis Tang <dennis@dennistang.net>2018-10-04 11:19:51 +0300
committerPhil Hughes <me@iamphill.com>2018-10-04 11:19:51 +0300
commit4edcb02f94ba832929c054097d2f8badc0a34060 (patch)
tree2b01b32354ff9892200ef07c8b9e56caf37c5c73 /app/assets/javascripts/set_status_modal
parent18777ec78d8b6040702adc530d2ac5dff0f2ea67 (diff)
Resolve "Add status message from within user menu"
Diffstat (limited to 'app/assets/javascripts/set_status_modal')
-rw-r--r--app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js21
-rw-r--r--app/assets/javascripts/set_status_modal/event_hub.js3
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue33
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue241
4 files changed, 298 insertions, 0 deletions
diff --git a/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
new file mode 100644
index 00000000000..14a89ef9293
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
@@ -0,0 +1,21 @@
+import { AwardsHandler } from '~/awards_handler';
+
+class EmojiMenuInModal extends AwardsHandler {
+ constructor(emoji, toggleButtonSelector, menuClass, selectEmojiCallback, targetContainerEl) {
+ super(emoji);
+
+ this.selectEmojiCallback = selectEmojiCallback;
+ this.toggleButtonSelector = toggleButtonSelector;
+ this.menuClass = menuClass;
+ this.targetContainerEl = targetContainerEl;
+
+ this.bindEvents();
+ }
+
+ postEmoji($emojiButton, awardUrl, selectedEmoji, callback) {
+ this.selectEmojiCallback(selectedEmoji, this.emoji.glEmojiTag(selectedEmoji));
+ callback();
+ }
+}
+
+export default EmojiMenuInModal;
diff --git a/app/assets/javascripts/set_status_modal/event_hub.js b/app/assets/javascripts/set_status_modal/event_hub.js
new file mode 100644
index 00000000000..0948c2e5352
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/event_hub.js
@@ -0,0 +1,3 @@
+import Vue from 'vue';
+
+export default new Vue();
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue b/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
new file mode 100644
index 00000000000..48e5ede80f2
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
@@ -0,0 +1,33 @@
+<script>
+import { s__ } from '~/locale';
+import eventHub from './event_hub';
+
+export default {
+ props: {
+ hasStatus: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ buttonText() {
+ return this.hasStatus ? s__('SetStatusModal|Edit status') : s__('SetStatusModal|Set status');
+ },
+ },
+ methods: {
+ openModal() {
+ eventHub.$emit('openModal');
+ },
+ },
+};
+</script>
+
+<template>
+ <button
+ type="button"
+ class="btn menu-item"
+ @click="openModal"
+ >
+ {{ buttonText }}
+ </button>
+</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
new file mode 100644
index 00000000000..43f0b6651b9
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -0,0 +1,241 @@
+<script>
+import $ from 'jquery';
+import createFlash from '~/flash';
+import Icon from '~/vue_shared/components/icon.vue';
+import GfmAutoComplete from '~/gfm_auto_complete';
+import { __, s__ } from '~/locale';
+import Api from '~/api';
+import eventHub from './event_hub';
+import EmojiMenuInModal from './emoji_menu_in_modal';
+
+const emojiMenuClass = 'js-modal-status-emoji-menu';
+
+export default {
+ components: {
+ Icon,
+ },
+ props: {
+ currentEmoji: {
+ type: String,
+ required: true,
+ },
+ currentMessage: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ defaultEmojiTag: '',
+ emoji: this.currentEmoji,
+ emojiMenu: null,
+ emojiTag: '',
+ isEmojiMenuVisible: false,
+ message: this.currentMessage,
+ modalId: 'set-user-status-modal',
+ noEmoji: true,
+ };
+ },
+ computed: {
+ isDirty() {
+ return this.message.length || this.emoji.length;
+ },
+ },
+ mounted() {
+ eventHub.$on('openModal', this.openModal);
+ },
+ beforeDestroy() {
+ this.emojiMenu.destroy();
+ },
+ methods: {
+ openModal() {
+ this.$root.$emit('bv::show::modal', this.modalId);
+ },
+ closeModal() {
+ this.$root.$emit('bv::hide::modal', this.modalId);
+ },
+ setupEmojiListAndAutocomplete() {
+ const toggleEmojiMenuButtonSelector = '#set-user-status-modal .js-toggle-emoji-menu';
+ const emojiAutocomplete = new GfmAutoComplete();
+ emojiAutocomplete.setup($(this.$refs.statusMessageField), { emojis: true });
+
+ import(/* webpackChunkName: 'emoji' */ '~/emoji')
+ .then(Emoji => {
+ if (this.emoji) {
+ this.emojiTag = Emoji.glEmojiTag(this.emoji);
+ }
+ this.noEmoji = this.emoji === '';
+ this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon');
+
+ this.emojiMenu = new EmojiMenuInModal(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ emojiMenuClass,
+ this.setEmoji,
+ this.$refs.userStatusForm,
+ );
+ })
+ .catch(() => createFlash(__('Failed to load emoji list.')));
+ },
+ showEmojiMenu() {
+ this.isEmojiMenuVisible = true;
+ this.emojiMenu.showEmojiMenu($(this.$refs.toggleEmojiMenuButton));
+ },
+ hideEmojiMenu() {
+ if (!this.isEmojiMenuVisible) {
+ return;
+ }
+
+ this.isEmojiMenuVisible = false;
+ this.emojiMenu.hideMenuElement($(`.${emojiMenuClass}`));
+ },
+ setDefaultEmoji() {
+ const { emojiTag } = this;
+ const hasStatusMessage = this.message;
+ if (hasStatusMessage && emojiTag) {
+ return;
+ }
+
+ if (hasStatusMessage) {
+ this.noEmoji = false;
+ this.emojiTag = this.defaultEmojiTag;
+ } else if (emojiTag === this.defaultEmojiTag) {
+ this.noEmoji = true;
+ this.clearEmoji();
+ }
+ },
+ setEmoji(emoji, emojiTag) {
+ this.emoji = emoji;
+ this.noEmoji = false;
+ this.clearEmoji();
+ this.emojiTag = emojiTag;
+ },
+ clearEmoji() {
+ if (this.emojiTag) {
+ this.emojiTag = '';
+ }
+ },
+ clearStatusInputs() {
+ this.emoji = '';
+ this.message = '';
+ this.noEmoji = true;
+ this.clearEmoji();
+ this.hideEmojiMenu();
+ },
+ removeStatus() {
+ this.clearStatusInputs();
+ this.setStatus();
+ },
+ setStatus() {
+ const { emoji, message } = this;
+
+ Api.postUserStatus({
+ emoji,
+ message,
+ })
+ .then(this.onUpdateSuccess)
+ .catch(this.onUpdateFail);
+ },
+ onUpdateSuccess() {
+ this.closeModal();
+ window.location.reload();
+ },
+ onUpdateFail() {
+ createFlash(
+ s__("SetStatusModal|Sorry, we weren't able to set your status. Please try again later."),
+ );
+
+ this.closeModal();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-ui-modal
+ :title="s__('SetStatusModal|Set a status')"
+ :modal-id="modalId"
+ :ok-title="s__('SetStatusModal|Set status')"
+ :cancel-title="s__('SetStatusModal|Remove status')"
+ ok-variant="success"
+ class="set-user-status-modal"
+ @shown="setupEmojiListAndAutocomplete"
+ @hide="hideEmojiMenu"
+ @ok="setStatus"
+ @cancel="removeStatus"
+ >
+ <div>
+ <input
+ v-model="emoji"
+ class="js-status-emoji-field"
+ type="hidden"
+ name="user[status][emoji]"
+ />
+ <div
+ ref="userStatusForm"
+ class="form-group position-relative m-0"
+ >
+ <div class="input-group">
+ <span class="input-group-btn">
+ <button
+ ref="toggleEmojiMenuButton"
+ v-gl-tooltip.bottom
+ :title="s__('SetStatusModal|Add status emoji')"
+ :aria-label="s__('SetStatusModal|Add status emoji')"
+ name="button"
+ type="button"
+ class="js-toggle-emoji-menu emoji-menu-toggle-button btn"
+ @click="showEmojiMenu"
+ >
+ <span v-html="emojiTag"></span>
+ <span
+ v-show="noEmoji"
+ class="js-no-emoji-placeholder no-emoji-placeholder position-relative"
+ >
+ <icon
+ name="emoji_slightly_smiling_face"
+ css-classes="award-control-icon-neutral"
+ />
+ <icon
+ name="emoji_smiley"
+ css-classes="award-control-icon-positive"
+ />
+ <icon
+ name="emoji_smile"
+ css-classes="award-control-icon-super-positive"
+ />
+ </span>
+ </button>
+ </span>
+ <input
+ ref="statusMessageField"
+ v-model="message"
+ :placeholder="s__('SetStatusModal|What\'s your status?')"
+ type="text"
+ class="form-control form-control input-lg js-status-message-field"
+ name="user[status][message]"
+ @keyup="setDefaultEmoji"
+ @keyup.enter.prevent
+ @click="hideEmojiMenu"
+ />
+ <span
+ v-show="isDirty"
+ class="input-group-btn"
+ >
+ <button
+ v-gl-tooltip.bottom
+ :title="s__('SetStatusModal|Clear status')"
+ :aria-label="s__('SetStatusModal|Clear status')"
+ name="button"
+ type="button"
+ class="js-clear-user-status-button clear-user-status btn"
+ @click="clearStatusInputs()"
+ >
+ <icon name="close" />
+ </button>
+ </span>
+ </div>
+ </div>
+ </div>
+ </gl-ui-modal>
+</template>