mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-08 07:21:03 +08:00
Update access modal [SCI-10091]
This commit is contained in:
parent
d9cd1a7883
commit
007bebed46
6 changed files with 168 additions and 134 deletions
|
|
@ -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>
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue