feat(socialnetwork): enhance folder and video management with user visibility options

- Added functionality to manage selected users for adult folders and erotic videos, allowing for more granular visibility control.
- Introduced new endpoints and methods in the SocialNetworkController and SocialNetworkService to handle selected users.
- Updated the frontend components to include input fields for selected users in CreateFolderDialog, EditImageDialog, and EroticPicturesView.
- Enhanced the routing to support fetching erotic folders and videos by username, improving user experience in profile views.
This commit is contained in:
Torsten Schulz (local)
2026-03-27 16:56:45 +01:00
parent 39032570e3
commit 71e120bf20
13 changed files with 1081 additions and 36 deletions

View File

@@ -30,6 +30,15 @@
</template>
</multiselect>
</div>
<div v-if="requiresSelectedUsers" class="form-group">
<label for="selectedUsers">{{ $t("socialnetwork.gallery.visibility.selected-users") }}</label>
<input
id="selectedUsers"
type="text"
v-model="selectedUsernamesText"
placeholder="anna, bert, clara"
/>
</div>
</div>
</DialogWidget>
</template>
@@ -55,6 +64,7 @@ export default {
visibilityOptions: [],
allVisibilityOptions: [],
selectedVisibility: [],
selectedUsernamesText: '',
parentFolder: {id: null, name: ''},
folderId: 0,
eroticMode: false
@@ -65,6 +75,9 @@ export default {
buttons() {
return [{ text: this.$t("socialnetwork.gallery.create_folder"), action: this.createFolder }];
},
requiresSelectedUsers() {
return this.selectedVisibility.some(option => option?.description === 'selected-users');
}
},
async mounted() {
await this.loadVisibilityOptions();
@@ -79,9 +92,11 @@ export default {
this.selectedVisibility = this.visibilityOptions.filter(option =>
folder.visibilityTypeIds.includes(option.id)
);
this.selectedUsernamesText = (folder.selectedUsers || []).join(', ');
} else {
this.folderTitle = '';
this.selectedVisibility = [];
this.selectedUsernamesText = '';
}
this.$refs.dialog.open();
},
@@ -109,6 +124,10 @@ export default {
name: this.folderTitle,
parentId: this.parentFolder.id,
visibilities: this.selectedVisibility.map(item => item.id),
selectedUsers: this.selectedUsernamesText
.split(',')
.map(value => value.trim())
.filter(Boolean),
};
try {
const basePath = this.eroticMode ? '/api/socialnetwork/erotic/folders' : '/api/socialnetwork/folders';

View File

@@ -28,6 +28,15 @@
</template>
</multiselect>
</div>
<div v-if="requiresSelectedUsers" class="form-group">
<label for="selectedUsers">{{ $t('socialnetwork.gallery.visibility.selected-users') }}</label>
<input
id="selectedUsers"
type="text"
v-model="selectedUsernamesText"
placeholder="anna, bert, clara"
/>
</div>
</div>
</DialogWidget>
</template>
@@ -48,6 +57,7 @@ export default {
imageTitle: '',
selectedVisibilities: [],
visibilityOptions: [],
selectedUsernamesText: '',
};
},
computed: {
@@ -57,12 +67,16 @@ export default {
{ text: this.$t('socialnetwork.gallery.imagedialog.close'), action: this.closeDialog }
];
},
requiresSelectedUsers() {
return this.selectedVisibilities.some(option => option?.description === 'selected-users');
}
},
methods: {
open(image) {
this.image = image;
this.imageTitle = image.title;
this.selectedVisibilities = image.visibilities || [];
this.selectedUsernamesText = (image.selectedUsers || []).join(', ');
this.$refs.dialog.open();
},
closeDialog() {
@@ -73,6 +87,10 @@ export default {
...this.image,
title: this.imageTitle,
visibilities: this.selectedVisibilities,
selectedUsers: this.selectedUsernamesText
.split(',')
.map(value => value.trim())
.filter(Boolean),
};
try {

View File

@@ -23,6 +23,14 @@
<td>{{ generateValue(key, value) }}</td>
</tr>
</table>
<div v-if="canOpenEroticPictures" class="adult-actions">
<button type="button" @click="openEroticPictures">
{{ $t('socialnetwork.erotic.picturesTitle') }}
</button>
<button type="button" @click="openEroticVideos">
{{ $t('socialnetwork.erotic.videosTitle') }}
</button>
</div>
</div>
<div class="tab-content images-tab" v-if="activeTab === 'images'">
<div v-if="folders.length === 0">{{ $t('socialnetwork.profile.noFolders') }}</div>
@@ -98,6 +106,7 @@ import { Editor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
import DOMPurify from 'dompurify';
import { showError } from '@/utils/feedback.js';
import { mapGetters } from 'vuex';
export default {
name: 'UserProfileDialog',
@@ -106,6 +115,16 @@ export default {
FolderItem,
EditorContent,
},
computed: {
...mapGetters(['user']),
canOpenEroticPictures() {
return Boolean(
this.userProfile?.username &&
this.user?.username &&
this.userProfile.username !== this.user.username
);
}
},
data() {
return {
isTitleTranslated: true,
@@ -251,6 +270,24 @@ export default {
openImageDialog(image) {
this.$root.$refs.showImageDialog.open(image);
},
openEroticPictures() {
this.closeDialog();
this.$router.push({
name: 'EroticPictures',
query: {
username: this.userProfile.username
}
});
},
openEroticVideos() {
this.closeDialog();
this.$router.push({
name: 'EroticVideos',
query: {
username: this.userProfile.username
}
});
},
toggleInputSection() {
this.showInputSection = !this.showInputSection;
},
@@ -468,6 +505,10 @@ export default {
margin-bottom: 20px;
}
.adult-actions {
margin-top: 20px;
}
.form-group {
margin: 10px 0;
}