-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/add presentations #108
Changes from 11 commits
6341554
c29fc95
f98241f
2cd7813
7778df6
f9476cd
04c13b8
b7e099d
50adbb4
48ce0dd
25bc09e
c18b262
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
name: Presentation Submission | ||
about: Submit Vue.js presentation to post for the community | ||
title: "[Presentation]" | ||
labels: '' | ||
assignees: '' | ||
--- | ||
|
||
## Presentation | ||
|
||
No need to post an issue for a presentation just get the presentation author authorization and submit a pull request following [this format](https://github.com/vuejs/events/compare/master...presnetation-pr-example?template=pull-request-presentation.md) | ||
|
||
If you meet a deadlink or a wrong informations please contact the author of the presentation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
name: Presentation PR | ||
about: Share a new presnetation | ||
title: '' | ||
labels: '' | ||
assignees: '' | ||
--- | ||
|
||
Thank you for submitting a presentation. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wording here |
||
|
||
To submit a presentation you just need to add a json file that contain your data at: src/.vuepress/data/presentations/\[theme\]/\[year\]/presentation-title.json | ||
|
||
The json format is the following, please copy it fully even if some fields are not filled: | ||
|
||
{ | ||
"slides": "", | ||
"author": "", | ||
"sourceLanguage": "", | ||
"city": "", | ||
"country": "", | ||
"vueVersion": "", | ||
"event": { | ||
"name": "", | ||
"link": "" | ||
}, | ||
"gitRepository": "", | ||
"videoLink": "", | ||
"reachSpeaker": { | ||
"twitter": "", | ||
"github": "", | ||
"vueDiscord": "", | ||
"email": "" | ||
}, | ||
"description": "" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
<template> | ||
<div> | ||
<div style="margin-top: 20px;"> | ||
<label for="title-input">Title:</label> | ||
<input id="title-input" class="input-css" v-model="value.title" placeholder="Type to filter title that contains your search" /> | ||
</div> | ||
<div style="margin-top: 20px;"> | ||
<div> | ||
<select v-model="value.theme" class="select-css"> | ||
<option value="">Theme</option> | ||
<option v-for="item in themes">{{item}}</option> | ||
</select> | ||
<select v-model="value.year" class="select-css"> | ||
<option value="">Year</option> | ||
<option v-for="item in years">{{item}}</option> | ||
</select> | ||
<select v-model="value.author" class="select-css"> | ||
<option value="">Author</option> | ||
<option v-for="item in getItemsForPresentationKey('author')">{{item}}</option> | ||
</select> | ||
</div> | ||
<div style="margin-top: 10px;"> | ||
<select v-model="value.event" class="select-css"> | ||
<option value="">Event</option> | ||
<option v-for="item in getItemsForPresentationKey('event', 'name')">{{item}}</option> | ||
</select> | ||
<select v-model="value.country" class="select-css"> | ||
<option value="">Country</option> | ||
<option v-for="item in getItemsForPresentationKey('country')">{{item}}</option> | ||
</select> | ||
<select v-model="value.language" class="select-css"> | ||
<option value="">Language</option> | ||
<option v-for="item in getItemsForPresentationKey('sourceLanguage')">{{item}}</option> | ||
</select> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import {presentationData} from '../data'; | ||
export default { | ||
name: "PresentationFilters", | ||
props: { | ||
value: { | ||
type: Object, | ||
required: true | ||
}, | ||
}, | ||
computed: { | ||
themes() { | ||
return Object.keys(presentationData); | ||
}, | ||
years() { | ||
let years = []; | ||
Object.values(presentationData).forEach(presentationByYear => { | ||
// presentationByYear look like {2019: [...], 2020: [...]} | ||
// So basically we concat the keys of presentationByYear with already found years and put it in a set to avoid duplcate | ||
years = [...new Set(years.concat(Object.keys(presentationByYear)))] | ||
}) | ||
return years | ||
} | ||
}, | ||
data() { | ||
return {}; | ||
}, | ||
methods: { | ||
getItemsForPresentationKey(key, subKey=null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting all the filter item get methods can be improved to only loop over presentation once (like done in presentationFiltered). But originally I wanted the filter to be related to each others (only display items left depends of other filters selectionned but that trigger some UX issues). |
||
const items = new Set(); | ||
Object.values(presentationData).forEach(presentationsByYear => { | ||
// presentationByYear look like {2019: [...], 2020: [...]} | ||
|
||
Object.values(presentationsByYear).forEach(presentations => { | ||
presentations.forEach(presentation => { | ||
// presentation is a presentation object as declared in json file | ||
if(!subKey && presentation[key]) { | ||
return items.add(presentation[key]) | ||
} | ||
else if(presentation[key] && presentation[key][subKey]) { | ||
items.add(presentation[key][subKey]) | ||
} | ||
}) | ||
}) | ||
}) | ||
return items | ||
} | ||
} | ||
}; | ||
</script> | ||
|
||
<style lang="css" scoped> | ||
.select-css { | ||
margin-right: 20px; | ||
font-size: 16px; | ||
font-family: sans-serif; | ||
font-weight: 700; | ||
color: #444; | ||
line-height: 1.3; | ||
padding: .6em 1.4em .5em .8em; | ||
box-sizing: border-box; | ||
border: 1px solid #aaa; | ||
box-shadow: 0 1px 0 1px rgba(0,0,0,.04); | ||
border-radius: .5em; | ||
-moz-appearance: none; | ||
-webkit-appearance: none; | ||
appearance: none; | ||
background-color: #fff; | ||
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'), | ||
linear-gradient(to bottom, #ffffff 0%,#e5e5e5 100%); | ||
background-repeat: no-repeat, repeat; | ||
background-position: right .7em top 50%, 0 0; | ||
background-size: .65em auto, 100%; | ||
} | ||
.select-css::-ms-expand { | ||
display: none; | ||
} | ||
.select-css:hover { | ||
border-color: #888; | ||
} | ||
.select-css:focus { | ||
border-color: #aaa; | ||
box-shadow: 0 0 1px 3px rgba(59, 153, 252, .7); | ||
box-shadow: 0 0 0 3px -moz-mac-focusring; | ||
color: #222; | ||
outline: none; | ||
} | ||
.select-css option { | ||
font-weight:normal; | ||
} | ||
|
||
|
||
.input-css { | ||
width: 100%; | ||
padding: 12px 20px; | ||
margin: 8px 0; | ||
display: inline-block; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
box-sizing: border-box; | ||
} | ||
</style> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<template> | ||
<li>{{text}} | ||
<a | ||
v-if="link" | ||
:href="link" | ||
target="_blank" | ||
rel="noopener noreferrer"> | ||
{{value}} | ||
</a> | ||
<span v-else>{{value}}</span> | ||
</li> | ||
</template> | ||
|
||
<script> | ||
export default { | ||
name: "PresentationInfoLine", | ||
props: { | ||
text: { | ||
type: String, | ||
default: "" | ||
}, | ||
value: { | ||
type: String, | ||
default: "" | ||
}, | ||
link: { | ||
type: String, | ||
default: "" | ||
} | ||
}, | ||
}; | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<template> | ||
<div style="margin-bottom: 35px;"> | ||
<h4 class="accordion" @click="isExpanded = !isExpanded">{{presentation.title}} ({{year}}) <span class="author-by">by {{presentation.author}} {{ isExpanded ? "-" : "+"}}</span></h4> | ||
<ul v-if="isExpanded"> | ||
<PresentationInfoLine text="Slides:" :value="presentation.slides" :link="presentation.slides" /> | ||
<PresentationInfoLine text="Vue version:" :value="presentation.vueVersion" /> | ||
<PresentationInfoLine text="Source Language:" :value="presentation.sourceLanguage" /> | ||
AMontagu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<PresentationInfoLine text="City:" :value="`${presentation.city}, ${presentation.country}`" /> | ||
<PresentationInfoLine text="Event:" :value="presentation.event.name" :link="presentation.event.link" /> | ||
<PresentationInfoLine text="Git:" :value="presentation.gitRepository" :link="presentation.gitRepository" /> | ||
<PresentationInfoLine text="Video:" :value="presentation.video" :link="presentation.video" /> | ||
<PresentationInfoLine text="Source Language:" :value="presentation.sourceLanguage" /> | ||
<li>Reach Speaker: | ||
<ul> | ||
<PresentationInfoLine text="Twitter:" :value="presentation.reachSpeaker.twitter" :link="presentation.reachSpeaker.twitter" /> | ||
<PresentationInfoLine text="Github:" :value="presentation.reachSpeaker.github" :link="presentation.reachSpeaker.github" /> | ||
<PresentationInfoLine text="Vue Discord:" :value="presentation.reachSpeaker.vueDiscord" /> | ||
<PresentationInfoLine text="Email:" :value="presentation.reachSpeaker.email" /> | ||
</ul> | ||
</li> | ||
</ul> | ||
<strong v-if="isExpanded">Description:</strong> | ||
<p>{{presentation.description}}</p> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import PresentationInfoLine from './PresentationInfoLine'; | ||
|
||
export default { | ||
name: "PresentationItem", | ||
components: { | ||
PresentationInfoLine, | ||
}, | ||
props: { | ||
presentation: { | ||
type: Object, | ||
required: true | ||
}, | ||
year: { | ||
type: String, | ||
required: true | ||
} | ||
}, | ||
data() { | ||
return { | ||
isExpanded: false, | ||
} | ||
}, | ||
computed: { | ||
presentationWithMeta() { | ||
const presentationWithMeta = {}; | ||
Object.entries(this.presentation).forEach(([key, value]) => { | ||
if(["description"].includes(key)) { | ||
return; | ||
} | ||
|
||
}) | ||
} | ||
} | ||
}; | ||
</script> | ||
|
||
<style lang="css" scoped> | ||
.author-by { | ||
float: right; | ||
} | ||
.accordion{ | ||
cursor: pointer; | ||
} | ||
</style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wording here