update webstack

This commit is contained in:
2021-02-08 17:06:59 +02:00
parent b78623ec1c
commit 098fa4e260
313 changed files with 6370 additions and 915 deletions

View File

@@ -0,0 +1,11 @@
<template>
<div class="mt-8">
<a :href="card.link" class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 font-semibold rounded">{{ card.button }}</a>
</div>
</template>
<script>
export default {
props:['card']
}
</script>

View File

@@ -0,0 +1,140 @@
<template>
<div
class="flex flex-post px-0 sm:px-4 pb-8 mb-8"
v-bind:class="{ 'no-border': !border }"
>
<g-link :to="path" class="post-card-image-link">
<g-image
:src="record.image"
:alt="record.title"
class="post-card-image"
></g-image>
</g-link>
<div>
<g-link :to="path">
<h2 class="post-card-title mt-3">{{ record.title || record.name }}</h2>
<p class="post-card-excerpt">{{ record.excerpt }}</p>
<section
class="flex flex-wrap post-tags container mx-auto relative py-1"
>
<g-link
v-for="membership in memberships"
:key="membership.id"
:to="membership.path"
class="text-xs bg-transparent hover:text-blue-700 py-1 px-2 mr-1 border hover:border-blue-500 border-gray-600 text-gray-700 rounded-full mb-2"
>{{ membership.title }}</g-link
>
</section>
</g-link>
<div class="w-full post-card-meta pt-2">
<div class="avatars">
<div class="flex items-center">
<div class="flex justify-between items-center">
<ul class="list-none flex author-list m-0">
<li
v-for="author in record.authors"
:key="author.id"
class="author-list-item"
>
<g-link :to="author.path" v-tooltip="author.name">
<g-image
:src="author.image"
:alt="author.name"
class="w-8 h-8 rounded-full bg-gray-200 border-2 border-white"
/>
</g-link>
</li>
</ul>
</div>
<div class="flex flex-col text-xs leading-none uppercase">
<p>
<g-link :to="path">
<time :datetime="record.datetime">{{
record.humanTime
}}</time>
</g-link>
</p>
<p>
<g-link :to="path">
<time :datetime="record.datetime">{{
record.startDate
}}</time>
</g-link>
{{ record.status }}
</p>
</div>
</div>
<section class="post-tags container mx-auto relative py-3" v-if="displaytags()">
<g-link
v-for="tag in record.tags"
:key="tag.id"
:to="tag.path"
class="text-xs bg-transparent hover:text-blue-700 py-2 px-4 mr-2 border hover:border-blue-500 border-gray-600 text-gray-700 rounded-full"
>{{ tag.title }}</g-link
>
</section>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
record: {},
showtags: false,
pathPrefix: "",
border: {
type: Boolean,
default: true,
},
},
computed: {
path(){
if (this.pathPrefix)
return this.pathPrefix + "/" + this.record.id
return this.record.path
},
memberships(){
var res = []
var memberships = this.record.memberships
if (!memberships){
return []
}
memberships.forEach(function(membership){
if(["foundation", "tech"].includes(membership.title)){
res.push(membership)
}
});
return res
}
},
methods: {
displaytags(){
return this.showtags
}
}
}
</script>
<style scoped>
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
.post-card-excerpt {
font-family: "Roboto", sans-serif;
line-height: 1.2;
}
.post-card-image {
max-width: 100%;
height: auto;
}
</style>

View File

@@ -0,0 +1,139 @@
<template>
<div v-if="card"
class="flex search-post px-0 sm:px-4 pb-8 mb-8"
v-bind:class="{ 'no-border': !border }"
>
<g-link :to="record.path" class="post-card-image-link">
<g-image
:src="record.image"
:alt="record.title"
class="post-card-image"
></g-image>
</g-link>
<div class="p-5">
<g-link :to="record.path">
<h2 class="post-card-title mt-3">{{ record.title || record.name }}</h2>
<p class="post-card-excerpt">{{ record.excerpt }}</p>
<section class="post-tags container mx-auto relative py-1">
<g-link
v-for="membership in record.memberships"
:key="membership.id"
:to="membership.path"
class="text-xs bg-transparent hover:text-blue-700 py-1 px-2 mr-1 border hover:border-blue-500 border-gray-600 text-gray-700 rounded-full"
>{{ membership.title }}</g-link
>
</section>
</g-link>
<div class="w-full post-card-meta pt-2">
<div class="avatars">
<div class="flex items-center">
<div class="flex justify-between items-center">
<ul class="list-none flex author-list m-0">
<li
v-for="author in record.authors"
:key="author.id"
class="author-list-item"
>
<g-link :to="author.path" v-tooltip="author.name">
<g-image
:src="author.image"
:alt="author.name"
class="w-8 h-8 rounded-full bg-gray-200 border-2 border-white"
/>
</g-link>
</li>
</ul>
</div>
<div class="flex flex-col text-xs leading-none uppercase">
<p>
<g-link :to="record.path">
<time :datetime="record.datetime">{{
record.humanTime
}}</time>
</g-link>
</p>
<p>
<g-link :to="record.path">
<time :datetime="record.datetime">{{
record.startDate
}}</time>
</g-link>
{{ record.status }}
</p>
</div>
</div>
<section class="post-tags container mx-auto relative py-3">
<g-link
v-for="tag in record.tags"
:key="tag.id"
:to="tag.path"
class="text-xs bg-transparent hover:text-blue-700 py-2 px-4 mr-2 border hover:border-blue-500 border-gray-600 text-gray-700 rounded-full"
>{{ tag.title }}</g-link
>
</section>
</div>
</div>
</div>
</div>
<div v-else
class="flex search-post px-0 sm:px-4 pb-8 mb-8"
v-bind:class="{ 'no-border': !border }"
>
<div class="p-5">
<g-link :to="record.path">
<h2 class="post-card-title mt-3">{{ record.title}}</h2>
<p class="post-card-excerpt" v-if="record.excerpt" >{{ record.excerpt.substring(100) }}</p>
</g-link>
</div>
</div>
</template>
<script>
export default {
props: {
record: {},
border: {
type: Boolean,
default: true,
},
},
computed: {
card(){return this.record.__typename != "MarkdownPage"},
path(){
if (this.pathPrefix)
return this.pathPrefix + "/" + this.record.id
return this.record.path
}
},
};
</script>
<style scoped>
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
.post-card-excerpt {
font-family: "Roboto", sans-serif;
line-height: 1.2;
}
.flex-post {
flex-direction: row;
}
.search-post{
border-bottom-width: 1px;
border-bottom-color: #e2e8f0;
width: 100%;
}
.post-card-image {
max-width: 400px;
height: auto;
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div class="bg-white">
<div class="max-w-7xl mx-auto py-16 px-4 sm:px-6 lg:py-24 lg:px-8">
<div class="grid grid-cols-1 gap-16">
<div class="lg:grid lg:grid-cols-3 lg:gap-8">
<h2 class="text-4xl mb-6 leading-tight font-semibold font-heading">
Get in touch
</h2>
<div
class="mt-8 grid grid-cols-1 gap-12 sm:grid-cols-2 sm:gap-x-8 sm:gap-y-12 lg:mt-0 lg:col-span-2"
>
<div v-for="(contact, idx) in contacts" :key="idx">
<h4 class="text-lg leading-6 font-medium text-gray-700">
{{ contact.title }}
</h4>
<div class="mt-2 text-base leading-6 text-gray-500">
<div>
{{ contact.mail }}
</div>
</div>
<div class="mt-1">
{{ contact.phone }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="border-t-2 border-gray-100"></div>
</div>
</template>
<script>
export default {
props: ["contacts"],
};
</script>

View File

@@ -0,0 +1,304 @@
<template>
<div class="fixed inset-0 h-16 bg-white">
<header
class="flex items-center justify-between flex-wrap container mx-auto px-4 sm:px-0 py-4 transition-all transition-500"
v-bind:class="{
'opacity-100': !disableScroll && scrollPosition > headerHeight,
'opacity-0': !disableScroll && scrollPosition < headerHeight,
}"
>
<div class="flex items-center justify-between px-4 py-3 sm:p-0">
<div class="inline-flex items-center flex-shrink-0">
<a href="/" class="flex">
<img
src="/img/TFN_black.svg"
class="mr-3 fill-current"
width="180"
v-if="theme == 'light'"
alt=""
/>
<img
src="/img/TFN_white.svg"
class="mr-3 fill-current"
width="180"
v-else
alt=""
/>
<!-- <span
class="hidden md:block font-semibold text-xl tracking-tight"
>{{ $static.metadata.siteName }}</span
> -->
</a>
</div>
<div class="sm:hidden ml-auto">
<button
@click="isOpen = !isOpen"
type="button"
class="block text-gray-500 focus:outline-none"
>
<svg class="h-6 w-6 fill-current" viewBox="0 0 24 24">
<path
v-if="isOpen"
fill-rule="evenodd"
d="M18.278 16.864a1 1 0 0 1-1.414 1.414l-4.829-4.828-4.828 4.828a1 1 0 0 1-1.414-1.414l4.828-4.829-4.828-4.828a1 1 0 0 1 1.414-1.414l4.829 4.828 4.828-4.828a1 1 0 1 1 1.414 1.414l-4.828 4.829 4.828 4.828z"
/>
<path
v-if="!isOpen"
fill-rule="evenodd"
d="M4 5h16a1 1 0 0 1 0 2H4a1 1 0 1 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2z"
/>
</svg>
</button>
</div>
<div class="text-gray-400 sm:block md:hidden">
<ul class="list-none flex justify-center md:justify-end">
<li class="mr-0 sm:mr-6">
<theme-switcher v-on="$listeners" :theme="theme" />
</li>
<li
:key="element.name"
v-for="(element, index) in navigation.social"
class="hover:text-white sm:block"
v-bind:class="{
'mr-6': index != Object.keys(navigation.social).length - 1,
}"
>
<span class="telegram_icon">
<a
:href="element.link"
target="_blank"
rel="noopener noreferrer"
>
<font-awesome :icon="['fab', element.icon]" />
</a>
</span>
</li>
</ul>
</div>
</div>
<nav
:class="isOpen ? 'block' : 'hidden'"
class="md:order-2 px-2 pt-2 pb-4 sm:flex sm:p-0 bg-white"
>
<ul
class="list-none sm:flex justify-left uppercase transition-all transition-500"
>
<li
class="py-1"
:key="element.name"
v-for="(element, index) in navigation.navLinks"
:class="{
'mr-2': index != Object.keys(navigation.navLinks).length - 1,
}"
>
<div
v-if="element.expandable"
class="relative"
x-data="{ open: false }"
>
<button
@click="setActive(index)"
class="flex flex-row items-center w-full md:w-auto md:inline md:mt-0 md:ml-4 animated-link"
>
<span class="uppercase">{{ element.name }}</span>
<svg
fill="currentColor"
viewBox="0 0 20 20"
:class="{
'rotate-180': active == index,
'rotate-0': !active == index,
}"
class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
<div
v-if="active == index"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute w-full mt-2 origin-top-right rounded-md shadow-lg md:w-48 z-30"
>
<div
v-if="open"
class="px-2 py-2 bg-white rounded-md shadow dark:bg-gray-700"
>
<div v-for="link in element.submenu" :key="link.title">
<a
v-if="link.external"
class="block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
@click="open = false"
:href="link.path"
target="_blank"
>{{ link.title }}</a
>
<a
v-else
class="block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
@click="open = false"
:href="link.path"
>{{ link.title }}</a
>
</div>
</div>
</div>
</div>
<g-link
v-else-if="element.external"
:to="element.link"
target="_blank"
class="animated-link"
>{{ element.name }}</g-link
>
<g-link v-else :to="element.link" class="animated-link">{{
element.name
}}</g-link>
</li>
</ul>
<div
class="md:hidden inline-flex rounded-full border-2 border-gray-200 w-1/2"
>
<span class="w-auto flex justify-end items-center p-2">
<font-awesome :icon="['fas', 'search']" />
</span>
<input
class="w-full rounded mr-4 bg-white"
type="text"
placeholder="Search..."
v-model="search"
@keyup.enter="result"
/>
</div>
</nav>
<div class="hidden md:ml-auto md:inline-block md:order-last">
<div class="inline-flex rounded-full border-2 border-gray-200 w-1/2">
<span class="w-auto flex justify-end items-center p-2">
<font-awesome :icon="['fas', 'search']" />
</span>
<input
class="w-full rounded mr-4 bg-white"
type="text"
placeholder="Search..."
v-model="search"
@keyup.enter="result"
/>
</div>
<ul class="list-none inline-flex justify-center md:justify-end">
<li class="mr-0 sm:mr-6">
<ThemeSwitcher v-on="$listeners" :theme="theme" />
</li>
<li
:key="element.name"
v-for="(element, index) in navigation.social"
class="sm:block"
v-bind:class="{
'mr-6': index != Object.keys(navigation.social).length - 1,
}"
>
<span class="telegram_icon">
<a :href="element.link" target="_blank" rel="noopener noreferrer">
<font-awesome :icon="['fab', element.icon]" />
</a>
</span>
</li>
</ul>
</div>
</header>
</div>
</template>
<script>
/*
* I'm a lazy guy, so i used this script
* https://codepen.io/ninaregli/pen/OjeMLP
* to calculate the current scroll position
*
* Will be used to add/remove the additional
* css classes to show the sticky navbar
*/
import ThemeSwitcher from "~/components/custom/ThemeSwitcher.vue";
export default {
components: {
ThemeSwitcher,
},
props: {
disableScroll: {
type: Boolean,
default: true,
},
theme: {
type: String,
},
navigation: {
type: Object,
},
},
data: function () {
return {
scrollPosition: null,
headerHeight: 0,
isOpen: false,
search: "",
open: false,
active: null,
};
},
methods: {
updateScroll() {
this.scrollPosition = window.scrollY;
},
setHeaderHeight(height) {
this.headerHeight = height;
},
result() {
window.location.href = `/search?query=${this.search}`;
},
setActive(index) {
this.active = index;
this.open = !this.open;
},
close(e) {
if (!this.$el.contains(e.target)) {
this.open = false;
}
},
},
mounted() {
if (!this.disableScroll) {
var height = document.getElementById("header").clientHeight;
this.setHeaderHeight(height);
window.addEventListener("scroll", this.updateScroll);
}
document.addEventListener("click", this.close);
},
beforeDestroy() {
document.removeEventListener("click", this.close);
},
};
</script>
<style scoped>
input:focus,
button:focus {
outline: 0;
}
.inset-0 {
z-index: 999;
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<div class="my-12">
<nav class="inline-block w-1/4 border-r-2 border-gray-200">
<a
v-for="(slide, index) in slides"
:key="index"
:href="`#${index}`"
class="mt-1 capitalize group flex items-center px-3 py-2 text-sm leading-5 font-medium hover:text-gray-900 focus:outline-none border-blue-500 hover:bg-gray-100 transition ease-in-out duration-150"
:class="{
'border-r-3 border-blue-500 hover:bg-gray-100': activeIndex === index,
}"
@click="setActive(index)"
>
<span> {{ slide.title }} </span>
</a>
</nav>
<div
class="content inline-block h-full w-3/4 align-top p-5 transition ease-in-out duration-150"
>
<div :id="slides[activeIndex]" class="hidden" style="display: block">
<g-image
v-if="slides[activeIndex].image"
:src="
require(`!!assets-loader!@images/sliders/${slides[activeIndex].image}`)
"
:alt="slides[activeIndex].title"
/>
<p>{{ slides[activeIndex].excerpt }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["slides"],
data() {
return {
activeIndex: 0,
};
},
methods: {
setActive(index) {
this.activeIndex = index;
},
},
};
</script>

View File

@@ -0,0 +1,285 @@
<template>
<div class="fixed top-16 left-0 z-50 mb-5 h-16 bg-gray-100 w-full">
<header
class="flex items-center justify-between flex-wrap container mx-auto px-4 py-1 sm:px-0 transition-all transition-500"
>
<div class="flex items-center justify-between px-4 py-2 sm:p-0">
<div class="sm:hidden ml-auto">
<button
@click="isOpen = !isOpen"
type="button"
class="block text-gray-500 focus:outline-none"
>
<svg class="h-6 w-6 fill-current" viewBox="0 0 24 24">
<path
v-if="isOpen"
fill-rule="evenodd"
d="M18.278 16.864a1 1 0 0 1-1.414 1.414l-4.829-4.828-4.828 4.828a1 1 0 0 1-1.414-1.414l4.828-4.829-4.828-4.828a1 1 0 0 1 1.414-1.414l4.829 4.828 4.828-4.828a1 1 0 1 1 1.414 1.414l-4.828 4.829 4.828 4.828z"
/>
<path
v-if="!isOpen"
fill-rule="evenodd"
d="M4 5h16a1 1 0 0 1 0 2H4a1 1 0 1 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2zm0 6h16a1 1 0 0 1 0 2H4a1 1 0 0 1 0-2z"
/>
</svg>
</button>
</div>
<div class="inline-flex items-center flex-shrink-0">
<span class="flex text-xl p-3 capitalize tracking-tight">filter</span>
</div>
</div>
<div class="sm:block md:hidden">
<ul class="list-none inline-flex justify-center md:justify-end">
<li class="py-1 mx-5 cursor-pointer" @click="resetAll()">Reset</li>
</ul>
</div>
<nav
:class="isOpen ? 'flex' : 'hidden'"
class="inline-flex md:order-2 sm:w-28 px-2 pt-2 pb-4 sm:flex sm:p-0 bg-gray-100"
>
<ul
class="list-none sm:flex justify-left capitalize transition-all transition-500"
>
<!-- Topics -->
<li class="py-1 mx-5">
<div class="relative" x-data="{ open: false }">
<button
@click="setActive(0)"
class="flex flex-row items-center w-full md:w-auto md:inline md:mt-0 md:ml-4 animated-link"
>
<span class="capitalize">{{ topic }}</span>
<svg
fill="currentColor"
viewBox="0 0 20 20"
:class="{
'rotate-180': active == 0,
'rotate-0': !active == 0,
}"
class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
<div
v-if="active == 0"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute w-full mt-2 origin-top-right rounded-md shadow-lg md:w-48 z-30"
>
<div
v-if="open"
class="w-64 max-h-10 px-2 py-2 bg-white rounded-md shadow dark:bg-gray-700"
>
<a
v-for="topic in topics"
:key="topic"
class="cursor-pointer block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
@click.self="
setTopic(topic);
open = false;
"
>{{ topic }}</a
>
</div>
</div>
</div>
</li>
<!-- Years -->
<li class="py-1 mx-5">
<div class="relative" x-data="{ open: false }">
<button
@click="setActive(1)"
class="flex flex-row items-center w-full md:w-auto md:inline md:mt-0 md:ml-4 animated-link"
>
<span class="capitalize">{{ year }}</span>
<svg
fill="currentColor"
viewBox="0 0 20 20"
:class="{
'rotate-180': active == 1,
'rotate-0': !active == 1,
}"
class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
<div
v-if="active == 1"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute w-full mt-2 origin-top-right rounded-md shadow-lg md:w-48 z-30"
>
<div
v-if="open"
class="w-64 px-2 py-2 bg-white rounded-md shadow dark:bg-gray-700"
>
<a
v-for="year in years"
:key="year"
class="cursor-pointer block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
@click.self="
setYear(year);
open = false;
"
>{{ year }}</a
>
</div>
</div>
</div>
</li>
<!-- Months -->
<li class="py-1 mx-5">
<div class="relative" x-data="{ open: false }">
<button
@click="setActive(2)"
class="flex flex-row items-center w-full md:w-auto md:inline md:mt-0 md:ml-4 animated-link"
>
<span class="capitalize">{{ month }}</span>
<svg
fill="currentColor"
viewBox="0 0 20 20"
:class="{
'rotate-180': active == 2,
'rotate-0': !active == 2,
}"
class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
<div
v-if="active == 2"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute w-full mt-2 origin-top-right rounded-md shadow-lg md:w-48 z-30"
>
<div
v-if="open"
class="w-64 overflow-y-auto h-40 px-2 py-2 bg-white rounded-md shadow dark:bg-gray-700"
>
<a
v-for="month in months"
:key="month"
class="cursor-pointer block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
@click.self="
setMonth(month);
open = false;
"
>{{ month }}</a
>
</div>
</div>
</div>
</li>
</ul>
</nav>
<div class="hidden md:ml-auto md:inline-block md:order-last">
<ul class="list-none inline-flex justify-center md:justify-end">
<li class="py-1 mx-5 cursor-pointer" @click="resetAll()">Reset</li>
</ul>
</div>
</header>
</div>
</template>
<script>
/*
* I'm a lazy guy, so i used this script
* https://codepen.io/ninaregli/pen/OjeMLP
* to calculate the current scroll position
*
* Will be used to add/remove the additional
* css classes to show the sticky navbar
*/
export default {
props: ["topics", "years", "months"],
data: function () {
return {
isOpen: false,
open: false,
active: null,
listArchive: false,
topic: "All Topics",
year: "All Years",
month: "All Months",
};
},
methods: {
setActive(index) {
this.active = index;
this.open = !this.open;
},
setTopic(event) {
this.$emit("selectedTopic", event);
this.topic = event;
},
setYear(event) {
this.$emit("selectedYear", event);
this.year = event;
},
setMonth(event) {
this.$emit("selectedMonth", event);
this.month = event;
},
resetAll() {
this.$emit("resetAll", true);
this.topic = "All Topics";
this.year = "All Year";
this.month = "All Months";
},
close(e) {
if (!this.$el.contains(e.target)) {
this.open = false;
}
},
},
mounted() {
document.addEventListener("click", this.close);
},
beforeDestroy() {
document.removeEventListener("click", this.close);
},
};
</script>
<style scoped>
.top-16 {
top: 4rem;
}
</style>

View File

@@ -0,0 +1,86 @@
<template>
<ul class="flex pl-0 list-none rounded my-2">
<li class="w-10 relative block text-center py-2 leading-tight bg-white border border-gray-300 text-black ml-0 mr-1 rounded hover:bg-gray-300" v-if="!isFirstPage(currentPage, totalPages)">
<g-link :to="previousPage(currentPage,totalPages)" class="page-link" tabindex="-1" >&laquo;</g-link>
</li>
<li
v-for="page in pages" :key="page.name"
v-bind:class="[isCurrentPage(currentPage, page.name) ? 'border-l-2 border-l-black' : '']"
class="w-10 relative block py-2 text-center leading-tight bg-white border border-gray-300 text-black rounded hover:bg-gray-300 ml-1 mr-1">
<g-link
:to="page.link"
class="page-link"
:aria-label="page.name"
:aria-current="page.name"
>{{page.name}}</g-link>
</li>
<li class="w-10 relative block py-2 text-center leading-tight bg-white border border-gray-300 text-black ml-1 rounded hover:bg-gray-300" v-if="!isLastPage(currentPage, totalPages)">
<g-link :to="nextPage(currentPage,totalPages)" class="page-link" tabindex="-1" >&raquo;</g-link>
</li>
</ul>
</template>
<script>
export default {
props: {
baseUrl: String,
currentPage: Number,
totalPages: Number,
maxVisibleButtons: {
type: Number,
required: false,
default: 3
}
},
methods: {
isFirstPage(currentPage, totalPages) {
return currentPage == 1;
},
isLastPage(currentPage, totalPages) {
return currentPage == totalPages;
},
isCurrentPage(currentPage, pageElement) {
return currentPage == pageElement;
},
nextPage(currentPage, totalPages) {
return `${this.baseUrl}/${currentPage + 1}`;
},
previousPage(currentPage, totalPages) {
return currentPage === 2
? `${this.baseUrl}/`
: `${this.baseUrl}/${currentPage - 1}`;
}
},
computed: {
startPage() {
if (this.currentPage === 1) {
return 1;
}
if (this.currentPage === this.totalPages) {
return this.currentPage - 1;
}
return this.currentPage - 1;
},
pages() {
const range = [];
for (
let i = this.startPage;
i <=
Math.min(this.startPage + this.maxVisibleButtons - 1, this.totalPages);
i += 1
) {
range.push({
name: i,
isDisabled: i === this.currentPage,
link: i === 1 ? `${this.baseUrl}/` : `${this.baseUrl}/${i}`
});
}
return range;
}
}
};
</script>

