Update access modal [SCI-10091]

This commit is contained in:
Anton 2024-01-29 15:19:25 +01:00
parent d9cd1a7883
commit 007bebed46
6 changed files with 168 additions and 134 deletions

View file

@ -1,27 +1,19 @@
<template>
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<i class="sn-icon sn-icon-close"></i>
</button>
<h4 class="modal-title truncate flex items-center gap-4">
{{ i18n.t('access_permissions.partials.new_assignments_form.title', {resource_name: params.object.name}) }}
<button class="close" @click="$emit('changeMode', 'editView')">
<i class="sn-icon sn-icon-left"></i>
</button>
</h4>
<div class="mb-6">
<div class="sci-label mb-2">
{{ i18n.t('access_permissions.partials.new_assignments_form.grant_access') }}
</div>
<div class="modal-body">
<div class="mb-4">
<GeneralDropdown @open="$emit('assigningNewUsers', true)" @close="$emit('assigningNewUsers', false)" :fieldOnlyOpen="true">
<template v-slot:field>
<div class="sci-input-container-v2 left-icon">
<input type="text" v-model="query" class="sci-input-field"
autofocus="true"
:placeholder="i18n.t('access_permissions.partials.new_assignments_form.find_people_html')" />
autofocus="true"
:placeholder="i18n.t('access_permissions.partials.new_assignments_form.find_people_html')" />
<i class="sn-icon sn-icon-search"></i>
</div>
</div>
<div class="h-[60vh] overflow-y-auto">
<div v-if="!visible && roles.length > 0" class="p-2 flex items-center gap-2">
</template>
<template v-slot:flyout>
<div v-if="!visible && roles.length > 0" class="py-2 flex border-solid border-0 border-b border-b-sn-sleepy-grey items-center gap-2">
<div>
<img src="/images/icon/team.png" class="rounded-full w-8 h-8">
</div>
@ -37,50 +29,57 @@
@setRole="(...args) => this.assignRole('all', ...args)"
></MenuDropdown>
</div>
<div v-for="user in filteredUsers" :key="user.id" class="p-2 flex items-center gap-2">
<div>
<img :src="user.attributes.avatar_url" class="rounded-full w-8 h-8">
<perfect-scrollbar class="h-80 relative">
<div v-for="user in filteredUsers" :key="user.id" class="py-2 flex items-center gap-2">
<div>
<img :src="user.attributes.avatar_url" class="rounded-full w-8 h-8">
</div>
<div>{{ user.attributes.name }}</div>
<MenuDropdown
class="ml-auto"
:listItems="rolesFromatted"
btnText="Assign"
:position="'right'"
:caret="true"
@setRole="(...args) => this.assignRole(user.id, ...args)"
></MenuDropdown>
</div>
<div>{{ user.attributes.name }}</div>
<MenuDropdown
class="ml-auto"
:listItems="rolesFromatted"
btnText="Assign"
:position="'right'"
:caret="true"
@setRole="(...args) => this.assignRole(user.id, ...args)"
></MenuDropdown>
</div>
</div>
</div>
</perfect-scrollbar>
</template>
</GeneralDropdown>
</div>
</template>
<script>
/* global HelperModule */
import MenuDropdown from '../menu_dropdown.vue';
import GeneralDropdown from '../general_dropdown.vue';
import axios from '../../../packs/custom_axios.js';
export default {
emits: ['modified', 'usersReloaded', 'changeVisibility'],
props: {
params: {
type: Object,
required: true,
required: true
},
visible: {
type: Boolean,
type: Boolean
},
default_role: {
type: Number,
type: Number
},
reloadUsers: {
type: Boolean
}
},
emits: ['changeMode'],
mounted() {
this.getUnAssignedUsers();
this.getRoles();
},
components: {
MenuDropdown,
GeneralDropdown
},
computed: {
rolesFromatted() {
@ -88,7 +87,7 @@ export default {
{
emit: 'setRole',
text: role[1],
params: role[0],
params: role[0]
}
));
},
@ -96,20 +95,28 @@ export default {
return this.unAssignedUsers.filter((user) => (
user.attributes.name.toLowerCase().includes(this.query.toLowerCase())
));
},
}
},
data() {
return {
unAssignedUsers: [],
roles: [],
query: '',
query: ''
};
},
watch: {
reloadUsers() {
if (this.reloadUsers) {
this.getUnAssignedUsers();
}
}
},
methods: {
getUnAssignedUsers() {
axios.get(this.params.object.urls.new_access)
.then((response) => {
this.unAssignedUsers = response.data.data;
this.$emit('usersReloaded');
});
},
getRoles() {
@ -122,8 +129,8 @@ export default {
axios.post(this.params.object.urls.create_access, {
user_assignment: {
user_id: id,
user_role_id: roleId,
},
user_role_id: roleId
}
})
.then((response) => {
this.$emit('modified');
@ -134,7 +141,7 @@ export default {
this.$emit('changeVisibility', true, roleId);
}
});
},
},
}
}
};
</script>

