Created
August 14, 2017 19:02
-
-
Save parallelo3301/b6ec2706b3e784a810866b5043b9f60c to your computer and use it in GitHub Desktop.
Vue Dynamic web - defined by YAML definition loaded from server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<component v-if="source" | |
:is="source.type || 'div'" | |
:items="source.data" | |
:config="source.config" | |
:query="source.query" | |
:dataField="source.dataField" | |
:pageEntityObject="pageEntityObject" | |
:parentBlockTitle="source.parentBlockTitle" | |
@update="resendUpdateEvent" | |
> | |
<EntityComponent v-if="hasRecursiveComponents(source)" | |
v-for="(value, key) of recursiveComponents(source)" | |
:key="key" | |
:source="value" | |
:pageEntityObject="pageEntityObject" | |
@update="resendUpdateEvent" | |
></EntityComponent> | |
</component> | |
<div v-else></div> | |
</div> | |
</template> | |
<script type="text/javascript"> | |
import EntityMixin from '../mixins/entityComponent' | |
import Standard from './grid/Standard.vue' | |
import Full from './grid/Full.vue' | |
import VideoPlayer from './VideoPlayer.vue' | |
import HeaderStandard from './HeaderStandard.vue' | |
import FooterStandard from './FooterStandard.vue' | |
import BlockHeader from './misc/BlockHeader.vue' | |
import MetaTitle from './misc/MetaTitle.vue' | |
export default { | |
name: 'EntityComponent', | |
mixins: [EntityMixin], | |
props: { | |
pageEntityObject: {}, | |
source: {}, | |
}, | |
created () { | |
// console.log('source', this.source) | |
}, | |
methods: { | |
resendUpdateEvent (msg) { | |
this.$emit('update', msg) | |
}, | |
hasRecursiveComponents (source) { | |
if (! source || ! source.components) { | |
return false | |
} | |
return true | |
}, | |
recursiveComponents (source) { | |
// console.log('recursive components', source) | |
if (! this.hasRecursiveComponents(source)) { | |
return [] | |
} | |
return source.components.map(obj => { | |
for (const i in obj) { | |
return obj[i] | |
} | |
}) | |
}, | |
}, | |
components: { | |
// async components - defined by function - every component can be code-splitted | |
Feedback (resolve) { require(['./custom/Feedback.vue'], resolve) }, | |
ImproveTopic (resolve) { require(['./custom/ImproveTopic.vue'], resolve) }, | |
GoogleMap (resolve) { require(['./custom/GoogleMap.vue'], resolve) }, | |
ReallyBigCustomizableSvg (resolve) { require(['./custom/ReallyBigCustomizableSvg.vue'], resolve) }, // :-) | |
// no code splitting - basic components | |
MetaTitle, | |
Standard, | |
Full, | |
VideoPlayer, | |
HeaderStandard, | |
FooterStandard, | |
BlockHeader, | |
}, | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<TopMenu key="menu" :config="headerMeta" /> | |
<!-- | |
staticke komponenty zustavaji zobrazeny pri prechodu mezi jednotlivymi strankami.. | |
pokud je dalsi stranka po nacteni dat neobsahuje, pak zmizi, ale v dobe nacitani zde zustavaji; | |
daji se tim vytvaret hezke komponenty, napr. mapa - zustane vykreslena, cele okoli stranky se vsak zmeni | |
--> | |
<div key="staticComponents"> | |
<EntityComponent v-for="(item, key) of topLevelStaticComponents" :key="key" :source="item" :pageEntityObject="loadedEntityObject" /> | |
</div> | |
<div v-if="isTemplateLoading"> | |
<div class="spacer-full"></div> | |
<Standard class="loader-container"> | |
<div class="loader align-center"> | |
<img src="~public/loader.gif" /> | |
<div class="spacer-full"></div> | |
<h3>{{ $t('loader.level.' + loaderLevel) }}</h3> | |
</div> | |
</Standard> | |
</div> | |
<div v-else-if="templateLoadingFailed"> | |
<div class="spacer-full"></div> | |
<Standard style="min-height: 450px"> | |
<h1>{{ $t('loader.failed') }}</h1> | |
<div class="spacer-full"></div> | |
<ErrorLinks /> | |
</Standard> | |
</div> | |
<div v-else> | |
<EntityComponent v-for="(item, key) of topLevelComponents" :key="key" :source="item" :pageEntityObject="loadedEntityObject" /> | |
</div> | |
<FooterStandard key="footer" /> | |
<Sidebar /> | |
</div> | |
</template> | |
<script type="text/javascript"> | |
import { mapGetters, mapActions } from 'vuex' | |
import TopMenu from '../components/TopMenu.vue' | |
import Standard from '../components/grid/Standard.vue' | |
import FooterStandard from '../components/FooterStandard.vue' | |
import Sidebar from '../components/Sidebar.vue' | |
import EntityComponent from '../components/EntityComponent.vue' | |
import ErrorLinks from '../components/custom/ErrorLinks.vue' | |
import { translateCollection } from '../utils' | |
const createId = (collection, id, $route) => { | |
const col = routeName === 'topics' ? routeName : collection | |
return translateCollection(col) + '/' + (id || 0) | |
} | |
export default { | |
props: ['collection', 'id'], | |
components: { | |
TopMenu, | |
EntityComponent, | |
Standard, | |
FooterStandard, | |
ErrorLinks, | |
Sidebar, | |
}, | |
data () { | |
const { collection, id } = this.$route.params | |
const { name } = this.$route | |
return { | |
id: createId(collection, id, name), | |
loaderLevel: 0, | |
timeout: null, | |
} | |
}, | |
metaInfo () { | |
return { | |
title: this.isTemplateLoading ? 'Loading...' : ( | |
this.templateLoadingFailed | |
? 'Error' | |
: '' | |
), | |
} | |
}, | |
computed: { | |
...mapGetters([ | |
'loadedEntityObject', | |
'loadingEntityId', | |
'getMetaData', | |
'getCompleteTemplate', | |
'isTemplateLoading', | |
'templateLoadingFailed', | |
]), | |
topLevelComponents () { | |
return this.recursiveComponents(this.getCompleteTemplate) | |
.filter(i => i.static !== true) | |
}, | |
topLevelStaticComponents () { | |
return this.recursiveComponents(this.getCompleteTemplate) | |
.filter(i => i.static === true) | |
}, | |
headerMeta () { | |
if (this.isTemplateLoading) { | |
if (this.loadingEntityId === 'homepage/0' || this.loadingEntityId === 'topics/0') { | |
return { | |
header: { | |
variant: 'default', | |
}, | |
} | |
} | |
return {} | |
} | |
return this.getMetaData | |
}, | |
}, | |
methods: { | |
recursiveComponents (source) { | |
if (! source || ! source.components) { | |
return [] | |
} | |
return source.components.map(obj => { | |
for (const i in obj) { | |
return obj[i] | |
} | |
}) | |
}, | |
startLoader () { | |
this.loaderLevel = 0 | |
this.timeout = setTimeout(() => { | |
this.loaderLevel++ | |
this.timeout = setTimeout(() => { | |
this.loaderLevel++ | |
}, 2500) | |
}, 1500) | |
}, | |
...mapActions([ | |
'loadTemplateData', | |
]), | |
}, | |
// fetching data (also for server-side rendering) | |
asyncData ({ store, route }) { | |
return store.dispatch('loadTemplateData', { | |
entityId: createId(route.params.collection, route.params.id, route), | |
}) | |
}, | |
watch: { | |
'isTemplateLoading' (to) { | |
if (! to && this.timeout) { | |
clearTimeout(this.timeout) | |
} | |
}, | |
'$route' (to, from) { | |
const toEntityId = createId(to.params.collection, to.params.id, this.$route) | |
if (this.id !== toEntityId) { | |
this.id = toEntityId | |
this.loadTemplateData({ | |
entityId: toEntityId, | |
}) | |
this.startLoader() | |
if (window) { | |
window.scrollTop = 0 | |
} | |
} | |
}, | |
}, | |
} | |
</script> | |
<style lang="stylus" scoped> | |
.loader | |
padding 180px 0 | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Ukazka komponenty, do ktere lze vlozit dalsi uroven komponent | |
Zde je pomoci <slot></slot> mozne vlozit obsah do te komponenty (obdoba React children), tj. dalsi vnoreni <component> z YAMLu --> | |
<template> | |
<div class="block full"> | |
<div class="content" :style="{ backgroundImage: bgImage, backgroundColor: bgColor }"> | |
<slot></slot> | |
</div> | |
</div> | |
</template> | |
<script type="text/javascript"> | |
import EntityMixin from '../mixins/entityComponent' | |
import BackgroundCustomizable from '../mixins/backgroundCustomizable' | |
export default { | |
mixins: [EntityMixin, BackgroundCustomizable], | |
} | |
</script> | |
<style lang="stylus" scoped> | |
@import '../../variables.styl' | |
// component is using global classes, so nothing is there for now | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
meta: | |
title: Toto je titulek topicu z meta dat | |
components: | |
# query po nacteni dat z api vytvori property data na vyssi urovni - tj. na stejne, jako type, config, query, atd... | |
# level 1 je vzdy popis pro editora | |
- header radek: | |
type: HeaderStandard | |
config: | |
buttons: | |
- follow | |
- share | |
query: | |
type: api | |
route: header/classes/18 | |
- popularni v zanru: | |
type: FullExtended | |
config: | |
#bgImage: https://cdn.bum.pp.ua/thumbs/Mark-Hamill-Star-Wars_0.jpg | |
components: # seznam vnorenych komponent, opet zanorene do popisu pro editora | |
- hlavicka: | |
type: BlockHeader | |
data: music.genre.popular | |
- topicy: | |
type: TopicWithVideosUnderList | |
query: | |
type: api | |
fields: | |
videos: 3 | |
route: music/genre/classes/18/interprets/popular | |
limit: 8 | |
- popular v zanru featured se ctyrma: | |
type: Full | |
components: | |
- popis pro editora: | |
type: FeaturedWithFourVideos | |
query: | |
type: api | |
limit: 1 | |
fields: | |
followers: true | |
videos: 4 | |
route: music/genre/classes/18/interprets/popular | |
- podobne zanry s videem: | |
type: Full | |
components: | |
- left: | |
type: TopicWithVideosNextToList | |
query: | |
type: api | |
limit: 4 | |
offset: 1 | |
fields: | |
videos: 2 | |
route: music/genre/classes/18/similar | |
- podobne zanry bez videa: | |
type: Full | |
components: | |
- left: | |
type: TopicImageCardSmallList | |
query: | |
type: api | |
limit: 8 | |
offset: 5 | |
fields: | |
videos: 0 | |
route: music/genre/classes/18/similar | |
- pop albums by decades: | |
type: Full | |
components: | |
- left: | |
type: ListVideoCardText | |
query: | |
type: api | |
limit: 4 | |
route: music/albums/genre/classes/18/decades | |
- pop videos: | |
type: Full | |
components: | |
- left: | |
type: ListVideoCardText | |
query: | |
type: api | |
route: music/genre/classes/18/videos |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment