add article and article part pages, extend article store

This commit is contained in:
2019-02-23 12:35:18 +07:00
parent cc6ea339af
commit c6f8da2c44
10 changed files with 428 additions and 103 deletions

View File

@@ -0,0 +1,105 @@
<template>
<v-card color="info" class="white--text">
<v-container fluid>
<!-- desktop layout -->
<v-layout row class="hidden-sm-and-down">
<v-flex md3>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="150px"
>
</v-img>
<div class="text-xs-center">
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</div>
</v-flex>
<v-flex md9>
<v-card-title>
<div>
<div class="headline">{{ article.title }}</div>
<div>{{ article.description }}</div>
<v-divider class="white"></v-divider>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts.length }} частей</div>
</div>
</v-card-title>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat>Добавить</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
<!-- tablet and mobile layout -->
<div class="hidden-md-and-up">
<v-layout row>
<v-flex xs4>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="100px"
>
</v-img>
</v-flex>
<v-flex xs8>
<v-card-title>
<h4>{{ article.title }}</h4>
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</v-card-title>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>{{ article.description }}</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts.length }} частей</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat>Добавить</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
</div>
</v-container>
</v-card>
</template>
<script>
import getArticleLevel from '@/helpers/article';
export default {
props: {
article: {
type: Object,
required: true,
},
},
methods: {
getArticleLevel: getArticleLevel,
},
};
</script>

View File

@@ -0,0 +1,35 @@
<template>
<div>
<v-card color="accent" class=white--text>
<v-card-title primary-title class="headline">
{{ part.title }}
</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn flat class="primary" :to="{
name: 'articlePart',
params: { articleId: this.articleId, partId: part.id },
}"
>
Открыть
</v-btn>
</v-card-actions>
</v-card>
</div>
</template>
<script>
export default {
props: {
part: {
type: Object,
required: true,
},
articleId: {
type: String,
required: true,
},
},
};
</script>

View File

@@ -15,93 +15,7 @@
</v-container>
</v-flex>
<v-flex v-for="article in filteredArticles" xs12 sm10 md8 offset-sm1 offset-md2 :key="article.id">
<v-card color="info" class="white--text">
<v-container fluid>
<!-- desktop layout -->
<v-layout row class="hidden-sm-and-down">
<v-flex md3>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="100px"
>
</v-img>
<div class="text-xs-center">
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</div>
</v-flex>
<v-flex md9>
<v-card-title>
<div>
<div class="headline">{{ article.title }}</div>
<div>{{ article.description }}</div>
<v-divider class="white"></v-divider>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts }} частей</div>
</div>
</v-card-title>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat>Открыть</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
<!-- tablet and mobile layout -->
<div class="hidden-md-and-up">
<v-layout row>
<v-flex xs4>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="100px"
>
</v-img>
</v-flex>
<v-flex xs8>
<v-card-title>
<h4>{{ article.title }}</h4>
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</v-card-title>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>{{ article.description }}</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts }} частей</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat>Открыть</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
</div>
</v-container>
</v-card>
<list-item :article="article"></list-item>
</v-flex>
</v-layout>
</v-container>
@@ -109,6 +23,8 @@
<script>
import ListItem from '@/components/ArticlesListItem';
export default {
data() {
return {
@@ -140,10 +56,8 @@
return filteredArticles;
},
},
methods: {
getArticleLevel(levels) {
return levels.join('/');
},
},
components: {
ListItem,
}
};
</script>

View File