View File

@@ -0,0 +1,122 @@
<template>
<div class="fixed top-16 left-0 z-50 mb-5 h-16 bg-gray-100 w-full">
<header
class="flex items-center flex-wrap container mx-auto pt-1 pb-0 sm:px-0 transition-all transition-500"
>
<div class="flex items-center justify-between px-4 sm:p-0">
<div class="inline-flex items-center flex-shrink-0">
<span class="flex text-xl p-3 capitalize tracking-tight"
>filter:</span
>
</div>
</div>
<nav
class="inline-flex md:order-2 px-2 pt-2 pb-4 sm:flex sm:p-0 bg-transparent"
>
<ul
class="list-none sm:flex justify-left capitalize transition-all transition-500"
>
<!-- Tags -->
<li class="pt-2 mx-5">
<div class="relative" x-data="{ open: false }">
<button
@click="setActive(0)"
class="flex flex-row items-center w-full md:w-auto md:inline md:mt-0 md:ml-4 animated-link"
>
<span class="capitalize">{{ selected }}</span>
<svg
fill="currentColor"
viewBox="0 0 20 20"
:class="{
'rotate-180': active == 0,
'rotate-0': !active == 0,
}"
class="inline w-4 h-4 mt-1 ml-1 transition-transform duration-200 transform md:-mt-1"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
<div
v-if="active == 0"
x-show="open"
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute w-full mt-2 origin-top-right rounded-md shadow-lg md:w-48 z-30"
>
<div
v-if="open"
class="w-64 max-h-10 px-2 py-2 bg-white rounded-md shadow dark:bg-gray-700"
>
<a
v-for="tag in tags"
:key="tag.path"
class="cursor-pointer block px-4 py-2 mt-2 text-sm font-semibold bg-transparent rounded-lg dark:bg-transparent dark:hover:bg-gray-600 dark-:focus:bg-gray-600 dark:focus:text-white dark:hover:text-white dark:text-gray-200 md:mt-0 hover:text-gray-900 focus:text-gray-900 hover:bg-gray-200 focus:bg-gray-200 focus:outline-none focus:shadow-outline"
:href="tag.path"
@click.self="open = false"
>{{ tag.title }}</a
>
</div>
</div>
</div>
</li>
</ul>
</nav>
</header>
</div>
</template>
<script>
/*
* I'm a lazy guy, so i used this script
* https://codepen.io/ninaregli/pen/OjeMLP
* to calculate the current scroll position
*
* Will be used to add/remove the additional
* css classes to show the sticky navbar
*/
export default {
props: ["tags", "selected"],
data() {
return {
tag: "All",
isOpen: false,
open: false,
active: null,
};
},
methods: {
setActive(index) {
this.active = index;
this.open = !this.open;
},
close(e) {
if (!this.$el.contains(e.target)) {
this.open = false;
}
},
},
mounted() {
document.addEventListener("click", this.close);
},
beforeDestroy() {
document.removeEventListener("click", this.close);
},
};
</script>
<style scoped>
.top-16 {
top: 4rem;
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
<a role="button" @click.prevent="toggleTheme()"
:aria-label="'Toggle ' + nextTheme"
:title="'Toggle ' + nextTheme"
class="toggle-theme"
>
<font-awesome :icon="['fas', 'sun']" class="mr-3" v-if="theme === 'dark'"></font-awesome>
<font-awesome :icon="['fas', 'moon']" class="mr-3" v-if="theme === 'light'"></font-awesome>
</a>
</template>
<script>
let themes = ['light', 'dark']
export default {
props: {
theme: {
type: String,
},
},
computed: {
nextTheme() {
const currentIndex = themes.indexOf(this.theme)
const nextIndex = (currentIndex + 1) % themes.length
return themes[nextIndex]
}
},
methods: {
toggleTheme() {
const currentIndex = themes.indexOf(this.theme);
const nextIndex = (currentIndex + 1) % themes.length;
window.__setPreferredTheme(themes[nextIndex])
this.$emit('setTheme', themes[nextIndex])
}
},
async mounted() {
// set default
if (typeof window.__theme !== 'undefined') this.$emit('setTheme', window.__theme)
}
}
</script>

View File

@@ -0,0 +1,23 @@
<template>
<section class="py-12 px-4 text-center">
<div class="w-full max-w-2xl mx-auto">
<h2 class="text-5xl leading-tight font-semibold font-heading">
{{ cta.title }}
</h2>
<p class="mt-6 mb-8 text-gray-600 leading-relaxed">
{{ cta.excerpt }}
</p>
<g-link
class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 mr-3 font-semibold rounded shadow"
:to="cta.link"
>{{ cta.button }}</g-link
>
</div>
</section>
</template>
<script>
export default {
props: ["cta"],
};
</script>

View File

@@ -0,0 +1,44 @@
<template>
<section class="py-12 px-4 text-center">
<h2 class="text-4xl mb-2 leading-tight font-semibold font-heading">
{{ main.title }}
</h2>
<p class="text-gray-600">{{ main.description }}</p>
<div class="flex flex-wrap items-center -mx-8 mt-12 mb-2">
<div
class="lg:w-1/3 px-8 mb-8"
v-for="(section, index) in sections"
:key="index"
>
<img
class="w-1/2 mx-auto mb-8 h-32"
:src="section.svg.src"
:alt="section.title"
/>
<h3 class="text-2xl mb-4 font-semibold font-heading">
<span
class="inline-flex items-center justify-center h-12 w-12 mr-2 border rounded-full"
>{{ index + 1 }}</span
>
<span>{{ section.title }}</span>
</h3>
<p class="text-gray-600">
{{ section.excerpt }}
</p>
</div>
</div>
<div>
<g-link
class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 mr-3 font-semibold rounded shadow"
:to="main.link"
>{{ main.button }}</g-link
>
</div>
</section>
</template>
<script>
export default {
props: ["main", "sections"],
};
</script>

View File

@@ -0,0 +1,38 @@
<template>
<section class="py-12 px-4">
<h2 class="text-3xl text-center mb-12 font-semibold font-heading">
{{ main.title }}
</h2>
<div class="flex flex-wrap -mx-4 mb-6">
<div
v-for="feature in features"
:key="feature.id"
class="lg:w-1/4 px-4 mb-6"
>
<g-image class="w-10 h-10" :src="feature.svg.src"></g-image>
<h3 class="text-xl my-3 font-semibold font-heading">
{{ feature.title }}
</h3>
<p class="text-sm text-gray-600 leading-relaxed">
{{ feature.excerpt }}
</p>
</div>
</div>
<div class="text-center">
<g-link
class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 mr-3 font-semibold rounded shadow"
:to="main.link"
>{{ main.btn }}</g-link
>
<p class="text-sm text-gray-400 mt-5">
{{ main.excerpt }}
</p>
</div>
</section>
</template>
<script>
export default {
props: ["main", "features"]
};
</script>

View File

@@ -0,0 +1,37 @@
<template>
<section class="py-12 px-4">
<div class="flex flex-wrap items-center text-center lg:text-left -mx-2">
<div class="lg:w-1/2 px-2">
<g-image
class="g-image g-image--lazy g-image--loading"
:src="main.image.src"
:alt="main.title"
></g-image>
</div>
<div class="lg:w-1/2 px-2 lg:pl-16 mt-10 lg:mt-0">
<h2 class="text-4xl px-4 mb-4 leading-tight font-semibold font-heading">
{{ main.title }}
</h2>
<div
class="p-4 mb-4"
:class="{ 'rounded shadow-md': index % 2 !== 0 }"
v-for="(howItWorkSec, index) in HIWData"
:key="index"
>
<h3 class="text-2xl mb-2 font-semibold font-heading">
{{ howItWorkSec.title }}
</h3>
<p class="text-gray-600 leading-relaxed">
{{ howItWorkSec.excerpt }}
</p>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
props: ["HIWData", "main"],
};
</script>

