Add course/session list, fix menu depending in user role.

pull/3272/head
Julio Montoya 5 years ago
parent 030eb8b84c
commit ddfd23a186
  1. 17
      .eslintrc.json
  2. 81
      assets/vue/App.vue
  3. 4
      assets/vue/router/index.js
  4. 12
      assets/vue/store/security.js
  5. 38
      assets/vue/views/user/courses/CourseCard.vue
  6. 45
      assets/vue/views/user/courses/List.vue
  7. 43
      assets/vue/views/user/sessions/List.vue
  8. 26
      assets/vue/views/user/sessions/SessionCard.vue
  9. 20
      src/CoreBundle/Entity/Course.php
  10. 7
      src/CoreBundle/Entity/CourseRelUser.php
  11. 4
      src/CoreBundle/Entity/Session.php
  12. 10
      src/CoreBundle/Entity/SessionRelCourseRelUser.php
  13. 12
      src/CoreBundle/Entity/User.php

@ -0,0 +1,17 @@
{
"root": true,
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"parser": "babel-eslint"
},
"env": {
"browser": true,
"node": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:vue/recommended"
]
}

@ -7,7 +7,6 @@
v-model="drawer"
:clipped="$vuetify.breakpoint.lgAndUp"
disable-resize-watcher
>
<v-list v-if="isAuthenticated">
<v-list-item :to="{ name: '/' }">
@ -21,7 +20,30 @@
</v-list-item-content>
</v-list-item>
<v-list-item :to="{ name: 'MyCourses' }">
<v-list-item-action>
<v-icon>mdi-home</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
My courses
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item :to="{ name: 'MySessions' }">
<v-list-item-action>
<v-icon>mdi-home</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
My sessions
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-group
v-if="isAdmin"
prepend-icon="mdi-plus"
value="true"
>
@ -170,9 +192,38 @@
</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon v-if="isAuthenticated">
<v-icon>mdi-bell</v-icon>
</v-btn>
<v-menu
v-if="isAuthenticated"
offset-y
:nudge-width="200"
>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on">
<v-avatar>
<v-icon dark>mdi-bell</v-icon>
</v-avatar>
</v-btn>
</template>
<v-card>
<v-card-text>
<div>Notifications</div>
</v-card-text>
<v-list>
<v-list-item>
<v-list-item-title>
Notification 1
</v-list-item-title>
</v-list-item>
<v-list-item>
<v-list-item-title>
Notification 2
</v-list-item-title>
</v-list-item>
</v-list>
</v-card>
</v-menu>
<v-menu
v-if="isAuthenticated"
@ -189,6 +240,10 @@
<v-list-item>
<v-list-item-title>Profile</v-list-item-title>
</v-list-item>
<v-list-item>
<v-list-item-title>Inbox</v-list-item-title>
</v-list-item>
<v-list-item>
<v-list-item-title>
<a href="/logout">Logout</a>
@ -257,44 +312,40 @@
isAuthenticated() {
return this.$store.getters['security/isAuthenticated']
},
isAdmin() {
return this.$store.getters['security/isAdmin']
},
},
watch: {
$route(to, from) {
console.log('remove');
this.$data.legacy_content = '';
if (document.querySelector("#sectionMainContent")) {
console.log('removed sectionMainContent');
document.querySelector("#sectionMainContent").remove();
}
let url = window.location.href;
console.log(url);
var n = url.indexOf("main/");
if (n > 0) {
console.log('ajax');
axios.get(url, {
params: {
from_vue: 1
}
})
.then((response) => {
// handle success
this.$data.legacy_content = response.data;
});
.then((response) => {
// handle success
this.$data.legacy_content = response.data;
});
}
},
legacy_content: {
handler: function () {
console.log('watch');
if (document.querySelector("#sectionMainContent")) {
//console.log('removed sectionMainContent');
//document.querySelector("#sectionMainContent").remove();
}
},
immediate: true
},
},
mounted() {
console.log('mounted');
let legacyContent = document.querySelector("#sectionMainContent");
if (legacyContent) {
document.querySelector("#sectionMainContent").remove();

@ -8,11 +8,15 @@ import courseCategoryRoutes from './coursecategory';
import documents from './documents';
import store from "../store";
import Login from "../views/Login";
import MyCourseList from "../views/user/courses/List";
import MySessionList from "../views/user/sessions/List";
let router = new VueRouter({
mode: "history",
routes: [
{ path: "/login", component: Login },
{ path: "/courses", name: "MyCourses", component: MyCourseList },
{ path: "/sessions", name: "MySessions", component: MySessionList },
courseRoutes,
courseCategoryRoutes,
documents

@ -26,9 +26,19 @@ export default {
isAuthenticated(state) {
return state.isAuthenticated;
},
isAdmin(state, getters) {
return getters.hasRole('ROLE_ADMIN');
},
getUser(state) {
return state.user;
},
hasRole(state) {
return role => {
return state.user.roles.indexOf(role) !== -1;
if (state.user.roles) {
return state.user.roles.indexOf(role) !== -1;
}
return false;
}
}
},

@ -0,0 +1,38 @@
<template>
<v-container grid-list-xl fluid>
<v-layout row wrap>
<v-row dense>
<v-col
v-for="card in courses"
:key="card.course.id"
:cols="12"
>
<v-card>
<v-card-title v-text="card.course.title">
</v-card-title>
<v-card-actions>
<v-btn
:href=" '/course/' + card.course.id + '/home'"
text
color="deep-purple accent-4"
>
Go
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-layout>
</v-container>
</template>
<script>
export default {
name: 'CourseCard',
props: {
courses: Array
},
};
</script>

@ -0,0 +1,45 @@
<template>
<div class="course-list">
{{ status }}
<CourseCard :courses="courses"></CourseCard>
</div>
</template>
<script>
import CourseCard from './CourseCard';
import ListMixin from '../../../mixins/ListMixin';
import { ENTRYPOINT } from '../../../config/entrypoint';
import axios from "axios";
export default {
name: 'CourseList',
servicePrefix: 'Course',
mixins: [ListMixin],
components: {
CourseCard
},
data() {
return {
status: null,
courses:null
};
},
created: function () {
this.load();
},
methods: {
load: function() {
this.status = 'Loading';
let user = this.$store.getters['security/getUser'];
axios.get(ENTRYPOINT + 'users/'+ user.id +'/courses.json').then(response => {
this.status = '';
this.courses = response.data;
}).catch(function(error) {
this.status = error;
});
}
}
};
</script>

@ -0,0 +1,43 @@
<template>
<div class="course-list">
{{ status }}
<SessionCard :sessions="sessions"></SessionCard>
</div>
</template>
<script>
import SessionCard from './SessionCard';
import ListMixin from '../../../mixins/ListMixin';
import { ENTRYPOINT } from '../../../config/entrypoint';
import axios from "axios";
export default {
name: 'SessionList',
servicePrefix: 'Course',
mixins: [ListMixin],
components: {
SessionCard
},
data() {
return {
status: null,
sessions:null
};
},
created: function () {
this.load();
},
methods: {
load: function() {
this.status = 'Loading';
let user = this.$store.getters['security/getUser'];
axios.get(ENTRYPOINT + 'users/' + user.id + '/session_course_subscriptions.json').then(response => {
this.status = '';
this.sessions = response.data;
}).catch(function (error) {
this.status = error;
});
}
}
};
</script>

@ -0,0 +1,26 @@
<template>
<v-container grid-list-xl fluid>
<v-layout row wrap>
<v-row dense>
<v-col
v-for="card in sessions"
:key="card.course.title"
:cols="12"
>
<v-card>
<v-card-title v-text="card.course.title"></v-card-title>
</v-card>
</v-col>
</v-row>
</v-layout>
</v-container>
</template>
<script>
export default {
name: 'SessionCard',
props: {
sessions: Array
},
};
</script>

@ -58,7 +58,7 @@ class Course extends AbstractResource implements ResourceInterface
/**
* @var int
* @Groups({"course:read"})
* @Groups({"course:read", "course_rel_user:read"})
* @ORM\Column(name="id", type="integer", nullable=false, unique=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
@ -70,7 +70,7 @@ class Course extends AbstractResource implements ResourceInterface
*
* @Assert\NotBlank()
*
* @Groups({"course:read", "course:write"})
* @Groups({"course:read", "course:write", "course_rel_user:read", "session_rel_course_rel_user:read"})
*
* @ORM\Column(name="title", type="string", length=250, nullable=true, unique=false)
*/
@ -80,7 +80,7 @@ class Course extends AbstractResource implements ResourceInterface
* @var string
* @Assert\NotBlank()
* @ApiProperty(iri="http://schema.org/courseCode")
* @Groups({"course:read", "course:write"})
* @Groups({"course:read", "course:write", "course_rel_user:read"})
*
* @Gedmo\Slug(
* fields={"title"},
@ -96,7 +96,7 @@ class Course extends AbstractResource implements ResourceInterface
* @var CourseRelUser[]|ArrayCollection
*
* @ApiSubresource()
* @Groups({"course:read"})
* Groups({"course:read"})
* "orphanRemoval" is needed to delete the CourseRelUser relation
* in the CourseAdmin class. The setUsers, getUsers, removeUsers and
* addUsers methods need to be added.
@ -154,32 +154,32 @@ class Course extends AbstractResource implements ResourceInterface
protected $currentUrl;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\SkillRelCourse", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="SkillRelCourse", mappedBy="course", cascade={"persist", "remove"})
*/
protected $skills;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\SkillRelUser", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="SkillRelUser", mappedBy="course", cascade={"persist", "remove"})
*/
protected $issuedSkills;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\GradebookCategory", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="GradebookCategory", mappedBy="course", cascade={"persist", "remove"})
*/
protected $gradebookCategories;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\GradebookEvaluation", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="GradebookEvaluation", mappedBy="course", cascade={"persist", "remove"})
*/
protected $gradebookEvaluations;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\GradebookLink", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="GradebookLink", mappedBy="course", cascade={"persist", "remove"})
*/
protected $gradebookLinks;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\TrackEHotspot", mappedBy="course", cascade={"persist", "remove"})
* @ORM\OneToMany(targetEntity="TrackEHotspot", mappedBy="course", cascade={"persist", "remove"})
*/
protected $trackEHotspots;

@ -13,7 +13,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
*
* @ApiResource(
* shortName="CourseSubscription",
* normalizationContext={"groups"={"course_rel_user:read"}}
* normalizationContext={"groups"={"course_rel_user:read", "user:read"}}
* )
*
* @ORM\Table(
@ -45,6 +45,7 @@ class CourseRelUser
protected $user;
/**
* @Groups({"course:read", "user:read"})
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course", inversedBy="users", cascade={"persist"})
* @ORM\JoinColumn(name="c_id", referencedColumnName="id")
*/
@ -52,14 +53,14 @@ class CourseRelUser
/**
* @var int
*
* @Groups({"user:read", "course:read"})
* @ORM\Column(name="relation_type", type="integer", nullable=false, unique=false)
*/
protected $relationType;
/**
* @var bool
*
* @Groups({"user:read"})
* @ORM\Column(name="status", type="integer", nullable=false, unique=false)
*/
protected $status;

@ -113,7 +113,7 @@ class Session
protected $urls;
/**
* @ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\ResourceLink", mappedBy="session", cascade={"remove"}, orphanRemoval=true)
* @ORM\OneToMany(targetEntity="ResourceLink", mappedBy="session", cascade={"remove"}, orphanRemoval=true)
*/
protected $resourceLinks;
@ -125,7 +125,7 @@ class Session
/**
* @var string
* @Assert\NotBlank()
* @Groups({"session:read", "session:write"})
* @Groups({"session:read", "session:write", "session_rel_course_rel_user:read"})
* @ORM\Column(name="name", type="string", length=150, nullable=false, unique=false)
*/
protected $name;

@ -4,11 +4,17 @@
namespace Chamilo\CoreBundle\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* Class SessionRelCourseRelUser.
*
* @ApiResource(
* shortName="SessionSubscription",
* normalizationContext={"groups"={"session_rel_course_rel_user:read", "user:read"}}
* )
* @ORM\Table(
* name="session_rel_course_rel_user",
* indexes={
@ -47,7 +53,7 @@ class SessionRelCourseRelUser
/**
* @var Session
*
* @Groups({"session_rel_course_rel_user:read"})
* @ORM\ManyToOne(targetEntity="Session", inversedBy="userCourseSubscriptions", cascade={"persist"})
* @ORM\JoinColumn(name="session_id", referencedColumnName="id", nullable=false)
*/
@ -55,7 +61,7 @@ class SessionRelCourseRelUser
/**
* @var Course
*
* @Groups({"session_rel_course_rel_user:read"})
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course", inversedBy="sessionUserSubscriptions", cascade={"persist"})
* @ORM\JoinColumn(name="c_id", referencedColumnName="id", nullable=false)
*/

@ -277,6 +277,7 @@ class User implements UserInterface, EquatableInterface
protected $dropBoxSentFiles;
/**
* @Groups({"user:read", "user:write"})
* @ORM\Column(type="array")
*/
protected $roles;
@ -344,6 +345,7 @@ class User implements UserInterface, EquatableInterface
protected $resourceNodes;
/**
* @ApiSubresource()
* @ORM\OneToMany(
* targetEntity="Chamilo\CoreBundle\Entity\SessionRelCourseRelUser",
* mappedBy="user",
@ -918,16 +920,6 @@ class User implements UserInterface, EquatableInterface
return \UserManager::formatUserFullName($this).$classString;
}
/**
* Get userId.
*
* @return int
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set lastname.
*

Loading…
Cancel
Save