Social: start new UI

pull/4020/head^2
Angel Fernando Quiroz Campos 3 years ago
parent 6868ea65f4
commit 221c0f2832
  1. 1
      assets/vue/components/layout/DashboardLayout.vue
  2. 105
      assets/vue/components/socialnetwork/Form.vue
  3. 74
      assets/vue/components/socialnetwork/Post.vue
  4. 51
      assets/vue/components/socialnetwork/PostList.vue
  5. 3
      assets/vue/router/index.js
  6. 14
      assets/vue/router/socialnetwork.js
  7. 24
      assets/vue/views/socialnetwork/Home.vue
  8. 59
      assets/vue/views/socialnetwork/Layout.vue
  9. 2
      src/CoreBundle/Controller/IndexController.php

@ -287,6 +287,7 @@ export default {
//{ icon: 'star_border', url: '/calendar', text: 'My calendar' },
//{ icon: 'compass', url: '/catalog', text: 'Explore' },
// { icon: 'star_border', url: '/news', text: 'News' },
{icon: 'mdi-network', url: '/socialnetwork', text: t('Social network')},
];
linksAdmin.value = [

@ -0,0 +1,105 @@
<template>
<q-card bordered class="mb-4" flat>
<q-card-section>
<q-form
class="q-gutter-md"
>
<q-input
v-model="content"
:error="v$.content.$error"
:label="$t('What are you thinking about?')"
autogrow
/>
<div class="row justify-between mt-0">
<q-file
v-model="attachment"
:label="$t('File upload')"
accept="image/*"
clearable
dense
@change="v$.attachment.$touch()"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
<q-btn
:label="$t('Post')"
icon="send"
@click="sendPost"
/>
</div>
</q-form>
</q-card-section>
</q-card>
</template>
<script>
import {reactive, toRefs} from "vue";
import {useStore} from "vuex";
import {MESSAGE_TYPE_WALL} from "../message/msgType";
import useVuelidate from "@vuelidate/core";
import {required} from "@vuelidate/validators";
export default {
name: "SocialNetworkForm",
setup() {
const store = useStore();
const currentUser = store.getters['security/getUser'];
const postState = reactive({
content: '',
attachment: null,
});
const v$ = useVuelidate({
content: {required},
}, postState);
async function sendPost() {
v$.value.$touch();
if (v$.value.$invalid) {
return;
}
const messagePayload = {
title: 'Post',
content: postState.content,
msgType: MESSAGE_TYPE_WALL,
sender: `/api/users/${currentUser.id}`,
receivers: [
{
receiver: `/api/users/${currentUser.id}`,
receiverType: 1
}
]
};
await store.dispatch('message/create', messagePayload);
if (postState.attachment) {
const message = store.state.message.created;
const attachmentPayload = {
messageId: message.id,
file: postState.attachment
};
await store.dispatch('messageattachment/createWithFormData', attachmentPayload);
}
postState.content = '';
postState.attachment = null;
}
return {
...toRefs(postState),
sendPost,
v$
}
}
}
</script>

@ -0,0 +1,74 @@
<template>
<q-card
bordered
class="mb-4"
flat
>
<q-item>
<q-item-section side>
<q-avatar>
<q-img :alt="message.sender.username" :src="message.sender.illustrationUrl" />
</q-avatar>
</q-item-section>
<q-item-section>
<q-item-label v-if="message.sender['@id'] === message.firstReceiver.receiver['@id']">
<router-link :to="{ name: 'SocialNetworkHome', query: { id: message.sender['@id']} }">
{{ message.sender.username }}
</router-link>
</q-item-label>
<q-item-label v-else>
<router-link :to="{ name: 'SocialNetworkHome', query: { id: message.sender['@id']} }">
{{ message.sender.username }}
</router-link>
&raquo;
<router-link :to="{ name: 'SocialNetworkHome', query: { id: message.firstReceiver.receiver['@id']} }">
{{ message.firstReceiver.receiver.username }}
</router-link>
</q-item-label>
<q-item-label caption>
{{ $filters.abbreviatedDatetime(message.sendDate) }}
</q-item-label>
</q-item-section>
</q-item>
<q-img
v-if="containsImage"
:alt="attachment.comment"
:src="attachment.contentUrl"
/>
<q-video
v-if="containsVideo"
:alt="attachment.comment"
:src="attachment.contentUrl"
/>
<q-card-section v-html="message.content" />
</q-card>
</template>
<script>
export default {
name: "SocialNetworkPost",
props: {
message: {
type: Object,
required: true
}
},
setup(props) {
const attachment = props.message.attachments.length ? props.message.attachments[0] : null;
const containsImage = attachment && attachment.resourceNode.resourceFile.mimeType.includes('image/');
const containsVideo = attachment && attachment.resourceNode.resourceFile.mimeType.includes('video/');
return {
attachment,
containsImage,
containsVideo
}
}
}
</script>

@ -0,0 +1,51 @@
<template>
<SocialNetworkPost
v-for="message in messageList"
:key="message.id"
:message="message"
/>
</template>
<script>
import {MESSAGE_TYPE_WALL} from "../message/msgType";
import SocialNetworkPost from "./Post";
import {useStore} from "vuex";
import {ref, watch} from "vue";
export default {
name: "SocialNetworkPostList",
components: {SocialNetworkPost},
props: {
user: {
type: Object,
required: true
}
},
setup(props) {
console.log(props.user, '<<<<<<');
const store = useStore();
let messageList = ref([]);
function listMessage(user) {
store.state.message.resetList = true;
store.dispatch('message/fetchAll', {
msgType: MESSAGE_TYPE_WALL,
'receivers.receiver': user['@id'],
'order[sendDate]': 'desc',
}).then(() => {
messageList.value = store.getters['message/list'];
});
}
watch(() => props.user, (current) => {listMessage(current)});
listMessage(props.user);
return {
messageList
}
}
}
</script>

@ -9,6 +9,7 @@ import userRelUserRoutes from './userreluser';
import calendarEventRoutes from './ccalendarevent';
import toolIntroRoutes from './ctoolintro';
import pageRoutes from './page';
import socialNetworkRoutes from './socialnetwork';
//import courseCategoryRoutes from './coursecategory';
import documents from './documents';
@ -93,7 +94,7 @@ const router = createRouter({
component: MySessionListUpcoming,
meta: {requiresAuth: true},
},
socialNetworkRoutes,
{
path: '/catalog',
redirect: '/catalog/course',

@ -0,0 +1,14 @@
export default {
path: '/socialnetwork',
meta: {requiresAuth: true},
name: 'SocialNetwork',
component: () => import('../views/socialnetwork/Layout.vue'),
props: route => ({uid: route.query.id}),
children: [
{
name: 'SocialNetworkHome',
path: '',
component: () => import('../views/socialnetwork/Home.vue')
},
]
}

@ -0,0 +1,24 @@
<template>
<div>
<SocialNetworkForm />
<SocialNetworkPostList :user="user" />
</div>
</template>
<script>
import SocialNetworkForm from "../../components/socialnetwork/Form";
import SocialNetworkPostList from "../../components/socialnetwork/PostList";
import {useRoute} from "vue-router";
export default {
name: "SocialNetworkHome",
components: {SocialNetworkPostList, SocialNetworkForm},
props: {
user: {
type: Object,
required: true
}
}
}
</script>

@ -0,0 +1,59 @@
<template>
<div class="row q-col-gutter-md">
<div class="col-8">
<SocialNetworkHome :user="user" />
</div>
<div class="col-4">
<q-card flat bordered>
<img
:src="user.illustrationUrl"
/>
<q-card-section class="text-center">
<div class="text-h6">{{ user.fullName }}</div>
<div class="text-subtitle2">{{ user.username }}</div>
</q-card-section>
</q-card>
</div>
</div>
</template>
<script>
import {useStore} from "vuex";
import {ref, watch} from "vue";
import SocialNetworkHome from "./Home";
export default {
name: "SocialNetworkLayout",
components: {SocialNetworkHome},
props: {
uid: {
type: String,
default: ''
}
},
setup(props) {
const store = useStore();
const user = ref({});
const currentUser = store.getters['security/getUser'];
async function setUser(uid) {
if (uid) {
store.dispatch('user/load', uid).then(data => {user.value = data});
} else {
user.value = currentUser;
}
}
setUser(props.uid);
watch(() => props.uid, (uid, old) => setUser(uid));
return {
user
}
}
}
</script>

@ -24,6 +24,8 @@ class IndexController extends BaseController
* @Route("/catalog/{slug}", name="catalog", methods={"GET", "POST"}, options={"expose"=true})
* @Route("/resources/document/{nodeId}/manager", methods={"GET"}, name="resources_filemanager")
* @Route("/account/home", name="account", options={"expose"=true}, name="chamilo_core_account_home")
*
* @Route("/socialnetwork", name="socialnetwork", options={"expose"=true}, name="chamilo_core_socialnetwork")
*/
#[Route('/sessions', name: 'sessions')]
#[Route('/sessions/{extra}', name: 'sessions_options')]

Loading…
Cancel
Save