Team functionality (#459)
* add api enpoints for adding, removing, updating user to workspace and leaving workspace * feat: updates client site workspace settings * refactor and add domain setting ui in modal * move workspace user functionality to its own component * adds tests * fix linting * updates select input to FlatSelectInput * moves workspace user role edit to seperated component * move user adding to its own component * adds check to usure users exist before checking is admin * fix loading users * feat: invite user to team functionality * fix token coulmn * fix self host mode changes * tests for user invite * Refactor back-end * Rename variables * Improve some styling elements + refactor workspace settings * More styling * More UI polishing * More UI fixes * PHP linting * Implemented most of the logic for team-functionnality * Fix user avatar URL * WIP remove users on cancellation * Finished pricing for team functionality * Fix tests * Fix linting * Added pricing_enabled helper * Fix pricing_enabled shortcut * Debug CI * Disable pricing when testing --------- Co-authored-by: LL-Etiane <lukongleinyuyetiane@gmail.com> Co-authored-by: Lukong Etiane <83535251+LL-Etiane@users.noreply.github.com> Co-authored-by: Julien Nahum <julien@nahum.net>
This commit is contained in:
87
client/components/pages/admin/AddUserToWorkspace.vue
Normal file
87
client/components/pages/admin/AddUserToWorkspace.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<form
|
||||
v-if="isWorkspaceAdmin"
|
||||
class="my-2"
|
||||
@submit.prevent="addUser"
|
||||
>
|
||||
<text-input
|
||||
v-model="newUser"
|
||||
name="email"
|
||||
label="Email"
|
||||
:required="true"
|
||||
:disabled="disabled"
|
||||
placeholder="Add a new user by email"
|
||||
/>
|
||||
<select-input
|
||||
v-model="newUserRole"
|
||||
name="newUserRole"
|
||||
:options="roleOptions"
|
||||
:disabled="disabled"
|
||||
placeholder="Select User Role"
|
||||
label="Role"
|
||||
:required="true"
|
||||
/>
|
||||
<div class="flex justify-center mt-2">
|
||||
<UButton
|
||||
type="submit"
|
||||
:disabled="disabled"
|
||||
:loading="addingUsersState"
|
||||
icon="i-heroicons-envelope"
|
||||
>
|
||||
Invite User
|
||||
</UButton>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch, ref } from "vue"
|
||||
|
||||
const props = defineProps({
|
||||
isWorkspaceAdmin: {},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['fetchUsers'])
|
||||
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
|
||||
const roleOptions = [
|
||||
{ name: "User", value: "user" },
|
||||
{ name: "Admin", value: "admin" }
|
||||
]
|
||||
|
||||
const newUser = ref("")
|
||||
const newUserRole = ref("user")
|
||||
const addingUsersState = ref(false)
|
||||
|
||||
|
||||
const addUser = () => {
|
||||
if (!newUser.value) return
|
||||
addingUsersState.value = true
|
||||
opnFetch(
|
||||
"/open/workspaces/" + workspacesStore.currentId + "/users/add",
|
||||
{
|
||||
method: "POST",
|
||||
body: {
|
||||
email: newUser.value,
|
||||
role: newUserRole.value,
|
||||
},
|
||||
}
|
||||
).then((data) => {
|
||||
newUser.value = ""
|
||||
newUserRole.value = "user"
|
||||
|
||||
useAlert().success(data.message)
|
||||
|
||||
emit("fetchUsers")
|
||||
}).catch((error) => {
|
||||
useAlert().error("There was an error adding user")
|
||||
}).finally(() => {
|
||||
addingUsersState.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
82
client/components/pages/admin/EditWorkSpaceUser.vue
Normal file
82
client/components/pages/admin/EditWorkSpaceUser.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<modal
|
||||
:show="showEditUserModal"
|
||||
max-width="lg"
|
||||
@close="$emit('close')"
|
||||
>
|
||||
<template #title>
|
||||
Edit User Role
|
||||
</template>
|
||||
<div class="px-4">
|
||||
<form
|
||||
@submit.prevent="updateUserRole"
|
||||
>
|
||||
<div>
|
||||
<FlatSelectInput
|
||||
v-model="userNewRole"
|
||||
name="newUserRole"
|
||||
:label="'New Role for '+props.user.name"
|
||||
:options="[
|
||||
{ name: 'User', value: 'user' },
|
||||
{ name: 'Admin', value: 'admin' }
|
||||
]"
|
||||
option-key="value"
|
||||
display-key="name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-full mt-6">
|
||||
<v-button
|
||||
:loading="updatingUserRoleState"
|
||||
class="w-full my-3"
|
||||
>
|
||||
Update
|
||||
</v-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {watch, ref} from "vue"
|
||||
|
||||
const props = defineProps(['user', 'showEditUserModal'])
|
||||
const emit = defineEmits(['close', 'fetchUsers'])
|
||||
|
||||
const workspacesStore = useWorkspacesStore()
|
||||
const userNewRole = ref("")
|
||||
|
||||
const updatingUserRoleState = ref(false)
|
||||
|
||||
watch(() => props.user, () => {
|
||||
userNewRole.value = props.user.pivot.role
|
||||
})
|
||||
|
||||
const updateUserRole = () => {
|
||||
updatingUserRoleState.value = true
|
||||
opnFetch(
|
||||
"/open/workspaces/" +
|
||||
workspacesStore.currentId +
|
||||
"/users/" +
|
||||
props.user.id +
|
||||
"/update-role",
|
||||
{
|
||||
method: "PUT",
|
||||
body: {
|
||||
role: userNewRole.value,
|
||||
},
|
||||
},
|
||||
{showSuccess: false},
|
||||
).then(() => {
|
||||
useAlert().success("User role updated.")
|
||||
emit('fetchUsers')
|
||||
emit('close')
|
||||
}).catch((error) => {
|
||||
useAlert().error("There was an error updating user role")
|
||||
}).finally(() => {
|
||||
updatingUserRoleState.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user