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:
Diffstat (limited to 'app/assets/javascripts/set_status_modal/set_status_form.vue')
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_form.vue231
1 files changed, 231 insertions, 0 deletions
diff --git a/app/assets/javascripts/set_status_modal/set_status_form.vue b/app/assets/javascripts/set_status_modal/set_status_form.vue
new file mode 100644
index 00000000000..7f9a30b7ff1
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/set_status_form.vue
@@ -0,0 +1,231 @@
+<script>
+import {
+ GlButton,
+ GlTooltipDirective,
+ GlIcon,
+ GlFormCheckbox,
+ GlFormInput,
+ GlFormInputGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ GlFormGroup,
+ GlSafeHtmlDirective,
+} from '@gitlab/ui';
+import $ from 'jquery';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
+import * as Emoji from '~/emoji';
+import { s__ } from '~/locale';
+import { TIME_RANGES_WITH_NEVER, AVAILABILITY_STATUS } from './constants';
+
+export default {
+ components: {
+ GlButton,
+ GlIcon,
+ GlFormCheckbox,
+ GlFormInput,
+ GlFormInputGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ GlFormGroup,
+ EmojiPicker: () => import('~/emoji/components/picker.vue'),
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ props: {
+ defaultEmoji: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ emoji: {
+ type: String,
+ required: true,
+ },
+ message: {
+ type: String,
+ required: true,
+ },
+ availability: {
+ type: Boolean,
+ required: true,
+ },
+ clearStatusAfter: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ currentClearStatusAfter: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ defaultEmojiTag: '',
+ emojiTag: '',
+ };
+ },
+ computed: {
+ isCustomEmoji() {
+ return this.emoji !== this.defaultEmoji;
+ },
+ isDirty() {
+ return Boolean(this.message.length || this.isCustomEmoji);
+ },
+ noEmoji() {
+ return this.emojiTag === '';
+ },
+ },
+ mounted() {
+ this.setupEmojiListAndAutocomplete();
+ },
+ methods: {
+ async setupEmojiListAndAutocomplete() {
+ const emojiAutocomplete = new GfmAutoComplete();
+ emojiAutocomplete.setup($(this.$refs.statusMessageField.$el), { emojis: true });
+
+ if (this.emoji) {
+ this.emojiTag = Emoji.glEmojiTag(this.emoji);
+ }
+ this.defaultEmojiTag = Emoji.glEmojiTag(this.defaultEmoji);
+
+ this.setDefaultEmoji();
+ },
+ setDefaultEmoji() {
+ const { emojiTag } = this;
+ const hasStatusMessage = Boolean(this.message.length);
+ if (hasStatusMessage && emojiTag) {
+ return;
+ }
+
+ if (hasStatusMessage) {
+ this.emojiTag = this.defaultEmojiTag;
+ } else if (emojiTag === this.defaultEmojiTag) {
+ this.clearEmoji();
+ }
+ },
+ handleEmojiClick(emoji) {
+ this.$emit('emoji-click', emoji);
+
+ this.emojiTag = Emoji.glEmojiTag(emoji);
+ },
+ clearEmoji() {
+ if (this.emojiTag) {
+ this.emojiTag = '';
+ }
+ },
+ clearStatusInputs() {
+ this.$emit('emoji-click', '');
+ this.$emit('message-input', '');
+ this.clearEmoji();
+ },
+ },
+ TIME_RANGES_WITH_NEVER,
+ AVAILABILITY_STATUS,
+ safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
+ i18n: {
+ statusMessagePlaceholder: s__(`SetStatusModal|What's your status?`),
+ clearStatusButtonLabel: s__('SetStatusModal|Clear status'),
+ availabilityCheckboxLabel: s__('SetStatusModal|Busy'),
+ availabilityCheckboxHelpText: s__(
+ 'SetStatusModal|An indicator appears next to your name and avatar',
+ ),
+ clearStatusAfterDropdownLabel: s__('SetStatusModal|Clear status after'),
+ clearStatusAfterMessage: s__('SetStatusModal|Your status resets on %{date}.'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-form-input-group class="gl-mb-5">
+ <gl-form-input
+ ref="statusMessageField"
+ :value="message"
+ :placeholder="$options.i18n.statusMessagePlaceholder"
+ @keyup="setDefaultEmoji"
+ @input="$emit('message-input', $event)"
+ @keyup.enter.prevent
+ />
+ <template #prepend>
+ <emoji-picker
+ dropdown-class="gl-h-full"
+ toggle-class="btn emoji-menu-toggle-button gl-px-4! gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
+ boundary="viewport"
+ :right="false"
+ @click="handleEmojiClick"
+ >
+ <template #button-content>
+ <span
+ v-if="noEmoji"
+ class="no-emoji-placeholder position-relative"
+ data-testid="no-emoji-placeholder"
+ >
+ <gl-icon name="slight-smile" class="award-control-icon-neutral" />
+ <gl-icon name="smiley" class="award-control-icon-positive" />
+ <gl-icon name="smile" class="award-control-icon-super-positive" />
+ </span>
+ <span v-else>
+ <span
+ v-safe-html:[$options.safeHtmlConfig]="emojiTag"
+ data-testid="selected-emoji"
+ ></span>
+ </span>
+ </template>
+ </emoji-picker>
+ </template>
+ <template v-if="isDirty" #append>
+ <gl-button
+ v-gl-tooltip.bottom
+ :title="$options.i18n.clearStatusButtonLabel"
+ :aria-label="$options.i18n.clearStatusButtonLabel"
+ icon="close"
+ class="js-clear-user-status-button"
+ @click="clearStatusInputs"
+ />
+ </template>
+ </gl-form-input-group>
+
+ <gl-form-checkbox
+ :checked="availability"
+ class="gl-mb-5"
+ data-testid="user-availability-checkbox"
+ @input="$emit('availability-input', $event)"
+ >
+ {{ $options.i18n.availabilityCheckboxLabel }}
+ <template #help>
+ {{ $options.i18n.availabilityCheckboxHelpText }}
+ </template>
+ </gl-form-checkbox>
+
+ <gl-form-group :label="$options.i18n.clearStatusAfterDropdownLabel" class="gl-mb-0">
+ <gl-dropdown
+ block
+ :text="clearStatusAfter.label"
+ data-testid="clear-status-at-dropdown"
+ toggle-class="gl-mb-0 gl-form-input-md"
+ >
+ <gl-dropdown-item
+ v-for="after in $options.TIME_RANGES_WITH_NEVER"
+ :key="after.name"
+ :data-testid="after.name"
+ @click="$emit('clear-status-after-click', after)"
+ >{{ after.label }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+
+ <template v-if="currentClearStatusAfter.length" #description>
+ <span data-testid="clear-status-at-message">
+ <gl-sprintf :message="$options.i18n.clearStatusAfterMessage">
+ <template #date>{{ currentClearStatusAfter }}</template>
+ </gl-sprintf>
+ </span>
+ </template>
+ </gl-form-group>
+ </div>
+</template>