diff --git a/cookbook/serializer.py b/cookbook/serializer.py
index c62fdc407..6c991e436 100644
--- a/cookbook/serializer.py
+++ b/cookbook/serializer.py
@@ -37,7 +37,7 @@ from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Cu
SupermarketCategoryRelation, Sync, SyncLog, Unit, UnitConversion,
UserFile, UserPreference, UserSpace, ViewLog, ConnectorConfig)
from cookbook.templatetags.custom_tags import markdown
-from recipes.settings import AWS_ENABLED, MEDIA_URL
+from recipes.settings import AWS_ENABLED, MEDIA_URL, EMAIL_HOST
class WritableNestedModelSerializer(WNMS):
@@ -1338,7 +1338,7 @@ class InviteLinkSerializer(WritableNestedModelSerializer):
validated_data['space'] = self.context['request'].space
obj = super().create(validated_data)
- if obj.email:
+ if obj.email and EMAIL_HOST is not '':
try:
if InviteLink.objects.filter(space=self.context['request'].space,
created_at__gte=datetime.now() - timedelta(hours=4)).count() < 20:
diff --git a/vue3/src/components/settings/SpaceMemberSettings.vue b/vue3/src/components/settings/SpaceMemberSettings.vue
index 6525a7151..47e1520fd 100644
--- a/vue3/src/components/settings/SpaceMemberSettings.vue
+++ b/vue3/src/components/settings/SpaceMemberSettings.vue
@@ -3,16 +3,14 @@
{{ $t('SpaceMembers') }}
-
-
+
- {{ g.name }}
+ {{ g.name }}
-
@@ -21,25 +19,28 @@
{{ $t('Created') }} {{ DateTime.fromJSDate(spaceUserEditDialogUserSpace.createdAt).toLocaleString(DateTime.DATETIME_MED) }}
-
+
-
{{$t('Note')}}
-
{{spaceUserEditDialogUserSpace.internalNote}}
+
{{ $t('Note') }}
+
{{ spaceUserEditDialogUserSpace.internalNote }}
- {{ $t('Cancel') }}
+ {{ $t('Cancel') }}
{{ $t('Save') }}
- {{ $t('Invites') }} {{$t('New')}}
+ {{ $t('Invites') }}
+ {{ $t('New') }}
+
+
@@ -47,7 +48,7 @@
- {{$t('Invites')}}
+ {{ $t('Invites') }}
@@ -59,8 +60,12 @@
- {{ $t('Cancel') }}
- {{ $t('Create') }}
+ {{ $t('Cancel') }}
+
+ {{ $t('Create') }}
+ {{ $t('Update') }}
+
+ {{ $t('Delete') }}
@@ -77,7 +82,8 @@ import {ApiApi, Group, InviteLink, UserSpace} from "@/openapi";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {useI18n} from "vue-i18n";
import {DateTime} from "luxon";
-import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component is out of labs
+import {VDateInput} from 'vuetify/labs/VDateInput'
+import {useClipboard} from "@vueuse/core"; //TODO remove once component is out of labs
const {t} = useI18n()
@@ -90,6 +96,7 @@ const spaceUserEditDialogUserSpace = ref({} as UserSpace)
const inviteLinkDialogState = ref(false)
const inviteLinkDialogObject = ref({} as InviteLink)
+const inviteLinkDialogLoading = ref(false)
const userTableHeaders = [
{title: t('Username'), key: 'user.username'},
@@ -126,28 +133,78 @@ onMounted(() => {
})
})
+/**
+ * update user space in DB and list on client
+ * @param userSpace UserSpace object to update
+ */
function updateUserSpace(userSpace: UserSpace) {
const api = new ApiApi()
api.apiUserSpacePartialUpdate({id: userSpace.id!, patchedUserSpace: userSpace}).then(r => {
-
+ spaceUserSpaces.value.splice(spaceUserSpaces.value.indexOf(userSpace), 1, r)
+ useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
}
-function createInviteLink(inviteLink: InviteLink){
+/**
+ * create or update the invite link, refresh invite link list on client
+ * @param inviteLink InviteLink object to update
+ */
+function saveInviteLink(inviteLink: InviteLink) {
const api = new ApiApi()
- api.apiInviteLinkCreate({inviteLink: inviteLink}).then(r => {
+ inviteLinkDialogLoading.value = true
+
+ if (inviteLink.id == undefined) {
+ api.apiInviteLinkCreate({inviteLink: inviteLink}).then(r => {
+ inviteLinkDialogState.value = false
+ spaceInviteLinks.value.push(r)
+ useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
+ }).catch(err => {
+ useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
+ }).finally(() => {
+ inviteLinkDialogLoading.value = false
+ })
+ } else {
+ api.apiInviteLinkUpdate({inviteLink: inviteLink, id: inviteLink.id}).then(r => {
+ inviteLinkDialogState.value = false
+ spaceInviteLinks.value.splice(spaceInviteLinks.value.indexOf(inviteLink), 1, r)
+ useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
+ }).catch(err => {
+ useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
+ }).finally(() => {
+ inviteLinkDialogLoading.value = false
+ })
+ }
+
+}
+
+/**
+ * delete invite link from database and client
+ * @param inviteLink InviteLink object to delete
+ */
+function deleteInviteLink(inviteLink: InviteLink) {
+ const api = new ApiApi()
+ api.apiInviteLinkDestroy({id: inviteLink.id}).then(r => {
inviteLinkDialogState.value = false
- spaceInviteLinks.value.push(r)
- useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
+ spaceInviteLinks.value.splice(spaceInviteLinks.value.indexOf(inviteLink) - 1, 1)
+ useMessageStore().addPreparedMessage(PreparedMessage.DELETE_SUCCESS)
}).catch(err => {
- useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
+ useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
}
+/**
+ * copy invite link with url to clipboard
+ * @param inviteLink InviteLink object to copy
+ */
+function copyInviteLink(inviteLink: InviteLink) {
+ const {copy} = useClipboard()
+ copy(`${location.protocol}//${location.host}/invite/${inviteLink.uuid}`)
+}
+