Commit 2f17b4cb authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch '40907-confidential-lock-icons-collapsed-sidebar' into 'master'

Resolve "Clicking confidential and lock icons on sidebar should also activate dropdown"

Closes #40907

See merge request gitlab-org/gitlab-ce!17869
parents b0e17493 91a4eb1c
<script> <script>
import Flash from '../../../flash'; import Flash from '../../../flash';
import editForm from './edit_form.vue'; import editForm from './edit_form.vue';
import Icon from '../../../vue_shared/components/icon.vue'; import Icon from '../../../vue_shared/components/icon.vue';
import { __ } from '../../../locale'; import { __ } from '../../../locale';
import eventHub from '../../event_hub';
export default { export default {
components: { components: {
editForm, editForm,
Icon, Icon,
},
props: {
isConfidential: {
required: true,
type: Boolean,
}, },
props: { isEditable: {
isConfidential: { required: true,
required: true, type: Boolean,
type: Boolean,
},
isEditable: {
required: true,
type: Boolean,
},
service: {
required: true,
type: Object,
},
}, },
data() { service: {
return { required: true,
edit: false, type: Object,
};
}, },
computed: { },
confidentialityIcon() { data() {
return this.isConfidential ? 'eye-slash' : 'eye'; return {
}, edit: false,
};
},
computed: {
confidentialityIcon() {
return this.isConfidential ? 'eye-slash' : 'eye';
}, },
methods: { },
toggleForm() { created() {
this.edit = !this.edit; eventHub.$on('closeConfidentialityForm', this.toggleForm);
}, },
updateConfidentialAttribute(confidential) { beforeDestroy() {
this.service.update('issue', { confidential }) eventHub.$off('closeConfidentialityForm', this.toggleForm);
.then(() => location.reload()) },
.catch(() => { methods: {
Flash(__('Something went wrong trying to change the confidentiality of this issue')); toggleForm() {
}); this.edit = !this.edit;
},
}, },
}; updateConfidentialAttribute(confidential) {
this.service
.update('issue', { confidential })
.then(() => location.reload())
.catch(() => {
Flash(
__(
'Something went wrong trying to change the confidentiality of this issue',
),
);
});
},
},
};
</script> </script>
<template> <template>
<div class="block issuable-sidebar-item confidentiality"> <div class="block issuable-sidebar-item confidentiality">
<div class="sidebar-collapsed-icon"> <div
class="sidebar-collapsed-icon"
@click="toggleForm"
>
<icon <icon
:name="confidentialityIcon" :name="confidentialityIcon"
:size="16"
aria-hidden="true" aria-hidden="true"
/> />
</div> </div>
...@@ -71,7 +85,6 @@ ...@@ -71,7 +85,6 @@
<div class="value sidebar-item-value hide-collapsed"> <div class="value sidebar-item-value hide-collapsed">
<editForm <editForm
v-if="edit" v-if="edit"
:toggle-form="toggleForm"
:is-confidential="isConfidential" :is-confidential="isConfidential"
:update-confidential-attribute="updateConfidentialAttribute" :update-confidential-attribute="updateConfidentialAttribute"
/> />
......
<script> <script>
import editFormButtons from './edit_form_buttons.vue'; import editFormButtons from './edit_form_buttons.vue';
import { s__ } from '../../../locale'; import { s__ } from '../../../locale';
export default { export default {
components: { components: {
editFormButtons, editFormButtons,
},
props: {
isConfidential: {
required: true,
type: Boolean,
}, },
props: { updateConfidentialAttribute: {
isConfidential: { required: true,
required: true, type: Function,
type: Boolean,
},
toggleForm: {
required: true,
type: Function,
},
updateConfidentialAttribute: {
required: true,
type: Function,
},
}, },
computed: { },
confidentialityOnWarning() { computed: {
return s__('confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.'); confidentialityOnWarning() {
}, return s__(
confidentialityOffWarning() { 'confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.',
return s__('confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.'); );
},
}, },
}; confidentialityOffWarning() {
return s__(
'confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.',
);
},
},
};
</script> </script>
<template> <template>
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
</p> </p>
<edit-form-buttons <edit-form-buttons
:is-confidential="isConfidential" :is-confidential="isConfidential"
:toggle-form="toggleForm"
:update-confidential-attribute="updateConfidentialAttribute" :update-confidential-attribute="updateConfidentialAttribute"
/> />
</div> </div>
......
<script> <script>
import $ from 'jquery';
import eventHub from '../../event_hub';
export default { export default {
props: { props: {
isConfidential: { isConfidential: {
required: true, required: true,
type: Boolean, type: Boolean,
}, },
toggleForm: {
required: true,
type: Function,
},
updateConfidentialAttribute: { updateConfidentialAttribute: {
required: true, required: true,
type: Function, type: Function,
...@@ -22,6 +21,16 @@ export default { ...@@ -22,6 +21,16 @@ export default {
return !this.isConfidential; return !this.isConfidential;
}, },
}, },
methods: {
closeForm() {
eventHub.$emit('closeConfidentialityForm');
$(this.$el).trigger('hidden.gl.dropdown');
},
submitForm() {
this.closeForm();
this.updateConfidentialAttribute(this.updateConfidentialBool);
},
},
}; };
</script> </script>
...@@ -30,14 +39,14 @@ export default { ...@@ -30,14 +39,14 @@ export default {
<button <button
type="button" type="button"
class="btn btn-default append-right-10" class="btn btn-default append-right-10"
@click="toggleForm" @click="closeForm"
> >
{{ __('Cancel') }} {{ __('Cancel') }}
</button> </button>
<button <button
type="button" type="button"
class="btn btn-close" class="btn btn-close"
@click.prevent="updateConfidentialAttribute(updateConfidentialBool)" @click.prevent="submitForm"
> >
{{ toggleButtonText }} {{ toggleButtonText }}
</button> </button>
......
<script> <script>
import editFormButtons from './edit_form_buttons.vue'; import editFormButtons from './edit_form_buttons.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable'; import issuableMixin from '../../../vue_shared/mixins/issuable';
import { __, sprintf } from '../../../locale'; import { __, sprintf } from '../../../locale';
export default { export default {
components: { components: {
editFormButtons, editFormButtons,
},
mixins: [issuableMixin],
props: {
isLocked: {
required: true,
type: Boolean,
}, },
mixins: [
issuableMixin,
],
props: {
isLocked: {
required: true,
type: Boolean,
},
toggleForm: { updateLockedAttribute: {
required: true, required: true,
type: Function, type: Function,
}, },
},
updateLockedAttribute: { computed: {
required: true, lockWarning() {
type: Function, return sprintf(
}, __(
'Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.',
),
{ issuableDisplayName: this.issuableDisplayName },
);
}, },
computed: { unlockWarning() {
lockWarning() { return sprintf(
return sprintf(__('Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.'), { issuableDisplayName: this.issuableDisplayName }); __(
}, 'Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.',
unlockWarning() { ),
return sprintf(__('Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.'), { issuableDisplayName: this.issuableDisplayName }); { issuableDisplayName: this.issuableDisplayName },
}, );
}, },
}; },
};
</script> </script>
<template> <template>
...@@ -54,7 +57,6 @@ ...@@ -54,7 +57,6 @@
<edit-form-buttons <edit-form-buttons
:is-locked="isLocked" :is-locked="isLocked"
:toggle-form="toggleForm"
:update-locked-attribute="updateLockedAttribute" :update-locked-attribute="updateLockedAttribute"
/> />
</div> </div>
......
<script> <script>
import $ from 'jquery';
import eventHub from '../../event_hub';
export default { export default {
props: { props: {
isLocked: { isLocked: {
...@@ -6,11 +9,6 @@ export default { ...@@ -6,11 +9,6 @@ export default {
type: Boolean, type: Boolean,
}, },
toggleForm: {
required: true,
type: Function,
},
updateLockedAttribute: { updateLockedAttribute: {
required: true, required: true,
type: Function, type: Function,
...@@ -26,6 +24,17 @@ export default { ...@@ -26,6 +24,17 @@ export default {
return !this.isLocked; return !this.isLocked;
}, },
}, },
methods: {
closeForm() {
eventHub.$emit('closeLockForm');
$(this.$el).trigger('hidden.gl.dropdown');
},
submitForm() {
this.closeForm();
this.updateLockedAttribute(this.toggleLock);
},
},
}; };
</script> </script>
...@@ -34,7 +43,7 @@ export default { ...@@ -34,7 +43,7 @@ export default {
<button <button
type="button" type="button"
class="btn btn-default append-right-10" class="btn btn-default append-right-10"
@click="toggleForm" @click="closeForm"
> >
{{ __('Cancel') }} {{ __('Cancel') }}
</button> </button>
...@@ -42,7 +51,7 @@ export default { ...@@ -42,7 +51,7 @@ export default {
<button <button
type="button" type="button"
class="btn btn-close" class="btn btn-close"
@click.prevent="updateLockedAttribute(toggleLock)" @click.prevent="submitForm"
> >
{{ buttonText }} {{ buttonText }}
</button> </button>
......
<script> <script>
import Flash from '~/flash'; import Flash from '~/flash';
import editForm from './edit_form.vue'; import editForm from './edit_form.vue';
import issuableMixin from '../../../vue_shared/mixins/issuable'; import issuableMixin from '../../../vue_shared/mixins/issuable';
import Icon from '../../../vue_shared/components/icon.vue'; import Icon from '../../../vue_shared/components/icon.vue';
import eventHub from '../../event_hub';
export default { export default {
components: { components: {
editForm, editForm,
Icon, Icon,
}, },
mixins: [ mixins: [issuableMixin],
issuableMixin,
],
props: { props: {
isLocked: { isLocked: {
required: true, required: true,
type: Boolean, type: Boolean,
}, },
isEditable: { isEditable: {
required: true, required: true,
type: Boolean, type: Boolean,
}, },
mediator: { mediator: {
required: true, required: true,
type: Object, type: Object,
validator(mediatorObject) { validator(mediatorObject) {
return mediatorObject.service && mediatorObject.service.update && mediatorObject.store; return (
}, mediatorObject.service &&
mediatorObject.service.update &&
mediatorObject.store
);
}, },
}, },
},
computed: { computed: {
lockIcon() { lockIcon() {
return this.isLocked ? 'lock' : 'lock-open'; return this.isLocked ? 'lock' : 'lock-open';
}, },
isLockDialogOpen() { isLockDialogOpen() {
return this.mediator.store.isLockDialogOpen; return this.mediator.store.isLockDialogOpen;
},
}, },
},
methods: { created() {
toggleForm() { eventHub.$on('closeLockForm', this.toggleForm);
this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen; },
},
beforeDestroy() {
eventHub.$off('closeLockForm', this.toggleForm);
},
updateLockedAttribute(locked) { methods: {
this.mediator.service.update(this.issuableType, { toggleForm() {
this.mediator.store.isLockDialogOpen = !this.mediator.store
.isLockDialogOpen;
},
updateLockedAttribute(locked) {
this.mediator.service
.update(this.issuableType, {
discussion_locked: locked, discussion_locked: locked,
}) })
.then(() => location.reload()) .then(() => location.reload())
.catch(() => Flash(this.__(`Something went wrong trying to change the locked state of this ${this.issuableDisplayName}`))); .catch(() =>
}, Flash(
this.__(
`Something went wrong trying to change the locked state of this ${
this.issuableDisplayName
}`,
),
),
);
}, },
}; },
};
</script> </script>
<template> <template>
<div class="block issuable-sidebar-item lock"> <div class="block issuable-sidebar-item lock">
<div class="sidebar-collapsed-icon"> <div
class="sidebar-collapsed-icon"
@click="toggleForm"
>
<icon <icon
:name="lockIcon" :name="lockIcon"
:size="16"
aria-hidden="true" aria-hidden="true"
class="sidebar-item-icon is-active" class="sidebar-item-icon is-active"
/> />
...@@ -85,7 +108,6 @@ ...@@ -85,7 +108,6 @@
<div class="value sidebar-item-value hide-collapsed"> <div class="value sidebar-item-value hide-collapsed">
<edit-form <edit-form
v-if="isLockDialogOpen" v-if="isLockDialogOpen"
:toggle-form="toggleForm"
:is-locked="isLocked" :is-locked="isLocked"
:update-locked-attribute="updateLockedAttribute" :update-locked-attribute="updateLockedAttribute"
:issuable-type="issuableType" :issuable-type="issuableType"
......
...@@ -14,7 +14,7 @@ describe 'Discussion Lock', :js do ...@@ -14,7 +14,7 @@ describe 'Discussion Lock', :js do
project.add_developer(user) project.add_developer(user)
end end
context 'when the discussion is unlocked' do context 'when the discussion is unlocked' do
it 'the user can lock the issue' do it 'the user can lock the issue' do
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
......
...@@ -161,6 +161,50 @@ feature 'Issue Sidebar' do ...@@ -161,6 +161,50 @@ feature 'Issue Sidebar' do
end end
end end
end end
context 'interacting with collapsed sidebar', :js do
collapsed_sidebar_selector = 'aside.right-sidebar.right-sidebar-collapsed'
expanded_sidebar_selector = 'aside.right-sidebar.right-sidebar-expanded'
confidentiality_sidebar_block = '.block.confidentiality'
lock_sidebar_block = '.block.lock'
collapsed_sidebar_block_icon = '.sidebar-collapsed-icon'
before do
resize_screen_sm
end
it 'confidentiality block expands then collapses sidebar' do
expect(page).to have_css(collapsed_sidebar_selector)
page.within(confidentiality_sidebar_block) do
find(collapsed_sidebar_block_icon).click
end
expect(page).to have_css(expanded_sidebar_selector)
page.within(confidentiality_sidebar_block) do
page.find('button', text: 'Cancel').click
end
expect(page).to have_css(collapsed_sidebar_selector)
end
it 'lock block expands then collapses sidebar' do
expect(page).to have_css(collapsed_sidebar_selector)
page.within(lock_sidebar_block) do
find(collapsed_sidebar_block_icon).click
end
expect(page).to have_css(expanded_sidebar_selector)
page.within(lock_sidebar_block) do
page.find('button', text: 'Cancel').click
end
expect(page).to have_css(collapsed_sidebar_selector)
end
end
end end
context 'as a guest' do context 'as a guest' do
......
...@@ -62,4 +62,22 @@ describe('Confidential Issue Sidebar Block', () => { ...@@ -62,4 +62,22 @@ describe('Confidential Issue Sidebar Block', () => {
done(); done();
}); });
}); });
it('displays the edit form when opened from collapsed state', (done) => {
expect(vm1.edit).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
expect(vm1.edit).toBe(true);
setTimeout(() => {
expect(
vm1.$el
.innerHTML
.includes('You are going to turn off the confidentiality.'),
).toBe(true);
done();
});
});
}); });
...@@ -68,4 +68,22 @@ describe('LockIssueSidebar', () => { ...@@ -68,4 +68,22 @@ describe('LockIssueSidebar', () => {
done(); done();
}); });
}); });
it('displays the edit form when opened from collapsed state', (done) => {
expect(vm1.isLockDialogOpen).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
expect(vm1.isLockDialogOpen).toBe(true);
setTimeout(() => {
expect(
vm1.$el
.innerHTML
.includes('Unlock this issue?'),
).toBe(true);
done();
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment