Finished guestbook and gallery. started diary
This commit is contained in:
@@ -21,23 +21,14 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<ErrorDialog ref="errorDialog" />
|
||||
<AnswerContact ref="answerContactDialog" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import { mapGetters } from 'vuex';
|
||||
import ErrorDialog from '@/dialogues/standard/ErrorDialog.vue';
|
||||
import { formatDateTimeLong } from '@/utils/datetime.js';
|
||||
import AnswerContact from '../../dialogues/admin/AnswerContact.vue';
|
||||
|
||||
export default {
|
||||
name: 'AdminContactsView',
|
||||
components: {
|
||||
ErrorDialog,
|
||||
AnswerContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
contacts: []
|
||||
@@ -53,11 +44,11 @@ export default {
|
||||
const openContactRequests = await apiClient.get('/api/admin/opencontacts');
|
||||
this.contacts = openContactRequests.data;
|
||||
} catch (error) {
|
||||
this.$refs.errorDialog.open(`tr:error.${error.response.data.error}`);
|
||||
this.$root.$refs.errorDialog.open(`tr:error.${error.response.data.error}`);
|
||||
}
|
||||
},
|
||||
async openRequest(contact) {
|
||||
this.$refs.answerContactDialog.open(contact);
|
||||
this.$root.$refs.answerContactDialog.open(contact);
|
||||
},
|
||||
async finishRequest(contact) {
|
||||
await apiClient.get('/api/admin/opencontacts/finish/${contact.id}');
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
<button type="submit">{{ $t('activate.submit') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
<ErrorDialog ref="errorDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import ErrorDialog from '@/dialogues/standard/ErrorDialog.vue';
|
||||
|
||||
export default {
|
||||
name: 'ActivateView',
|
||||
@@ -27,9 +25,6 @@ export default {
|
||||
token: this.$route.query.token || ''
|
||||
};
|
||||
},
|
||||
components: {
|
||||
ErrorDialog,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user'])
|
||||
},
|
||||
@@ -43,7 +38,7 @@ export default {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error activating account:', error);
|
||||
this.$refs.errorDialog.open(this.$t('activate.failure'));
|
||||
this.$root.$refs.errorDialog.open(this.$t('activate.failure'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
<RandomChatDialog ref="randomChatDialog" />
|
||||
<RegisterDialog ref="registerDialog" />
|
||||
<PasswordResetDialog ref="passwordResetDialog" />
|
||||
<ErrorDialog ref="errorDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -48,7 +47,6 @@ import RegisterDialog from '@/dialogues/auth/RegisterDialog.vue';
|
||||
import PasswordResetDialog from '@/dialogues/auth/PasswordResetDialog.vue';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import { mapActions } from 'vuex';
|
||||
import ErrorDialog from '@/dialogues/standard/ErrorDialog.vue';
|
||||
|
||||
export default {
|
||||
name: 'HomeNoLoginView',
|
||||
@@ -62,7 +60,6 @@ export default {
|
||||
RandomChatDialog,
|
||||
RegisterDialog,
|
||||
PasswordResetDialog,
|
||||
ErrorDialog,
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['login']),
|
||||
@@ -80,7 +77,7 @@ export default {
|
||||
const response = await apiClient.post('/api/auth/login', { username: this.username, password: this.password });
|
||||
this.login(response.data);
|
||||
} catch (error) {
|
||||
this.$refs.errorDialog.open(`tr:error.${error.response.data.error}`);
|
||||
this.$root.$refs.errorDialog.open(`tr:error.${error.response.data.error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
<div class="gallery-view">
|
||||
<div class="sidebar">
|
||||
<h3>{{ $t('socialnetwork.gallery.folders') }}</h3>
|
||||
<ul>
|
||||
<ul class="tree">
|
||||
<folder-item v-for="folder in [folders]" :key="folder.id" :folder="folder"
|
||||
:selected-folder="selectedFolder" @select-folder="selectFolder" :isLastItem="true" :depth="0"
|
||||
:parentsWithChildren="[false]"></folder-item>
|
||||
:parentsWithChildren="[false]" @edit-folder="openEditFolderDialog" @delete-folder="deleteFolder">
|
||||
</folder-item>
|
||||
</ul>
|
||||
<button @click="openCreateFolderDialog">{{ $t('socialnetwork.gallery.create_folder') }}</button>
|
||||
</div>
|
||||
@@ -74,8 +75,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CreateFolderDialog ref="createFolderDialog" :parentFolder="selectedFolder" @created="handleFolderCreated" />
|
||||
<ImageDialog ref="imageDialog" :visibilityOptions="visibilityOptions" @save="saveImage" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -83,15 +82,11 @@ import apiClient from '@/utils/axios.js';
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import FolderItem from '../../components/FolderItem.vue';
|
||||
import 'vue-multiselect/dist/vue-multiselect.min.css';
|
||||
import CreateFolderDialog from '../../dialogues/socialnetwork/CreateFolderDialog.vue';
|
||||
import ImageDialog from '../../dialogues/socialnetwork/ImageDialog.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
FolderItem,
|
||||
Multiselect,
|
||||
CreateFolderDialog,
|
||||
ImageDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -154,7 +149,12 @@ export default {
|
||||
});
|
||||
},
|
||||
openCreateFolderDialog() {
|
||||
this.$refs.createFolderDialog.open();
|
||||
const parentFolder = this.selectedFolder || { id: null, name: this.$t('socialnetwork.gallery.root_folder') };
|
||||
Object.assign(this.$root.$refs.createFolderDialog, {
|
||||
parentFolder: parentFolder,
|
||||
folderId: 0,
|
||||
});
|
||||
this.$root.$refs.createFolderDialog.open();
|
||||
},
|
||||
async handleFolderCreated() {
|
||||
await this.loadFolders();
|
||||
@@ -209,7 +209,7 @@ export default {
|
||||
this.isUploadVisible = !this.isUploadVisible;
|
||||
},
|
||||
openImageDialog(image) {
|
||||
this.$refs.imageDialog.open(image);
|
||||
this.$root.$refs.editImageDialog.open(image);
|
||||
},
|
||||
async saveImage(updatedImage) {
|
||||
try {
|
||||
@@ -228,7 +228,34 @@ export default {
|
||||
console.error('Error saving image:', error);
|
||||
}
|
||||
},
|
||||
},
|
||||
openEditFolderDialog(folder) {
|
||||
const parentFolder = folder.parent || { id: null, name: this.$t('socialnetwork.gallery.root_folder') };
|
||||
Object.assign(this.$root.$refs.createFolderDialog, {
|
||||
parentFolder: parentFolder,
|
||||
folderId: folder.id,
|
||||
});
|
||||
this.$root.$refs.createFolderDialog.open(folder);
|
||||
},
|
||||
async deleteFolder(folder) {
|
||||
const folderName = folder.name;
|
||||
const confirmed = await this.$root.$refs.chooseDialog.open({
|
||||
title: this.$t('socialnetwork.gallery.delete_folder_confirmation_title'),
|
||||
message: this.$t('socialnetwork.gallery.delete_folder_confirmation_message').replace('%%folderName%%', folderName),
|
||||
});
|
||||
if (confirmed) {
|
||||
const deletedFolderIsCurrentFolder = folder.id === this.selectFolder.id;
|
||||
try {
|
||||
await apiClient.delete(`/api/socialnetwork/folders/${folder.id}`);
|
||||
await this.loadFolders();
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen des Ordners:', error);
|
||||
}
|
||||
if (deletedFolderIsCurrentFolder) {
|
||||
this.selectFolder = this.folders[0];
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -300,4 +327,21 @@ export default {
|
||||
object-fit: contain;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.tree {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
93
frontend/src/views/social/GuestbookView.vue
Normal file
93
frontend/src/views/social/GuestbookView.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<h2>{{ $t('socialnetwork.guestbook.title') }}</h2>
|
||||
<div>
|
||||
<div v-if="guestbookEntries.length === 0">{{ $t('socialnetwork.profile.guestbook.noEntries') }}
|
||||
</div>
|
||||
<div v-else class="guestbook-entries">
|
||||
<div v-for="entry in guestbookEntries" :key="entry.id" class="guestbook-entry">
|
||||
<img v-if="entry.image" :src="entry.image.url" alt="Entry Image"
|
||||
style="max-width: 400px; max-height: 400px;" />
|
||||
<p v-html="entry.contentHtml"></p>
|
||||
<div class="entry-info">
|
||||
<span class="entry-timestamp">{{ new Date(entry.createdAt).toLocaleString() }}</span>
|
||||
<span class="entry-user">
|
||||
<span @click="openProfile(entry.senderUsername)">{{ entry.sender }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<button @click="loadGuestbookEntries(currentPage - 1)" v-if="currentPage !== 1">{{
|
||||
$t('socialnetwork.guestbook.prevPage') }}</button>
|
||||
<span>{{ $t('socialnetwork.guestbook.page') }} {{ currentPage }} / {{ totalPages }}</span>
|
||||
<button @click="loadGuestbookEntries(currentPage + 1)" v-if="currentPage < totalPages">{{
|
||||
$t('socialnetwork.guestbook.nextPage')
|
||||
}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'GuestbookView',
|
||||
data() {
|
||||
return {
|
||||
guestbookEntries: [],
|
||||
currentPage: 1,
|
||||
totalPages: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['user']),
|
||||
},
|
||||
methods: {
|
||||
...mapActions('socialnetwork', ['fetchUserProfile']),
|
||||
openProfile(username) {
|
||||
this.$router.push({ name: 'profile', params: { username } });
|
||||
},
|
||||
async loadGuestbookEntries(page) {
|
||||
console.log(page);
|
||||
try {
|
||||
const response = await apiClient.get(`/api/socialnetwork/guestbook/entries/${this.user.username}/${page}`);
|
||||
this.guestbookEntries = response.data.entries;
|
||||
this.currentPage = page;
|
||||
this.totalPages = response.data.totalPages;
|
||||
this.guestbookEntries.forEach((entry) => {
|
||||
if (entry.withImage) {
|
||||
this.fetchGuestbookImage(this.user.username, entry);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Gästebucheinträge:', error);
|
||||
}
|
||||
console.log('page changed', this.currentPage);
|
||||
},
|
||||
async fetchGuestbookImage(guestbookOwnerName, entry) {
|
||||
try {
|
||||
const response = await apiClient.get(`/api/socialnetwork/guestbook/image/${this.user.username}/${entry.id}`, {
|
||||
responseType: 'blob',
|
||||
});
|
||||
entry.image = { url: URL.createObjectURL(response.data) };
|
||||
} catch (error) {
|
||||
console.error('Error fetching image:', error);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log('get it');
|
||||
this.loadGuestbookEntries(1);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.pagination {
|
||||
margin-top: 1em;
|
||||
background-color: #7BBE55;
|
||||
color: #fff;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
</style>
|
||||
@@ -52,19 +52,16 @@
|
||||
{{ $t('socialnetwork.usersearch.no_results') }}
|
||||
</div>
|
||||
</div>
|
||||
<UserProfileDialog ref="userProfileDialog" :username="selectedUsername" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Multiselect from 'vue-multiselect';
|
||||
import 'vue-multiselect/dist/vue-multiselect.min.css';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import UserProfileDialog from '@/dialogues/socialnetwork/UserProfileDialog.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Multiselect,
|
||||
UserProfileDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -108,8 +105,8 @@ export default {
|
||||
}
|
||||
},
|
||||
openUserProfile(id) {
|
||||
this.$refs.userProfileDialog.userId = id;
|
||||
this.$refs.userProfileDialog.open();
|
||||
this.$root.$refs.userProfileDialog.userId = id;
|
||||
this.$root.$refs.userProfileDialog.open();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user