View File

@@ -0,0 +1,62 @@
<template>
<!-- component -->
<div class="container bg-gray-200 mx-auto w-full h-full">
<div class="relative wrap overflow-hidden p-10 h-full">
<div
class="border-2-2 absolute border-opacity-20 border-gray-700 h-full border"
style="left: 50%"
></div>
<div
v-for="(post, index) in roadmap"
:key="index"
class="mb-8 flex justify-between items-center w-full"
:class="{
'flex-row-reverse left-timeline': index % 2 !== 0,
'right-timeline': index % 2 == 0,
}"
>
<div class="order-1 w-5/12"></div>
<div
class="z-20 flex items-center order-1 bg-gray-800 shadow-xl w-8 h-8 rounded-full"
>
<h1 class="mx-auto font-semibold text-lg text-white">
{{ index + 1 }}
</h1>
</div>
<div
class="order-1 rounded-lg shadow-xl w-5/12 px-6 py-4"
:class="{
'bg-red-400': index % 2 !== 0,
'bg-gray-400': index % 2 == 0,
}"
>
<h3
class="mb-3 font-bold text-xl"
:class="{
'text-white': index % 2 !== 0,
'text-gray-800': index % 2 == 0,
}"
>
{{ post.title }}
</h3>
<p
class="text-sm leading-snug tracking-wide text-opacity-100"
:class="{
'text-white': index % 2 !== 0,
'text-gray-800': index % 2 == 0,
}"
>
{{ post.excerpt }}
</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ["roadmap"],
};
</script>