@@ -0,0 +1,109 @@
<template>
<v-card color="info" class="white--text">
<v-container fluid>
<!-- desktop layout -->
<v-layout row class="hidden-sm-and-down">
<v-flex md3>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="100px"
>
</v-img>
<div class="text-xs-center">
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</div>
</v-flex>
<v-flex md9>
<v-card-title>
<div>
<div class="headline">{{ article.title }}</div>
<div>{{ article.description }}</div>
<v-divider class="white"></v-divider>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts.length }} частей</div>
</div>
</v-card-title>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat :to="{ name: 'article', params: { articleId: article.id } }">
Открыть
</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
<!-- tablet and mobile layout -->
<div class="hidden-md-and-up">
<v-layout row>
<v-flex xs4>
<v-img
src="https://images-na.ssl-images-amazon.com/images/I/51U6bQbA8oL._SY346_.jpg"
height="100px"
>
</v-img>
</v-flex>
<v-flex xs8>
<v-card-title>
<h4>{{ article.title }}</h4>
<v-btn flat color="white">
<v-icon left>visibility</v-icon>
Youtube
</v-btn>
</v-card-title>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>{{ article.description }}</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<div>Уровень: {{ getArticleLevel(article.level) }} {{ article.parts.length }} частей</div>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<v-card-actions>
<v-rating v-model="article.rating" color="yellow" readonly dense half-increments></v-rating>
<div class="ml-1">
<span>{{ article.rating }}</span>
<span>({{ article.ratingsCount }})</span>
</div>
<v-spacer></v-spacer>
<v-btn class="primary" flat :to="{ name: 'article', params: { articleId: article.id } }">
Открыть
</v-btn>
</v-card-actions>
</v-flex>
</v-layout>
</div>
</v-container>
</v-card>
</template>
<script>
import getArticleLevel from '@/helpers/article';
export default {
props: {
article: {
type: Object,
required: true,
},
},
methods: {
getArticleLevel: getArticleLevel,
},
};
</script>

3
src/helpers/article.js Normal file
View File

@@ -0,0 +1,3 @@
const getArticleLevel = levels => levels.join('/');
export default getArticleLevel;

View File

@@ -24,28 +24,40 @@ export default new Router({
{
path: '/articles',
name: 'articles',
component: () => import(/* webpackChunkName: "articles" */ '@/views/Articles.vue'),
component: () => import(/* webpackChunkName: "articles/index" */ '@/views/Articles'),
},
{
path: '/articles/:articleId',
name: 'article',
props: true,
component: () => import(/* webpackChunkName: "articles/article" */ '@/views/Article')
},
{
path: '/articles/:articleId/part/:partId',
name: 'articlePart',
props: true,
component: () => import(/* webpackChunkName: "articles/article_part" */ '@/views/ArticlePart')
},
{
path: '/words',
name: 'words',
component: () => import(/* webpackChunkName: "words" */ '@/views/Words.vue'),
component: () => import(/* webpackChunkName: "words" */ '@/views/Words'),
},
{
path: '/profile',
name: 'profile',
component: () => import(/* webpackChunkName: "words" */ '@/views/Profile.vue'),
component: () => import(/* webpackChunkName: "words" */ '@/views/Profile'),
beforeEnter: AuthMiddleware,
},
{
path: '/sign_in',
name: 'signIn',
component: () => import(/* webpackChunkName: "sign_in" */ '@/views/SignIn.vue'),
component: () => import(/* webpackChunkName: "sign_in" */ '@/views/SignIn'),
},
{
path: '/sign_up',
name: 'signUp',
component: () => import(/* webpackChunkName: "sign_up" */ '@/views/SignUp.vue'),
component: () => import(/* webpackChunkName: "sign_up" */ '@/views/SignUp'),
},
{
path: '*',

View File

@@ -6,33 +6,112 @@ export default {
title: 'Harry Potter und Stein der Weisen - 1',
description: 'Первая глава первой книги о Гарри Поттере',
imageId: 'asfgdfhmfgn131',
parts: 7,
level: ['B2', 'C1'],
rating: 4,
ratingsCount: 164,
youtubePlaylistId: 'asdadsadad',
parts: [
{
id: 'asdasdad123',
title: 'kapitel 1',
youtubeId: 'asdasdad1',
},
{
id: 'asdasdad124',
title: 'kapitel 2',
youtubeId: 'asdasdad2',
},
{
id: 'asdasdad125',
title: 'kapitel 3',
youtubeId: 'asdasdad3',
},
{
id: 'asdasdad126',
title: 'kapitel 4',
youtubeId: 'asdasdad4',
},
],
},
{
id: 'sgjngsnaadasd2',
title: 'Harry Potter und Stein der Weisen - 2',
description: 'Вторая глава первой книги о Гарри Поттере',
imageId: 'asfgdf111hmfgn131',
parts: 7,
level: ['B1', 'B2'],
rating: 3.5,
ratingsCount: 55,
youtubePlaylistId: 'asdadsadad234234',
parts: [
{
id: 'bsdasdad123',
title: 'kapitel 1',
youtubeId: 'bsdasdad1',
},
{
id: 'bsdasdad124',
title: 'kapitel 2',
youtubeId: 'bsdasdad2',
},
{
id: 'bsdasdad125',
title: 'kapitel 3',
youtubeId: 'bsdasdad3',
},
],
},
{
id: 'sgjngsdbfd12as',
title: 'Harry Potter und Stein der Weisen - 3',
description: 'Третья глава первой книги о Гарри Поттере',
imageId: 'asfgdfhmfgn13111',
parts: 7,
level: ['A2'],
rating: 2,
ratingsCount: 80,
youtubePlaylistId: 'asdadsada435346',
parts: [
{
id: 'bsdasdad123',
title: 'kapitel 1',
youtubeId: 'bsdasdad1',
},
{
id: 'bsdasdad124',
title: 'kapitel 2',
youtubeId: 'bsdasdad2',
},
{
id: 'bsdasdad125',
title: 'kapitel 3',
youtubeId: 'bsdasdad3',
},
],
},
],
articleParts: [
{
articleId: 'sgjngsnaada312',
articlePartId: 'asdasdad123',
articleTitle: 'Harry Potter und Stein der Weisen - 1',
partTitle: 'kapitel 1',
youtubeId: 'asdasdad1',
content: [
{
sentences: [
{
origText: 'Bla',
transText: 'Бла',
},
]
}
],
words: [
{
origWord: 'Hallo',
transWord: 'Привет',
},
],
},
],
},
@@ -43,5 +122,6 @@ export default {
},
getters: {
getArticles: state => state.articles,
getParts: state => state.articleParts,
},
};

