summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/sidebar/components/sidebar_editable_item.vue')
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_editable_item.vue95
1 files changed, 95 insertions, 0 deletions
diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
new file mode 100644
index 00000000000..9da839cd133
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue
@@ -0,0 +1,95 @@
+<script>
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+
+export default {
+ components: { GlButton, GlLoadingIcon },
+ inject: ['canUpdate'],
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ edit: false,
+ };
+ },
+ destroyed() {
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ window.removeEventListener('keyup', this.collapseOnEscape);
+ },
+ methods: {
+ collapseWhenOffClick({ target }) {
+ if (!this.$el.contains(target)) {
+ this.collapse();
+ }
+ },
+ collapseOnEscape({ key }) {
+ if (key === 'Escape') {
+ this.collapse();
+ }
+ },
+ expand() {
+ if (this.edit) {
+ return;
+ }
+
+ this.edit = true;
+ this.$emit('open');
+ window.addEventListener('click', this.collapseWhenOffClick);
+ window.addEventListener('keyup', this.collapseOnEscape);
+ },
+ collapse({ emitEvent = true } = {}) {
+ if (!this.edit) {
+ return;
+ }
+
+ this.edit = false;
+ if (emitEvent) {
+ this.$emit('close');
+ }
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ window.removeEventListener('keyup', this.collapseOnEscape);
+ },
+ toggle({ emitEvent = true } = {}) {
+ if (this.edit) {
+ this.collapse({ emitEvent });
+ } else {
+ this.expand();
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-display-flex gl-align-items-center gl-mb-3" @click.self="collapse">
+ <span data-testid="title">{{ title }}</span>
+ <gl-loading-icon v-if="loading" inline class="gl-ml-2" />
+ <gl-button
+ v-if="canUpdate"
+ variant="link"
+ class="gl-text-gray-900! gl-hover-text-blue-800! gl-ml-auto js-sidebar-dropdown-toggle"
+ data-testid="edit-button"
+ @keyup.esc="toggle"
+ @click="toggle"
+ >
+ {{ __('Edit') }}
+ </gl-button>
+ </div>
+ <div v-show="!edit" class="gl-text-gray-500" data-testid="collapsed-content">
+ <slot name="collapsed">{{ __('None') }}</slot>
+ </div>
+ <div v-show="edit" data-testid="expanded-content">
+ <slot :edit="edit"></slot>
+ </div>
+ </div>
+</template>