View file

@ -1,75 +1,56 @@
<template>
<div>
<div class="modal-header">
<button type="button"
class="close"
data-dismiss="modal"
aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
<h4 class="modal-title truncate !block">
{{ i18n.t(`access_permissions.${params.object.type}.modals.edit_modal.title`, {
resource_name: params.object.name
}) }}
</h4>
</div>
<div class="modal-body">
<div class="h-[60vh] overflow-y-auto">
<div v-for="userAssignment in manuallyAssignedUsers"
:key="userAssignment.id"
class="p-2 flex items-center gap-2">
<div>
<img :src="userAssignment.attributes.user.avatar_url" class="rounded-full w-8 h-8">
</div>
<div>
<div>{{ userAssignment.attributes.user.name }}</div>
<div class="text-xs text-sn-grey">{{ userAssignment.attributes.inherit_message }}</div>
</div>
<MenuDropdown
v-if="!userAssignment.attributes.last_owner && params.object.urls.update_access"
class="ml-auto"
:listItems="rolesFromatted"
:btnText="userAssignment.attributes.user_role.name"
:position="'right'"
:caret="true"
@setRole="(...args) => this.changeRole(userAssignment.attributes.user.id, ...args)"
@removeRole="() => this.removeRole(userAssignment.attributes.user.id)"
></MenuDropdown>
<div class="ml-auto btn btn-light pointer-events-none" v-else>
{{ userAssignment.attributes.user_role.name }}
<div class="h-6 w-6"></div>
</div>
</div>
<div v-if="roles.length > 0 && visible" class="p-2 flex items-center gap-2">
<div>
<img src="/images/icon/team.png" class="rounded-full w-8 h-8">
</div>
<div>
{{ i18n.t('access_permissions.everyone_else', { team_name: params.object.team }) }}
</div>
<i class="sn-icon sn-icon-info"
:title='this.autoAssignedUsers.map((ua) => ua.attributes.user.name).join("\u000d")'></i>
<MenuDropdown
v-if="params.object.top_level_assignable && params.object.urls.update_access"
class="ml-auto"
:listItems="rolesFromatted"
:btnText="this.roles.find((role) => role[0] == default_role)[1]"
:position="'right'"
:caret="true"
@setRole="(...args) => this.changeDefaultRole(...args)"
@removeRole="() => this.changeDefaultRole()"
></MenuDropdown>
<div class="ml-auto btn btn-light pointer-events-none" v-else>
{{ this.roles.find((role) => role[0] == default_role)[1] }}
<div class="h-6 w-6"></div>
</div>
</div>
<div v-if="roles.length > 0 && visible" class="p-2 flex items-center gap-2 border-solid border-0 border-b border-b-sn-sleepy-grey">
<div>
<img src="/images/icon/team.png" class="rounded-full w-8 h-8">
</div>
<div>
{{ i18n.t('access_permissions.everyone_else', { team_name: params.object.team }) }}
</div>
<i class="sn-icon sn-icon-info"
:title='this.autoAssignedUsers.map((ua) => ua.attributes.user.name).join("\u000d")'></i>
<MenuDropdown
v-if="params.object.top_level_assignable && params.object.urls.update_access"
class="ml-auto"
:listItems="rolesFromatted"
:btnText="this.roles.find((role) => role[0] == default_role)[1]"
:position="'right'"
:caret="true"
@setRole="(...args) => this.changeDefaultRole(...args)"
@removeRole="() => this.changeDefaultRole()"
></MenuDropdown>
<div class="ml-auto btn btn-light pointer-events-none" v-else>
{{ this.roles.find((role) => role[0] == default_role)[1] }}
<div class="h-6 w-6"></div>
</div>
</div>
<div v-if="params.object.urls.new_access" class="modal-footer">
<button class="btn-light ml-auto btn" @click="$emit('changeMode', 'newView')">
<i class="sn-icon sn-icon-new-task"></i>
{{ i18n.t('access_permissions.grant_access') }}
</button >
</div>
<perfect-scrollbar class="h-[50vh] relative">
<div v-for="userAssignment in manuallyAssignedUsers"
:key="userAssignment.id"
class="p-2 flex items-center gap-2">
<div>
<img :src="userAssignment.attributes.user.avatar_url" class="rounded-full w-8 h-8">
</div>
<div>
<div>{{ userAssignment.attributes.user.name }}</div>
<div class="text-xs text-sn-grey">{{ userAssignment.attributes.inherit_message }}</div>
</div>
<MenuDropdown
v-if="!userAssignment.attributes.last_owner && params.object.urls.update_access"
class="ml-auto"
:listItems="rolesFromatted"
:btnText="userAssignment.attributes.user_role.name"
:position="'right'"
:caret="true"
@setRole="(...args) => this.changeRole(userAssignment.attributes.user.id, ...args)"
@removeRole="() => this.removeRole(userAssignment.attributes.user.id)"
></MenuDropdown>
<div class="ml-auto btn btn-light pointer-events-none" v-else>
{{ userAssignment.attributes.user_role.name }}
<div class="h-6 w-6"></div>
</div>
</div>
</perfect-scrollbar>
</div>
</template>
@ -80,6 +61,7 @@ import MenuDropdown from '../menu_dropdown.vue';
import axios from '../../../packs/custom_axios.js';
export default {
emits: ['modified', 'usersReloaded', 'changeVisibility'],
props: {
params: {
type: Object,
@ -90,13 +72,22 @@ export default {
},
default_role: {
type: Number
},
reloadUsers: {
type: Boolean
}
},
emits: ['changeMode', 'modified'],
mounted() {
this.getAssignedUsers();
this.getRoles();
},
watch: {
reloadUsers() {
if (this.reloadUsers) {
this.getAssignedUsers();
}
}
},
components: {
MenuDropdown
},
@ -153,6 +144,7 @@ export default {
axios.get(this.params.object.urls.show_access)
.then((response) => {
this.assignedUsers = response.data.data;
this.$emit('usersReloaded');
});
},
getRoles() {

View file

@ -2,15 +2,43 @@
<div ref="modal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<component
:is="mode"
:params="params"
:visible="visible"
:default_role="default_role"
@changeMode="changeMode"
@modified="modified = true"
@changeVisibility="changeVisibility"
></component>
<div class="modal-header">
<button type="button"
class="close"
data-dismiss="modal"
aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
<h4 class="modal-title truncate !block">
{{ i18n.t(`access_permissions.${params.object.type}.modals.edit_modal.title`, {
resource_name: params.object.name
}) }}
</h4>
</div>
<div class="modal-body">
<AssignFlyout
v-if="params.object.urls.new_access"
:params="params"
:visible="visible"
:default_role="default_role"
:reloadUsers="reloadUnAssignedUsers"
@modified="modified = true; reloadUsers = true"
@assigningNewUsers="(v) => { assigningNewUsers = v }"
@usersReloaded="reloadUnAssignedUsers = false"
@changeVisibility="changeVisibility"
/>
<h5 class="py-2.5">
{{ i18n.t('access_permissions.partials.new_assignments_form.people_with_access') }}
</h5>
<editView
:class="{'opacity-50 pointer-events-none': assigningNewUsers}"
:params="params"
:visible="visible"
:default_role="default_role"
:reloadUsers="reloadUsers"
@modified="modified = true; reloadUnAssignedUsers = true"
@usersReloaded="reloadUsers = false"
@changeVisibility="changeVisibility"
/>
</div>
</div>
</div>
</div>
@ -21,21 +49,22 @@
import SelectDropdown from '../select_dropdown.vue';
import modalMixin from '../modal_mixin';
import editView from './edit.vue';
import newView from './new.vue';
import AssignFlyout from './assign_flyout.vue';
export default {
emits: ['modified', 'usersReloaded', 'changeVisibility'],
name: 'AccessModal',
props: {
params: {
type: Object,
required: true,
},
required: true
}
},
mixins: [modalMixin],
components: {
SelectDropdown,
editView,
newView,
AssignFlyout
},
data() {
return {
@ -43,6 +72,9 @@ export default {
modified: false,
visible: false,
default_role: null,
reloadUsers: false,
assigningNewUsers: false,
reloadUnAssignedUsers: false
};
},
mounted() {
@ -61,7 +93,7 @@ export default {
changeVisibility(status, role) {
this.visible = status;
this.default_role = role;
},
},
}
}
};
</script>

View file

@ -1,6 +1,6 @@
<template>
<div class="relative" v-click-outside="closeMenu" >
<div ref="field" class="cursor-pointer" @click.stop="isOpen = !isOpen">
<div ref="field" class="cursor-pointer" @click.stop="isOpen = (!isOpen || fieldOnlyOpen)">
<slot name="field"></slot>
</div>
<teleport to="body">
@ -34,7 +34,8 @@ export default {
btnIcon: { type: String, required: false },
caret: { type: Boolean, default: false },
alwaysShow: { type: Boolean, default: false },
closeDropdown: { type: Boolean, default: false }
closeDropdown: { type: Boolean, default: false },
fieldOnlyOpen: { type: Boolean, default: false }
},
data() {
return {
@ -59,7 +60,7 @@ export default {
},
methods: {
closeMenu(e) {
if (e && e.target.closest('.sn-dropdown, .sn-select-dropdown, .dp__instance_calendar')) return;
if (e && e.target.closest('.sn-dropdown, .sn-select-dropdown, .sn-menu-dropdown, .dp__instance_calendar')) return;
this.isOpen = false;
}
}

View file

@ -9,7 +9,7 @@
<teleport to="body">
<div ref="flyout"
v-if="isOpen"
class="fixed z-[3000] bg-sn-white inline-block rounded p-2.5 sn-shadow-menu-sm flex flex-col gap-[1px]"
class="fixed z-[3000] sn-menu-dropdown bg-sn-white inline-block rounded p-2.5 sn-shadow-menu-sm flex flex-col gap-[1px]"
:class="{
'right-0': position === 'right',
'left-0': position === 'left',

View file

@ -3676,13 +3676,15 @@ en:
submit: "Grant access"
submit_singular: "Grant access to 1 member"
submit_plural: "Grant access to {num} members"
find_people_html: "Find people"
find_people_html: "Search members"
grant_access: "Grant new access"
people_with_access: "People with access"
new_protocol_assignments_form:
title: "Select members"
submit: "Grant access"
submit_singular: "Grant access to 1 member"
submit_plural: "Grant access to {num} members"
find_people_html: "Find people"
find_people_html: "Search members"
experiment_member_field:
reset: "Inherit role"
reset_description: "The inherited role from project will be applied"