- User with whom you want to share. The user will receive an
- email notification once you create this resource.
+ {{ $t('shareable-dialog.user-create-text') }}
-
+
- By default, the user has the ability to view the ressource.
- You can also allow th user to edit and delete this resource.
+ {{ $t('shareable-dialog.abilities-text') }}
- By default, the resource is shared until you manually remove
- the ability. If you prefer, you can also set an expiration
- date at which time the user will no longer be able to access
- this resource.
+ {{ $t('shareable-dialog.expiry-date-text') }}
-
+
@@ -70,9 +76,11 @@ const props = withDefaults(
shareableType: ShareableModel;
shareableModelId: number | string;
shareable: undefined | Shareable;
+ disabledUserIds?: number[];
}>(),
{
shareable: undefined,
+ disabledUserIds: () => [],
},
);
@@ -87,6 +95,12 @@ const isEditDialog = computed(() => {
return props.shareable != undefined;
});
+const tomorrow = computed(() => {
+ const date = new Date();
+ date.setDate(date.getDate() + 1);
+ return date.toISOString().substring(0, 10);
+});
+
const title = computed(() => {
if (!isEditDialog.value) {
switch (props.shareableType) {
@@ -121,7 +135,17 @@ const shareableService = new ShareableService(
props.shareableModelId,
);
+const loading = ref(false);
async function save() {
+ loading.value = true;
+
+ // date sent to server is in UTC, so we need to add the timezone offset
+ if (expires_at.value) {
+ const date = new Date(expires_at.value);
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
+ expires_at.value = date.toISOString();
+ }
+
if (props.shareable) {
const updatedShareable = await shareableService.update({
id: props.shareable.id,
@@ -130,7 +154,20 @@ async function save() {
expires_at: expires_at.value,
});
emit('updated', updatedShareable);
+ return;
+ }
+
+ if (!user_id.value) {
+ return;
}
+
+ const createShareable = await shareableService.create({
+ user_id: user_id.value,
+ can_edit: can_edit.value,
+ can_delete: can_delete.value,
+ expires_at: expires_at.value,
+ });
+ emit('created', createShareable);
}
diff --git a/resources/src/models/User/components/UserSelect.vue b/resources/src/models/User/components/UserSelect.vue
index 9aa73a7b..48b6b534 100644
--- a/resources/src/models/User/components/UserSelect.vue
+++ b/resources/src/models/User/components/UserSelect.vue
@@ -13,6 +13,7 @@
stack-label
outlined
:readonly="props.readonly"
+ :rules="rules"
:hide-hint="props.readonly"
hint="Start typing to search for an user (first name, last name, or email)"
@filter="filterUsers"
@@ -107,11 +108,13 @@ const props = withDefaults(
disabledEmails?: string[];
disabledIds?: number[];
readonly?: boolean;
+ required?: boolean;
}>(),
{
disabledEmails: () => [],
disabledIds: () => [],
readonly: false,
+ required: false,
},
);
@@ -131,7 +134,6 @@ watch(selectedUser, (user) => {
});
onMounted(async () => {
- console.log('here', props.modelValue);
if (props.modelValue) {
const user = await UserService.get(props.modelValue);
selectedUser.value = user;
@@ -154,6 +156,21 @@ const filterUsers = async (val: string, update, abort) => {
});
};
+const { t } = useI18n();
+const rules = computed(() => {
+ const rules = [
+ // required
+ (val: string | null) => {
+ console.log('required', val);
+ if (!props.required) return true;
+ const msg = t('common.required');
+ if (val === null) return msg;
+ return true;
+ },
+ ];
+ return rules;
+});
+
function createdUser(item: UserResource) {
userSelect.value?.updateInputValue('', true);
selectedUser.value = item;
diff --git a/tests/Feature/ManuscriptRecordSharingTest.php b/tests/Feature/ManuscriptRecordSharingTest.php
index 27271dd0..d7f7b922 100644
--- a/tests/Feature/ManuscriptRecordSharingTest.php
+++ b/tests/Feature/ManuscriptRecordSharingTest.php
@@ -265,3 +265,36 @@
$mailable = new ManuscriptRecordSharedMail($shareable);
$mailable->assertSeeInHtml('Never');
});
+
+test('a user cannot share the same manuscript twice to the same user', function(){
+
+ $manuscript = ManuscriptRecord::factory()->create();
+ $user = $manuscript->user;
+ $sharedUser = User::factory()->create();
+
+ $this->actingAs($user)->postJson('/api/manuscript-records/'.$manuscript->id.'/sharing', [
+ 'user_id' => $sharedUser->id,
+ 'can_edit' => true,
+ 'can_delete' => true,
+ 'expires_at' => '2023-11-17T18:22:52.080Z',
+ ])->assertCreated();
+
+ $this->actingAs($user)->postJson('/api/manuscript-records/'.$manuscript->id.'/sharing', [
+ 'user_id' => $sharedUser->id,
+ 'can_edit' => true,
+ 'can_delete' => true,
+ 'expires_at' => null,
+ ])->assertOk();
+
+ // should only be one shareable, with updated expiry...
+ $this->assertDatabaseCount('shareables', 1);
+ $this->assertDatabaseHas('shareables', [
+ 'shareable_type' => ManuscriptRecord::class,
+ 'shareable_id' => $manuscript->id,
+ 'user_id' => $sharedUser->id,
+ 'shared_by' => $user->id,
+ 'can_edit' => true,
+ 'can_delete' => true,
+ 'expires_at' => null,
+ ]);
+ });