parent
af2527dd47
commit
6c9edb976f
@ -0,0 +1,9 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'UserLayout' |
||||||
|
} |
||||||
|
</script> |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'UserGroupLayout' |
||||||
|
} |
||||||
|
</script> |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'UserRelUserLayout' |
||||||
|
} |
||||||
|
</script> |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
export default { |
||||||
|
path: '/resources/users', |
||||||
|
meta: { requiresAuth: true }, |
||||||
|
name: 'users', |
||||||
|
component: () => import('../components/user/Layout.vue'), |
||||||
|
//redirect: { name: 'UserGroupList' },
|
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'UserGroupShow', |
||||||
|
//path: ':id',
|
||||||
|
path: 'show', |
||||||
|
component: () => import('../views/usergroup/Show.vue') |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
export default { |
||||||
|
path: '/resources/usergroups', |
||||||
|
meta: { requiresAuth: true }, |
||||||
|
name: 'usergroups', |
||||||
|
component: () => import('../components/usergroup/Layout.vue'), |
||||||
|
redirect: { name: 'UserGroupList' }, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'UserGroupList', |
||||||
|
path: '', |
||||||
|
component: () => import('../views/usergroup/List.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'UserGroupShow', |
||||||
|
//path: ':id',
|
||||||
|
path: 'show', |
||||||
|
component: () => import('../views/usergroup/Show.vue') |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
export default { |
||||||
|
path: '/resources/friends', |
||||||
|
meta: { requiresAuth: true }, |
||||||
|
name: 'friends', |
||||||
|
component: () => import('../components/userreluser/Layout.vue'), |
||||||
|
redirect: { name: 'UserGroupList' }, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'UserRelUserList', |
||||||
|
path: '', |
||||||
|
component: () => import('../views/userreluser/List.vue') |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'UserRelUserAdd', |
||||||
|
//path: ':id',
|
||||||
|
path: 'add', |
||||||
|
component: () => import('../views/userreluser/Add.vue') |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
import makeService from './api'; |
||||||
|
|
||||||
|
export default makeService('user'); |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
import makeService from './api'; |
||||||
|
|
||||||
|
export default makeService('usergroups'); |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
import makeService from './api'; |
||||||
|
|
||||||
|
export default makeService('user_rel_users'); |
||||||
@ -0,0 +1,563 @@ |
|||||||
|
<template> |
||||||
|
<Toolbar |
||||||
|
> |
||||||
|
<template v-slot:right> |
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="composeHandler"> |
||||||
|
<v-icon icon="mdi-email-plus-outline" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
:loading="isLoading" |
||||||
|
@click="reloadHandler"> |
||||||
|
<v-icon icon="mdi-refresh" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="confirmDeleteMultiple" |
||||||
|
:class="[ !selectedItems || !selectedItems.length ? 'hidden': '']" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-delete" /> |
||||||
|
</v-btn> |
||||||
|
<!-- :disabled="!selectedItems || !selectedItems.length"--> |
||||||
|
<v-btn |
||||||
|
icon |
||||||
|
tile |
||||||
|
@click="markAsUnReadMultiple" |
||||||
|
:class="[ !selectedItems || !selectedItems.length ? 'hidden': '']" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-email" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
:class="[ !selectedItems || !selectedItems.length ? 'hidden': '']" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-email-open" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
</template> |
||||||
|
</Toolbar> |
||||||
|
|
||||||
|
<div class="flex flex-row pt-2"> |
||||||
|
<div class="w-1/5 "> |
||||||
|
<v-card |
||||||
|
max-width="300" |
||||||
|
tile |
||||||
|
> |
||||||
|
<v-list dense> |
||||||
|
<!-- v-model="selectedItem"--> |
||||||
|
<v-list-item-group |
||||||
|
color="primary" |
||||||
|
> |
||||||
|
<v-list-item @click="goToInbox"> |
||||||
|
<v-list-item-icon> |
||||||
|
<v-icon icon="mdi-inbox"></v-icon> |
||||||
|
</v-list-item-icon> |
||||||
|
<v-list-item-content> |
||||||
|
<v-list-item-title>Inbox</v-list-item-title> |
||||||
|
</v-list-item-content> |
||||||
|
</v-list-item> |
||||||
|
|
||||||
|
<v-list-item @click="goToSent"> |
||||||
|
<v-list-item-icon> |
||||||
|
<v-icon icon="mdi-send-outline"></v-icon> |
||||||
|
</v-list-item-icon> |
||||||
|
<v-list-item-content> |
||||||
|
<v-list-item-title>Sent</v-list-item-title> |
||||||
|
</v-list-item-content> |
||||||
|
</v-list-item> |
||||||
|
|
||||||
|
<v-list-item @click="goToUnread"> |
||||||
|
<v-list-item-icon> |
||||||
|
<v-icon icon="mdi-email-outline"></v-icon> |
||||||
|
</v-list-item-icon> |
||||||
|
<v-list-item-content> |
||||||
|
<v-list-item-title>Unread</v-list-item-title> |
||||||
|
</v-list-item-content> |
||||||
|
</v-list-item> |
||||||
|
|
||||||
|
|
||||||
|
<v-list-item |
||||||
|
v-for="(tag, i) in tags" |
||||||
|
:key="i" |
||||||
|
@click="goToTag(tag)" |
||||||
|
> |
||||||
|
<v-list-item-icon> |
||||||
|
<v-icon icon="mdi-label-outline"></v-icon> |
||||||
|
</v-list-item-icon> |
||||||
|
<v-list-item-content> |
||||||
|
<v-list-item-title v-text="tag.tag"></v-list-item-title> |
||||||
|
</v-list-item-content> |
||||||
|
</v-list-item> |
||||||
|
</v-list-item-group> |
||||||
|
</v-list> |
||||||
|
</v-card> |
||||||
|
</div> |
||||||
|
<div class="w-4/5 pl-4"> |
||||||
|
<div class="text-h4 q-mb-md">{{ title }}</div> |
||||||
|
<DataTable |
||||||
|
class="p-datatable-sm" |
||||||
|
:value="items" |
||||||
|
v-model:selection="selectedItems" |
||||||
|
dataKey="id" |
||||||
|
v-model:filters="filters" |
||||||
|
filterDisplay="menu" |
||||||
|
sortBy="sendDate" |
||||||
|
sortOrder="asc" |
||||||
|
:lazy="true" |
||||||
|
:paginator="true" |
||||||
|
:rows="10" |
||||||
|
:totalRecords="totalItems" |
||||||
|
:loading="isLoading" |
||||||
|
@page="onPage($event)" |
||||||
|
@sort="sortingChanged($event)" |
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown" |
||||||
|
:rowsPerPageOptions="[5, 10, 20, 50]" |
||||||
|
responsiveLayout="scroll" |
||||||
|
currentPageReportTemplate="Showing {first} to {last} of {totalRecords}" |
||||||
|
:globalFilterFields="['title', 'sendDate']"> |
||||||
|
|
||||||
|
<Column selectionMode="multiple" style="width: 3rem" :exportable="false"></Column> |
||||||
|
|
||||||
|
<Column field="userSender" :header="$t('From')" :sortable="false"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<q-avatar size="40px"> |
||||||
|
<img :src="slotProps.data.userSender.illustrationUrl + '?w=80&h=80&fit=crop'" /> |
||||||
|
</q-avatar> |
||||||
|
|
||||||
|
<a |
||||||
|
v-if="slotProps.data" |
||||||
|
@click="showHandler(slotProps.data)" |
||||||
|
class="cursor-pointer" |
||||||
|
:class="[ true === slotProps.data.read ? 'font-normal': 'font-semibold']" |
||||||
|
> |
||||||
|
{{ slotProps.data.userSender.username }} |
||||||
|
</a> |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
|
||||||
|
<Column field="title" :header="$t('Title')" :sortable="false"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<a |
||||||
|
v-if="slotProps.data" |
||||||
|
@click="showHandler(slotProps.data)" |
||||||
|
class="cursor-pointer" |
||||||
|
v-bind:class="{ 'font-semibold': !slotProps.data.read }" |
||||||
|
> |
||||||
|
{{ slotProps.data.title }} |
||||||
|
</a> |
||||||
|
|
||||||
|
<div class="flex flex-row"> |
||||||
|
<v-chip v-for="tag in slotProps.data.tags" > |
||||||
|
{{ tag.tag }} |
||||||
|
</v-chip> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<!-- <template #filter="{filterModel}">--> |
||||||
|
<!-- <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by name"/>--> |
||||||
|
<!-- </template>--> |
||||||
|
<!-- --> |
||||||
|
|
||||||
|
<!-- <template #filter="{filterModel}">--> |
||||||
|
<!-- <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by title"/>--> |
||||||
|
<!-- </template>--> |
||||||
|
<!-- <template #filterclear="{filterCallback}">--> |
||||||
|
<!-- <Button type="button" icon="pi pi-times" @click="filterCallback()" class="p-button-secondary"></Button>--> |
||||||
|
<!-- </template>--> |
||||||
|
<!-- <template #filterapply="{filterCallback}">--> |
||||||
|
<!-- <Button type="button" icon="pi pi-check" @click="filterCallback()" class="p-button-success"></Button>--> |
||||||
|
<!-- </template>--> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column field="sendDate" :header="$t('Send date')" :sortable="true"> |
||||||
|
<template #body="slotProps"> |
||||||
|
{{$luxonDateTime.fromISO(slotProps.data.sendDate).toRelative() }} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column :exportable="false"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<div class="flex flex-row gap-2"> |
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="confirmDeleteItem(slotProps.data)" > |
||||||
|
<v-icon icon="mdi-delete" /> |
||||||
|
</v-btn> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
</DataTable> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<!-- Dialogs--> |
||||||
|
|
||||||
|
<Dialog v-model:visible="itemDialog" :style="{width: '450px'}" :header="$t('New folder')" :modal="true" class="p-fluid"> |
||||||
|
<div class="p-field"> |
||||||
|
<label for="name">{{ $t('Name') }}</label> |
||||||
|
<InputText |
||||||
|
autocomplete="off" |
||||||
|
id="title" |
||||||
|
v-model.trim="item.title" |
||||||
|
required="true" |
||||||
|
autofocus |
||||||
|
:class="{'p-invalid': submitted && !item.title}" |
||||||
|
/> |
||||||
|
<small class="p-error" v-if="submitted && !item.title">$t('Title is required')</small> |
||||||
|
</div> |
||||||
|
|
||||||
|
<template #footer> |
||||||
|
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/> |
||||||
|
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveItem" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteItemDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete <b>{{item.title}}</b>?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteItemDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteItemButton" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteMultipleDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete the selected items?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteMultipleDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteMultipleItems" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import ListMixin from '../../mixins/ListMixin'; |
||||||
|
import ActionCell from '../../components/ActionCell.vue'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue'; |
||||||
|
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue'; |
||||||
|
|
||||||
|
import {useRoute, useRouter} from 'vue-router' |
||||||
|
import DataFilter from '../../components/DataFilter'; |
||||||
|
import DocumentsFilterForm from '../../components/documents/Filter'; |
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'; |
||||||
|
import { useStore } from 'vuex'; |
||||||
|
import isEmpty from 'lodash/isEmpty'; |
||||||
|
import moment from "moment"; |
||||||
|
import toInteger from "lodash/toInteger"; |
||||||
|
import useState from "../../hooks/useState"; |
||||||
|
import axios from "axios"; |
||||||
|
import {ENTRYPOINT} from "../../config/entrypoint"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'UserGroupList', |
||||||
|
servicePrefix: 'usergroups', |
||||||
|
components: { |
||||||
|
Toolbar, |
||||||
|
ActionCell, |
||||||
|
ResourceFileIcon, |
||||||
|
ResourceFileLink, |
||||||
|
DocumentsFilterForm, |
||||||
|
DataFilter |
||||||
|
}, |
||||||
|
mixins: [ListMixin], |
||||||
|
setup() { |
||||||
|
const store = useStore(); |
||||||
|
const filters = ref([]); |
||||||
|
const filtersSent = ref([]); |
||||||
|
const user = store.getters["security/getUser"]; |
||||||
|
const tags = ref([]); |
||||||
|
const title = ref('Inbox'); |
||||||
|
|
||||||
|
filtersSent.value = { |
||||||
|
msgType: 2, |
||||||
|
userSender: user.id |
||||||
|
} |
||||||
|
|
||||||
|
// inbox |
||||||
|
filters.value = { |
||||||
|
msgType: 1, |
||||||
|
userReceiver: user.id |
||||||
|
}; |
||||||
|
|
||||||
|
// Get user tags. |
||||||
|
axios.get(ENTRYPOINT + 'message_tags', { |
||||||
|
params: { |
||||||
|
user: user['@id'] |
||||||
|
} |
||||||
|
}).then(response => { |
||||||
|
let data = response.data; |
||||||
|
tags.value = data['hydra:member']; |
||||||
|
}); |
||||||
|
|
||||||
|
function goToInbox() { |
||||||
|
title.value = 'Inbox'; |
||||||
|
filters.value = { |
||||||
|
msgType: 1, |
||||||
|
userReceiver: user.id, |
||||||
|
}; |
||||||
|
store.dispatch('message/resetList'); |
||||||
|
store.dispatch('message/fetchAll', filters.value); |
||||||
|
} |
||||||
|
|
||||||
|
function goToUnread() { |
||||||
|
title.value = 'Unread'; |
||||||
|
filters.value = { |
||||||
|
msgType: 1, |
||||||
|
userReceiver: user.id, |
||||||
|
read: false |
||||||
|
}; |
||||||
|
store.dispatch('message/resetList'); |
||||||
|
store.dispatch('message/fetchAll', filters.value); |
||||||
|
} |
||||||
|
|
||||||
|
function goToSent() { |
||||||
|
title.value = 'Sent'; |
||||||
|
filters.value = { |
||||||
|
msgType: 2, |
||||||
|
userSender: user.id |
||||||
|
}; |
||||||
|
store.dispatch('message/resetList'); |
||||||
|
store.dispatch('message/fetchAll', filters.value); |
||||||
|
} |
||||||
|
|
||||||
|
function goToTag(tag) { |
||||||
|
title.value = tag.tag; |
||||||
|
filters.value = { |
||||||
|
msgType: 1, |
||||||
|
userReceiver: user.id, |
||||||
|
tags: [tag] |
||||||
|
}; |
||||||
|
store.dispatch('message/resetList'); |
||||||
|
store.dispatch('message/fetchAll', filters.value); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
goToInbox, |
||||||
|
goToSent, |
||||||
|
goToTag, |
||||||
|
goToUnread, |
||||||
|
tags, |
||||||
|
filters, |
||||||
|
title, |
||||||
|
} |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
columns: [ |
||||||
|
{ label: this.$i18n.t('Title'), field: 'title', name: 'title', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Sender'), field: 'userSender', name: 'userSender', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Modified'), field: 'sendDate', name: 'updatedAt', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Actions'), name: 'action', sortable: false} |
||||||
|
], |
||||||
|
pageOptions: [10, 20, 50, this.$i18n.t('All')], |
||||||
|
selected: [], |
||||||
|
isBusy: false, |
||||||
|
options: { |
||||||
|
sortBy: 'sendDate', |
||||||
|
sortDesc: 'asc', |
||||||
|
}, |
||||||
|
selectedItems: [], |
||||||
|
// prime vue |
||||||
|
itemDialog: false, |
||||||
|
deleteItemDialog: false, |
||||||
|
deleteMultipleDialog: false, |
||||||
|
item: {}, |
||||||
|
submitted: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
// From crud.js list function |
||||||
|
...mapGetters('resourcenode', { |
||||||
|
resourceNode: 'getResourceNode' |
||||||
|
}), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
|
||||||
|
...mapGetters('message', { |
||||||
|
items: 'list', |
||||||
|
}), |
||||||
|
|
||||||
|
//...getters |
||||||
|
|
||||||
|
// From ListMixin |
||||||
|
...mapFields('message', { |
||||||
|
deletedItem: 'deleted', |
||||||
|
error: 'error', |
||||||
|
isLoading: 'isLoading', |
||||||
|
resetList: 'resetList', |
||||||
|
totalItems: 'totalItems', |
||||||
|
view: 'view' |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
composeHandler() { |
||||||
|
let folderParams = this.$route.query; |
||||||
|
this.$router.push({ name: `${this.$options.servicePrefix}Create` , query: folderParams}); |
||||||
|
}, |
||||||
|
|
||||||
|
// prime |
||||||
|
onPage(event) { |
||||||
|
this.options.itemsPerPage = event.rows; |
||||||
|
this.options.page = event.page + 1; |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
sortingChanged(event) { |
||||||
|
console.log('sortingChanged'); |
||||||
|
console.log(event); |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
// ctx.sortBy ==> Field key for sorting by (or null for no sorting) |
||||||
|
// ctx.sortDesc ==> true if sorting descending, false otherwise |
||||||
|
}, |
||||||
|
openNew() { |
||||||
|
this.item = {}; |
||||||
|
this.submitted = false; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
hideDialog() { |
||||||
|
this.itemDialog = false; |
||||||
|
this.submitted = false; |
||||||
|
}, |
||||||
|
saveItem() { |
||||||
|
this.submitted = true; |
||||||
|
|
||||||
|
if (this.item.title.trim()) { |
||||||
|
if (this.item.id) { |
||||||
|
} else { |
||||||
|
//this.products.push(this.product); |
||||||
|
this.item.filetype = 'folder'; |
||||||
|
this.item.parentResourceNodeId = this.$route.params.node; |
||||||
|
this.item.resourceLinkList = JSON.stringify([{ |
||||||
|
gid: this.$route.query.gid, |
||||||
|
sid: this.$route.query.sid, |
||||||
|
cid: this.$route.query.cid, |
||||||
|
visibility: 2, // visible by default |
||||||
|
}]); |
||||||
|
|
||||||
|
this.create(this.item); |
||||||
|
this.showMessage('Saved'); |
||||||
|
} |
||||||
|
|
||||||
|
this.itemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
} |
||||||
|
}, |
||||||
|
editItem(item) { |
||||||
|
this.item = {...item}; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteItem(item) { |
||||||
|
this.item = item; |
||||||
|
this.deleteItemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteMultiple() { |
||||||
|
this.deleteMultipleDialog = true; |
||||||
|
}, |
||||||
|
markAsReadMultiple(){ |
||||||
|
console.log('markAsReadMultiple'); |
||||||
|
this.selectedItems.forEach(message => { |
||||||
|
message.read = true; |
||||||
|
this.update(message); |
||||||
|
}); |
||||||
|
this.selectedItems = null; |
||||||
|
this.resetList = true; |
||||||
|
}, |
||||||
|
reloadHandler() { |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
markAsUnReadMultiple(){ |
||||||
|
console.log('markAsUnReadMultiple'); |
||||||
|
this.selectedItems.forEach(message => { |
||||||
|
message.read = false; |
||||||
|
this.update(message); |
||||||
|
}); |
||||||
|
this.selectedItems = null; |
||||||
|
this.resetList = true; |
||||||
|
//this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
deleteMultipleItems() { |
||||||
|
console.log('deleteMultipleItems'); |
||||||
|
console.log(this.selectedItems); |
||||||
|
this.deleteMultipleAction(this.selectedItems); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
this.deleteMultipleDialog = false; |
||||||
|
this.selectedItems = null; |
||||||
|
//this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
deleteItemButton() { |
||||||
|
console.log('deleteItem'); |
||||||
|
this.deleteItem(this.item); |
||||||
|
//this.items = this.items.filter(val => val.iid !== this.item.iid); |
||||||
|
this.deleteItemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
onRowSelected(items) { |
||||||
|
this.selected = items |
||||||
|
}, |
||||||
|
selectAllRows() { |
||||||
|
this.$refs.selectableTable.selectAllRows() |
||||||
|
}, |
||||||
|
clearSelected() { |
||||||
|
this.$refs.selectableTable.clearSelected() |
||||||
|
}, |
||||||
|
async deleteSelected() { |
||||||
|
console.log('deleteSelected'); |
||||||
|
/*for (let i = 0; i < this.selected.length; i++) { |
||||||
|
let item = this.selected[i]; |
||||||
|
//this.deleteHandler(item); |
||||||
|
this.deleteItem(item); |
||||||
|
}*/ |
||||||
|
|
||||||
|
this.deleteMultipleAction(this.selected); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
}, |
||||||
|
//...actions, |
||||||
|
// From ListMixin |
||||||
|
...mapActions('message', { |
||||||
|
getPage: 'fetchAll', |
||||||
|
create: 'create', |
||||||
|
update: 'update', |
||||||
|
deleteItem: 'del', |
||||||
|
deleteMultipleAction: 'delMultiple' |
||||||
|
}), |
||||||
|
...mapActions('resourcenode', { |
||||||
|
findResourceNode: 'findResourceNode', |
||||||
|
}), |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
@ -0,0 +1,242 @@ |
|||||||
|
<template> |
||||||
|
<div v-if="item"> |
||||||
|
<Toolbar |
||||||
|
:handle-delete="del" |
||||||
|
> |
||||||
|
<template v-slot:right> |
||||||
|
<!-- <v-toolbar-title v-if="item">--> |
||||||
|
<!-- {{--> |
||||||
|
<!-- `${$options.servicePrefix} ${item['@id']}`--> |
||||||
|
<!-- }}--> |
||||||
|
<!-- </v-toolbar-title>--> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
:loading="isLoading" |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="reply" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-reply" /> |
||||||
|
</v-btn> |
||||||
|
</template> |
||||||
|
</Toolbar> |
||||||
|
|
||||||
|
<VueMultiselect |
||||||
|
placeholder="Tags" |
||||||
|
v-model="item.tags" |
||||||
|
:loading="isLoadingSelect" |
||||||
|
tag-placeholder="Add this as new tag" |
||||||
|
:options="tags" |
||||||
|
:multiple="true" |
||||||
|
:searchable="true" |
||||||
|
:internal-search="false" |
||||||
|
@search-change="asyncFind" |
||||||
|
|
||||||
|
@select="addTagToMessage" |
||||||
|
@remove="removeTagFromMessage" |
||||||
|
|
||||||
|
:taggable="true" |
||||||
|
@tag="addTag" |
||||||
|
label="tag" |
||||||
|
track-by="id" |
||||||
|
/> |
||||||
|
|
||||||
|
<p class="text-lg"> |
||||||
|
From: |
||||||
|
<q-avatar size="32px"> |
||||||
|
<img :src="item['userSender']['illustrationUrl'] + '?w=80&h=80&fit=crop'" /> |
||||||
|
<!-- <q-icon name="person" ></q-icon>--> |
||||||
|
</q-avatar> |
||||||
|
{{ item['userSender']['username'] }} |
||||||
|
</p> |
||||||
|
|
||||||
|
<p class="text-lg"> |
||||||
|
{{ $luxonDateTime.fromISO(item['sendDate']).toRelative() }} |
||||||
|
</p> |
||||||
|
|
||||||
|
<p class="text-lg"> |
||||||
|
<h3>{{ item.title }}</h3> |
||||||
|
</p> |
||||||
|
|
||||||
|
<div class="flex flex-row"> |
||||||
|
<div class="w-full"> |
||||||
|
<p v-html="item.content" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<Loading :visible="isLoading" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<style src="vue-multiselect/dist/vue-multiselect.css"></style> |
||||||
|
|
||||||
|
<script> |
||||||
|
import {mapActions, mapGetters, useStore} from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import Loading from '../../components/Loading.vue'; |
||||||
|
import ShowMixin from '../../mixins/ShowMixin'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import VueMultiselect from 'vue-multiselect' |
||||||
|
import {computed, ref} from "vue"; |
||||||
|
import isEmpty from "lodash/isEmpty"; |
||||||
|
import axios from "axios"; |
||||||
|
import {ENTRYPOINT} from "../../config/entrypoint"; |
||||||
|
import useVuelidate from "@vuelidate/core"; |
||||||
|
import {useRoute, useRouter} from "vue-router"; |
||||||
|
import NotificationMixin from "../../mixins/NotificationMixin"; |
||||||
|
|
||||||
|
const servicePrefix = 'usergroups'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'UserGroupShow', |
||||||
|
components: { |
||||||
|
Loading, |
||||||
|
Toolbar, |
||||||
|
VueMultiselect |
||||||
|
}, |
||||||
|
setup () { |
||||||
|
const tags = ref([]); |
||||||
|
const isLoadingSelect = ref(false); |
||||||
|
const store = useStore(); |
||||||
|
const user = store.getters["security/getUser"]; |
||||||
|
const find = store.getters["message/find"]; |
||||||
|
const route = useRoute(); |
||||||
|
const router = useRouter(); |
||||||
|
|
||||||
|
let id = route.params.id; |
||||||
|
if (isEmpty(id)) { |
||||||
|
id = route.query.id; |
||||||
|
} |
||||||
|
|
||||||
|
console.log(id); |
||||||
|
console.log(decodeURIComponent(id)); |
||||||
|
|
||||||
|
let item = find(decodeURIComponent(id)); |
||||||
|
|
||||||
|
// Change to read |
||||||
|
if (false === item.read) { |
||||||
|
axios.put(ENTRYPOINT + 'messages/' + item.id, { |
||||||
|
read: true, |
||||||
|
}).then(response => { |
||||||
|
console.log(response); |
||||||
|
}).catch(function (error) { |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function addTag(newTag) { |
||||||
|
axios.post(ENTRYPOINT + 'message_tags', { |
||||||
|
user: user['@id'], |
||||||
|
tag: newTag, |
||||||
|
}).then(response => { |
||||||
|
addTagToMessage(response.data); |
||||||
|
//this.showMessage('Added'); |
||||||
|
item.tags.push(response.data); |
||||||
|
console.log(response); |
||||||
|
isLoadingSelect.value = false; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function addTagToMessage(newTag) { |
||||||
|
console.log('addTagToMessage'); |
||||||
|
let tagsToUpdate = []; |
||||||
|
item.tags.forEach(tagItem => { |
||||||
|
tagsToUpdate.push(tagItem['@id']); |
||||||
|
}); |
||||||
|
tagsToUpdate.push(newTag['@id']); |
||||||
|
console.log(tagsToUpdate); |
||||||
|
|
||||||
|
axios.put(ENTRYPOINT + 'messages/' + item.id, { |
||||||
|
tags: tagsToUpdate, |
||||||
|
}).then(response => { |
||||||
|
//this.showMessage('Added'); |
||||||
|
console.log(response); |
||||||
|
isLoadingSelect.value = false; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function removeTagFromMessage() { |
||||||
|
let tagsToUpdate = []; |
||||||
|
item.tags.forEach(tagItem => { |
||||||
|
tagsToUpdate.push(tagItem['@id']); |
||||||
|
}); |
||||||
|
|
||||||
|
axios.put(ENTRYPOINT + 'messages/' + item.id, { |
||||||
|
tags: tagsToUpdate, |
||||||
|
}).then(response => { |
||||||
|
console.log(response); |
||||||
|
isLoadingSelect.value = false; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
axios.get(ENTRYPOINT + 'message_tags', { |
||||||
|
params: { |
||||||
|
user: user['@id'] |
||||||
|
} |
||||||
|
}).then(response => { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
let data = response.data; |
||||||
|
tags.value = data['hydra:member']; |
||||||
|
}); |
||||||
|
|
||||||
|
function reply() { |
||||||
|
let params = route.query; |
||||||
|
router.push({name: `${servicePrefix}Reply`, query: params}); |
||||||
|
} |
||||||
|
|
||||||
|
function asyncFind (query) { |
||||||
|
if (query.toString().length < 3) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
isLoadingSelect.value = true; |
||||||
|
axios.get(ENTRYPOINT + 'message_tags', { |
||||||
|
params: { |
||||||
|
user: user['@id'] |
||||||
|
} |
||||||
|
}).then(response => { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
let data = response.data; |
||||||
|
tags.value = data['hydra:member']; |
||||||
|
|
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
v$: useVuelidate(), tags, isLoadingSelect, item, |
||||||
|
addTag, addTagToMessage, removeTagFromMessage, asyncFind, reply |
||||||
|
}; |
||||||
|
}, |
||||||
|
mixins: [ShowMixin, NotificationMixin], |
||||||
|
computed: { |
||||||
|
...mapFields('message', { |
||||||
|
isLoading: 'isLoading' |
||||||
|
}), |
||||||
|
...mapGetters('message', ['find']), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions('message', { |
||||||
|
deleteItem: 'del', |
||||||
|
reset: 'resetShow', |
||||||
|
retrieve: 'loadWithQuery' |
||||||
|
}), |
||||||
|
}, |
||||||
|
servicePrefix |
||||||
|
}; |
||||||
|
</script> |
||||||
@ -0,0 +1,190 @@ |
|||||||
|
<template> |
||||||
|
<Toolbar > |
||||||
|
<template v-slot:right> |
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
:loading="isLoading" |
||||||
|
@click="reloadHandler"> |
||||||
|
<v-icon icon="mdi-account-plus-outline" /> |
||||||
|
</v-btn> |
||||||
|
</template> |
||||||
|
</Toolbar> |
||||||
|
|
||||||
|
<div class="flex flex-row pt-2"> |
||||||
|
<div class="w-full"> |
||||||
|
<div class="text-h4 q-mb-md">Search</div> |
||||||
|
|
||||||
|
<VueMultiselect |
||||||
|
placeholder="Add" |
||||||
|
|
||||||
|
:loading="isLoadingSelect" |
||||||
|
:options="users" |
||||||
|
:multiple="true" |
||||||
|
:searchable="true" |
||||||
|
:internal-search="false" |
||||||
|
@search-change="asyncFind" |
||||||
|
|
||||||
|
@select="addFriend" |
||||||
|
limit-text="3" |
||||||
|
limit="3" |
||||||
|
label="username" |
||||||
|
track-by="id" |
||||||
|
/> |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<style src="vue-multiselect/dist/vue-multiselect.css"></style> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import ListMixin from '../../mixins/ListMixin'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
|
||||||
|
import VueMultiselect from 'vue-multiselect' |
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'; |
||||||
|
import { useStore } from 'vuex'; |
||||||
|
import axios from "axios"; |
||||||
|
import {ENTRYPOINT} from "../../config/entrypoint"; |
||||||
|
import useVuelidate from "@vuelidate/core"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'UserRelUserAdd', |
||||||
|
servicePrefix: 'userreluser', |
||||||
|
components: { |
||||||
|
Toolbar, |
||||||
|
VueMultiselect |
||||||
|
}, |
||||||
|
mixins: [ListMixin], |
||||||
|
setup() { |
||||||
|
const users = ref([]); |
||||||
|
const isLoadingSelect = ref(false); |
||||||
|
const store = useStore(); |
||||||
|
const user = store.getters["security/getUser"]; |
||||||
|
|
||||||
|
function asyncFind (query) { |
||||||
|
if (query.toString().length < 3) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
isLoadingSelect.value = true; |
||||||
|
axios.get(ENTRYPOINT + 'users', { |
||||||
|
params: { |
||||||
|
username: query |
||||||
|
} |
||||||
|
}).then(response => { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
let data = response.data; |
||||||
|
users.value = data['hydra:member']; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function addFriend(friend) { |
||||||
|
axios.post(ENTRYPOINT + 'user_rel_users', { |
||||||
|
user: user['@id'], |
||||||
|
friend: friend['@id'], |
||||||
|
relationType: 10, |
||||||
|
}).then(response => { |
||||||
|
console.log(response); |
||||||
|
isLoadingSelect.value = false; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return {v$: useVuelidate(), users, asyncFind, addFriend, isLoadingSelect}; |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
selected: [], |
||||||
|
isBusy: false, |
||||||
|
options: { |
||||||
|
sortBy: 'sendDate', |
||||||
|
sortDesc: 'asc', |
||||||
|
}, |
||||||
|
selectedItems: [], |
||||||
|
// prime vue |
||||||
|
itemDialog: false, |
||||||
|
deleteItemDialog: false, |
||||||
|
deleteMultipleDialog: false, |
||||||
|
item: {}, |
||||||
|
submitted: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
// From crud.js list function |
||||||
|
...mapGetters('resourcenode', { |
||||||
|
resourceNode: 'getResourceNode' |
||||||
|
}), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
|
||||||
|
...mapGetters('message', { |
||||||
|
items: 'list', |
||||||
|
}), |
||||||
|
|
||||||
|
//...getters |
||||||
|
|
||||||
|
// From ListMixin |
||||||
|
...mapFields('message', { |
||||||
|
deletedItem: 'deleted', |
||||||
|
error: 'error', |
||||||
|
isLoading: 'isLoading', |
||||||
|
resetList: 'resetList', |
||||||
|
totalItems: 'totalItems', |
||||||
|
view: 'view' |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
deleteItemButton() { |
||||||
|
console.log('deleteItem'); |
||||||
|
this.deleteItem(this.item); |
||||||
|
//this.items = this.items.filter(val => val.iid !== this.item.iid); |
||||||
|
this.deleteItemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
onRowSelected(items) { |
||||||
|
this.selected = items |
||||||
|
}, |
||||||
|
selectAllRows() { |
||||||
|
this.$refs.selectableTable.selectAllRows() |
||||||
|
}, |
||||||
|
clearSelected() { |
||||||
|
this.$refs.selectableTable.clearSelected() |
||||||
|
}, |
||||||
|
async deleteSelected() { |
||||||
|
this.deleteMultipleAction(this.selected); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
}, |
||||||
|
//...actions, |
||||||
|
// From ListMixin |
||||||
|
...mapActions('userreluser', { |
||||||
|
getPage: 'fetchAll', |
||||||
|
create: 'create', |
||||||
|
update: 'update', |
||||||
|
deleteItem: 'del', |
||||||
|
deleteMultipleAction: 'delMultiple' |
||||||
|
}), |
||||||
|
...mapActions('resourcenode', { |
||||||
|
findResourceNode: 'findResourceNode', |
||||||
|
}), |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
@ -0,0 +1,381 @@ |
|||||||
|
<template> |
||||||
|
<Toolbar > |
||||||
|
<template v-slot:right> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
:loading="isLoading" |
||||||
|
:to="'/resources/friends/add'" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-account-plus-outline" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
:loading="isLoading" |
||||||
|
@click="reloadHandler" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-refresh" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="confirmDeleteMultiple" |
||||||
|
:class="[ !selectedItems || !selectedItems.length ? 'hidden': '']" |
||||||
|
> |
||||||
|
<v-icon icon="mdi-delete" /> |
||||||
|
</v-btn> |
||||||
|
<!-- :disabled="!selectedItems || !selectedItems.length"--> |
||||||
|
|
||||||
|
</template> |
||||||
|
</Toolbar> |
||||||
|
|
||||||
|
<div class="flex flex-row pt-2"> |
||||||
|
<div class="w-full"> |
||||||
|
<div class="text-h4 q-mb-md">Friends</div> |
||||||
|
<DataTable |
||||||
|
class="p-datatable-sm" |
||||||
|
:value="items" |
||||||
|
v-model:selection="selectedItems" |
||||||
|
dataKey="id" |
||||||
|
v-model:filters="filters" |
||||||
|
filterDisplay="menu" |
||||||
|
sortBy="sendDate" |
||||||
|
sortOrder="asc" |
||||||
|
:lazy="true" |
||||||
|
:paginator="false" |
||||||
|
:totalRecords="totalItems" |
||||||
|
:loading="isLoading" |
||||||
|
@page="onPage($event)" |
||||||
|
@sort="sortingChanged($event)" |
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown" |
||||||
|
:rowsPerPageOptions="[5, 10, 20, 50]" |
||||||
|
responsiveLayout="scroll" |
||||||
|
currentPageReportTemplate="Showing {first} to {last} of {totalRecords}" |
||||||
|
> |
||||||
|
|
||||||
|
<Column selectionMode="multiple" style="width: 3rem" :exportable="false"></Column> |
||||||
|
|
||||||
|
<Column field="userSender" :header="$t('User')" :sortable="false"> |
||||||
|
<template #body="slotProps"> |
||||||
|
<q-avatar size="40px"> |
||||||
|
<img :src="slotProps.data.friend.illustrationUrl + '?w=80&h=80&fit=crop'" /> |
||||||
|
</q-avatar> |
||||||
|
{{ slotProps.data.friend.username }} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column field="createdAt" :header="$t('Sent date')" :sortable="true"> |
||||||
|
<template #body="slotProps"> |
||||||
|
{{$luxonDateTime.fromISO(slotProps.data.createdAt).toRelative() }} |
||||||
|
</template> |
||||||
|
</Column> |
||||||
|
|
||||||
|
<Column :exportable="false"> |
||||||
|
|
||||||
|
<template #body="slotProps"> |
||||||
|
<!-- class="flex flex-row gap-2"--> |
||||||
|
|
||||||
|
<v-icon v-if="slotProps.data.relationType == 3" icon="mdi-check" /> |
||||||
|
|
||||||
|
|
||||||
|
<v-btn |
||||||
|
v-if="slotProps.data.relationType == 10" |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="addFriend(slotProps.data)" > |
||||||
|
<v-icon icon="mdi-plus" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
tile |
||||||
|
icon |
||||||
|
@click="confirmDeleteItem(slotProps.data)" > |
||||||
|
<v-icon icon="mdi-delete" /> |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
</Column> |
||||||
|
</DataTable> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<Dialog v-model:visible="itemDialog" :style="{width: '450px'}" :header="$t('New folder')" :modal="true" class="p-fluid"> |
||||||
|
<div class="p-field"> |
||||||
|
<label for="name">{{ $t('Name') }}</label> |
||||||
|
<InputText |
||||||
|
autocomplete="off" |
||||||
|
id="title" |
||||||
|
v-model.trim="item.title" |
||||||
|
required="true" |
||||||
|
autofocus |
||||||
|
:class="{'p-invalid': submitted && !item.title}" |
||||||
|
/> |
||||||
|
<small class="p-error" v-if="submitted && !item.title">$t('Title is required')</small> |
||||||
|
</div> |
||||||
|
|
||||||
|
<template #footer> |
||||||
|
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/> |
||||||
|
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveItem" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteItemDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete <b>{{item.title}}</b>?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteItemDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteItemButton" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
|
||||||
|
<Dialog v-model:visible="deleteMultipleDialog" :style="{width: '450px'}" header="Confirm" :modal="true"> |
||||||
|
<div class="confirmation-content"> |
||||||
|
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" /> |
||||||
|
<span v-if="item">Are you sure you want to delete the selected items?</span> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteMultipleDialog = false"/> |
||||||
|
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteMultipleItems" /> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapActions, mapGetters } from 'vuex'; |
||||||
|
import { mapFields } from 'vuex-map-fields'; |
||||||
|
import ListMixin from '../../mixins/ListMixin'; |
||||||
|
import ActionCell from '../../components/ActionCell.vue'; |
||||||
|
import Toolbar from '../../components/Toolbar.vue'; |
||||||
|
import ResourceFileIcon from '../../components/documents/ResourceFileIcon.vue'; |
||||||
|
import ResourceFileLink from '../../components/documents/ResourceFileLink.vue'; |
||||||
|
|
||||||
|
import DataFilter from '../../components/DataFilter'; |
||||||
|
import DocumentsFilterForm from '../../components/documents/Filter'; |
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'; |
||||||
|
import { useStore } from 'vuex'; |
||||||
|
import axios from "axios"; |
||||||
|
import {ENTRYPOINT} from "../../config/entrypoint"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'UserRelUserList', |
||||||
|
servicePrefix: 'userreluser', |
||||||
|
components: { |
||||||
|
Toolbar, |
||||||
|
}, |
||||||
|
mixins: [ListMixin], |
||||||
|
setup() { |
||||||
|
const store = useStore(); |
||||||
|
const user = store.getters["security/getUser"]; |
||||||
|
|
||||||
|
const isLoadingSelect = ref(false); |
||||||
|
function addFriend(friend) { |
||||||
|
axios.put(friend['@id'], { |
||||||
|
relationType: 3, |
||||||
|
}).then(response => { |
||||||
|
console.log(response); |
||||||
|
isLoadingSelect.value = false; |
||||||
|
}).catch(function (error) { |
||||||
|
isLoadingSelect.value = false; |
||||||
|
console.log(error); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
addFriend, |
||||||
|
} |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
columns: [ |
||||||
|
{ label: this.$i18n.t('User'), field: 'friend.username', name: 'friend', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Sent'), field: 'createdAt', name: 'createdAt', sortable: true}, |
||||||
|
{ label: this.$i18n.t('Actions'), name: 'action', sortable: false} |
||||||
|
], |
||||||
|
pageOptions: [10, 20, 50, this.$i18n.t('All')], |
||||||
|
selected: [], |
||||||
|
isBusy: false, |
||||||
|
selectedItems: [], |
||||||
|
// prime vue |
||||||
|
itemDialog: false, |
||||||
|
deleteItemDialog: false, |
||||||
|
deleteMultipleDialog: false, |
||||||
|
item: {}, |
||||||
|
submitted: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
console.log('mounted'); |
||||||
|
this.filters = { |
||||||
|
friend: this.currentUser.id |
||||||
|
}; |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
// From crud.js list function |
||||||
|
...mapGetters('resourcenode', { |
||||||
|
resourceNode: 'getResourceNode' |
||||||
|
}), |
||||||
|
...mapGetters({ |
||||||
|
'isAuthenticated': 'security/isAuthenticated', |
||||||
|
'isAdmin': 'security/isAdmin', |
||||||
|
'currentUser': 'security/getUser', |
||||||
|
}), |
||||||
|
|
||||||
|
...mapGetters('userreluser', { |
||||||
|
items: 'list', |
||||||
|
}), |
||||||
|
|
||||||
|
//...getters |
||||||
|
|
||||||
|
// From ListMixin |
||||||
|
...mapFields('userreluser', { |
||||||
|
deletedItem: 'deleted', |
||||||
|
error: 'error', |
||||||
|
isLoading: 'isLoading', |
||||||
|
resetList: 'resetList', |
||||||
|
totalItems: 'totalItems', |
||||||
|
view: 'view' |
||||||
|
}), |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
// prime |
||||||
|
onPage(event) { |
||||||
|
this.options.itemsPerPage = event.rows; |
||||||
|
this.options.page = event.page + 1; |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
sortingChanged(event) { |
||||||
|
console.log('sortingChanged'); |
||||||
|
console.log(event); |
||||||
|
this.options.sortBy = event.sortField; |
||||||
|
this.options.sortDesc = event.sortOrder === -1; |
||||||
|
|
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
// ctx.sortBy ==> Field key for sorting by (or null for no sorting) |
||||||
|
// ctx.sortDesc ==> true if sorting descending, false otherwise |
||||||
|
}, |
||||||
|
openNew() { |
||||||
|
this.item = {}; |
||||||
|
this.submitted = false; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
hideDialog() { |
||||||
|
this.itemDialog = false; |
||||||
|
this.submitted = false; |
||||||
|
}, |
||||||
|
saveItem() { |
||||||
|
this.submitted = true; |
||||||
|
|
||||||
|
if (this.item.title.trim()) { |
||||||
|
if (this.item.id) { |
||||||
|
} else { |
||||||
|
//this.products.push(this.product); |
||||||
|
this.item.filetype = 'folder'; |
||||||
|
this.item.parentResourceNodeId = this.$route.params.node; |
||||||
|
this.item.resourceLinkList = JSON.stringify([{ |
||||||
|
gid: this.$route.query.gid, |
||||||
|
sid: this.$route.query.sid, |
||||||
|
cid: this.$route.query.cid, |
||||||
|
visibility: 2, // visible by default |
||||||
|
}]); |
||||||
|
|
||||||
|
this.create(this.item); |
||||||
|
this.showMessage('Saved'); |
||||||
|
} |
||||||
|
|
||||||
|
this.itemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
} |
||||||
|
}, |
||||||
|
editItem(item) { |
||||||
|
this.item = {...item}; |
||||||
|
this.itemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteItem(item) { |
||||||
|
this.item = item; |
||||||
|
this.deleteItemDialog = true; |
||||||
|
}, |
||||||
|
confirmDeleteMultiple() { |
||||||
|
this.deleteMultipleDialog = true; |
||||||
|
}, |
||||||
|
markAsReadMultiple(){ |
||||||
|
console.log('markAsReadMultiple'); |
||||||
|
this.selectedItems.forEach(message => { |
||||||
|
message.read = true; |
||||||
|
this.update(message); |
||||||
|
}); |
||||||
|
this.selectedItems = null; |
||||||
|
this.resetList = true; |
||||||
|
}, |
||||||
|
reloadHandler() { |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
markAsUnReadMultiple(){ |
||||||
|
console.log('markAsUnReadMultiple'); |
||||||
|
this.selectedItems.forEach(message => { |
||||||
|
message.read = false; |
||||||
|
this.update(message); |
||||||
|
}); |
||||||
|
this.selectedItems = null; |
||||||
|
this.resetList = true; |
||||||
|
//this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
deleteMultipleItems() { |
||||||
|
console.log('deleteMultipleItems'); |
||||||
|
console.log(this.selectedItems); |
||||||
|
this.deleteMultipleAction(this.selectedItems); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
this.deleteMultipleDialog = false; |
||||||
|
this.selectedItems = null; |
||||||
|
//this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
deleteItemButton() { |
||||||
|
console.log('deleteItem'); |
||||||
|
this.deleteItem(this.item); |
||||||
|
//this.items = this.items.filter(val => val.iid !== this.item.iid); |
||||||
|
this.deleteItemDialog = false; |
||||||
|
this.item = {}; |
||||||
|
this.onUpdateOptions(this.options); |
||||||
|
}, |
||||||
|
onRowSelected(items) { |
||||||
|
this.selected = items |
||||||
|
}, |
||||||
|
selectAllRows() { |
||||||
|
this.$refs.selectableTable.selectAllRows() |
||||||
|
}, |
||||||
|
clearSelected() { |
||||||
|
this.$refs.selectableTable.clearSelected() |
||||||
|
}, |
||||||
|
async deleteSelected() { |
||||||
|
this.deleteMultipleAction(this.selected); |
||||||
|
this.onRequest({ |
||||||
|
pagination: this.pagination, |
||||||
|
}); |
||||||
|
}, |
||||||
|
//...actions, |
||||||
|
// From ListMixin |
||||||
|
...mapActions('userreluser', { |
||||||
|
getPage: 'fetchAll', |
||||||
|
create: 'create', |
||||||
|
update: 'update', |
||||||
|
deleteItem: 'del', |
||||||
|
deleteMultipleAction: 'delMultiple' |
||||||
|
}), |
||||||
|
...mapActions('resourcenode', { |
||||||
|
findResourceNode: 'findResourceNode', |
||||||
|
}), |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
Loading…
Reference in new issue