View File

@@ -0,0 +1,28 @@
<template>
<section class="py-8 px-4">
<div class="flex flex-wrap items-center -mx-4">
<div class="w-full lg:w-4/6 px-4 mb-8 lg:mb-0 text-center lg:text-left">
<h2 class="text-xl font-semibold font-heading">
{{ signup.title }}
</h2>
</div>
<div class="w-full lg:w-2/6 px-4 text-center">
<g-link
class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 mr-3 font-semibold rounded shadow"
:to="signup.link1"
>{{ signup.button1 }}</g-link
><g-link
class="text-gray-900 bg-transparent hover:underline"
:to="signup.link2"
>{{ signup.button2 }}</g-link
>
</div>
</div>
</section>
</template>
<script>
export default {
props: ["signup"],
};
</script>

View File

@@ -0,0 +1,32 @@
<template>
<section class="py-12 px-4 text-center">
<div class="w-full max-w-2xl mx-auto">
<span class="text-sm font-semibold">{{ header.title }}</span>
<h2 class="text-5xl mt-2 mb-6 leading-tight font-semibold font-heading">
{{ header.subtitle }}
</h2>
<p class="mb-8 text-gray-600 leading-relaxed">
{{ header.excerpt }}
</p>
<div>
<g-link
class="bg-gray-900 learn-button hover:bg-gray-700 text-gray-100 px-5 py-3 mr-3 font-semibold rounded shadow"
v-if="header.btn1"
:to="header.link1"
>{{ header.btn1 }}</g-link
><g-link
class="text-gray-900 bg-transparent hover:underline"
v-if="header.btn2"
:to="header.link2"
>{{ header.btn2 }}</g-link
>
</div>
</div>
</section>
</template>
<script>
export default {
props: ["header"],
};
</script>