36
src/views/Article.vue Normal file
View File

@@ -0,0 +1,36 @@
<template>
<v-container grid-list-md v-if="article">
<v-layout row wrap>
<v-flex xs12 xs10 offset-sm1>
<article-details :article="article"></article-details>
</v-flex>
<v-flex xs12 xs10 offset-sm1 v-for="part in article.parts" :key="part.id">
<article-parts-list-item :part="part" :articleId="article.id"></article-parts-list-item>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import ArticleDetails from '@/components/ArticleDetails';
import ArticlePartsListItem from '@/components/ArticlePartsListItem';
export default {
props: {
articleId: {
type: String,
required: true,
},
},
computed: {
article() {
return this.$store.getters.getArticles.find(article => article.id == this.articleId);
},
},
components: {
ArticleDetails,
ArticlePartsListItem,
},
};
</script>

33
src/views/ArticlePart.vue Normal file
View File

@@ -0,0 +1,33 @@
<template>
<v-container grid-list-md v-if="part">
<v-layout row wrap>
<v-flex xs12 sm10 offset-sm1>
<!-- content -->
</v-flex>
<v-flex xs12 sm10 offset-sm1>
<!-- words -->
</v-flex>
</v-layout>
</v-container>
</template>
<script>
export default {
props: {
articleId: {
type: String,
required: true,
},
partId: {
type: String,
required: true,
},
},
computed: {
part() {
return this.$store.getters.getParts.find(part => part.articleId === this.articleId
&& part.articlePartId === this.partId);
}
}
};
</script>

View File

@@ -1,8 +1,6 @@
<template>
<div>
<articles-list>
</articles-list>
<articles-list></articles-list>
</div>
</template>