Merge bristol-js/main

This commit is contained in:
Oliver Davies 2025-10-02 08:19:37 +01:00
commit 5a78a86bdc
22 changed files with 9242 additions and 0 deletions

23
bristol-js/.gitignore vendored Normal file
View file

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

24
bristol-js/README.md Normal file
View file

@ -0,0 +1,24 @@
# bristoljs-demo
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View file

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

44
bristol-js/package.json Normal file
View file

@ -0,0 +1,44 @@
{
"name": "bristoljs-demo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"tailwindcss": "^1.8.5",
"vue": "^2.6.11"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"tailwindcss-aspect-ratio": "^3.0.0",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

View file

@ -0,0 +1,5 @@
module.exports = {
plugins: [
require('tailwindcss')
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;700;900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

118
bristol-js/src/App.vue Normal file
View file

@ -0,0 +1,118 @@
<template>
<div id="app" class="font-display text-black">
<navbar :name="title" />
<div class="h-48 flex items-center justify-center bg-yellow">
<div class="p-4 text-center">
<h1 class="text-4xl leading-none font-bold">{{ title }}</h1>
<p class="mt-6 text-sm">{{ description }}</p>
</div>
</div>
<main>
<recent-talks/>
<div class="max-w-6xl px-3 mx-auto">
<div class="mt-12 mb-20 grid gap-8 md:grid-cols-3">
<div
class="flex flex-col-reverse space-y-6 space-y-reverse"
style="justify-content: start"
>
<div class="space-y-2">
<h2 class="text-lg font-bold text-center">About</h2>
<p class="font-body text-center text-sm leading-relaxed">Since May 2012 we've held monthly JavaScript talks. Today the group is over 800 members strong and has a great friendly community that we've been proud to see grow.</p>
</div>
<div>
<svg class="mx-auto h-16 w-16 fill-current text-yellow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"/></svg>
</div>
</div>
<div
class="flex flex-col-reverse space-y-6 space-y-reverse"
style="justify-content: start"
>
<div class="space-y-2">
<h2 class="text-lg font-bold text-center">Format</h2>
<p class="font-body text-center text-sm leading-relaxed">Talk nights are usually held on the last Wednesday of every month. They usual consist of two main talks and occasionally lightning talks that can be on any topic.</p>
</div>
<div>
<svg class="mx-auto h-16 w-16 fill-current text-yellow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M347.94 129.86L203.6 195.83a31.938 31.938 0 00-15.77 15.77l-65.97 144.34c-7.61 16.65 9.54 33.81 26.2 26.2l144.34-65.97a31.938 31.938 0 0015.77-15.77l65.97-144.34c7.61-16.66-9.54-33.81-26.2-26.2zm-77.36 148.72c-12.47 12.47-32.69 12.47-45.16 0-12.47-12.47-12.47-32.69 0-45.16 12.47-12.47 32.69-12.47 45.16 0 12.47 12.47 12.47 32.69 0 45.16zM248 8C111.03 8 0 119.03 0 256s111.03 248 248 248 248-111.03 248-248S384.97 8 248 8zm0 448c-110.28 0-200-89.72-200-200S137.72 56 248 56s200 89.72 200 200-89.72 200-200 200z"/></svg>
</div>
</div>
<div
class="flex flex-col-reverse space-y-6 space-y-reverse"
style="justify-content: start"
>
<div class="space-y-2">
<h2 class="text-lg font-bold text-center">Fancy speaking?</h2>
<p class="font-body text-center text-sm leading-relaxed">Bristol JS is only as strong as it's speakers so we're always on the lookout for great talks. Drop us an <a href="#0">e-mail</a> with an outline of your talk as well as your availability, if it's right for us we'll get you booked in.</p>
</div>
<div>
<svg class="mx-auto h-16 w-16 fill-current text-yellow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M576 240c0-23.63-12.95-44.04-32-55.12V32.01C544 23.26 537.02 0 512 0c-7.12 0-14.19 2.38-19.98 7.02l-85.03 68.03C364.28 109.19 310.66 128 256 128H64c-35.35 0-64 28.65-64 64v96c0 35.35 28.65 64 64 64h33.7c-1.39 10.48-2.18 21.14-2.18 32 0 39.77 9.26 77.35 25.56 110.94 5.19 10.69 16.52 17.06 28.4 17.06h74.28c26.05 0 41.69-29.84 25.9-50.56-16.4-21.52-26.15-48.36-26.15-77.44 0-11.11 1.62-21.79 4.41-32H256c54.66 0 108.28 18.81 150.98 52.95l85.03 68.03a32.023 32.023 0 0019.98 7.02c24.92 0 32-22.78 32-32V295.13C563.05 284.04 576 263.63 576 240zm-96 141.42l-33.05-26.44C392.95 311.78 325.12 288 256 288v-96c69.12 0 136.95-23.78 190.95-66.98L480 98.58v282.84z"/></svg>
</div>
</div>
</div>
</div>
<div class="max-w-6xl mx-auto pt-12 pb-24">
<div class="grid gap-6 md:grid-cols-2">
<frequently-asked/>
</div>
</div>
</main>
<aside class="py-24 px-4 bg-gray-50">
<our-sponsors/>
</aside>
<footer class="py-20 bg-black">
<div class="max-w-6xl mx-auto px-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
<section>
<h2 class="pb-2 text-xl font-bold border-b-2 text-white">Links</h2>
<div class="mt-6 space-x-1">
<a href="#" class="btn btn-blue">Meetup</a>
<a href="#" class="btn btn-blue">Twitter</a>
<a href="#" class="btn btn-blue">YouTube</a>
</div>
</section>
</div>
</div>
</footer>
</div>
</template>
<script>
import FrequentlyAsked from '@/components/frequently-asked'
import Navbar from '@/components/navbar'
import OurSponsors from '@/components/our-sponsors'
import RecentTalks from '@/components/recent-talks'
export default {
name: 'App',
components: {
FrequentlyAsked,
Navbar,
OurSponsors,
RecentTalks
},
data() {
return {
title: 'Bristol JS',
description: 'We host monthly JavaScript meetings in the beautiful city of Bristol, UK.'
}
}
}
</script>
<style src="@/assets/css/tailwind.css"/>

View file

@ -0,0 +1,19 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply px-4 py-3 inline-block text-lg rounded-lg
}
.btn-blue {
@apply bg-blue-500 border border-blue-600 text-white;
@apply transition-colors ease-in-out duration-300;
@apply hover:bg-blue-550
}
.link {
@apply text-blue-500 hover:text-blue-600
}
}

View file

@ -0,0 +1,10 @@
<template>
<div class="space-y-2">
<h2 class="pb-2 text-lg font-bold border-b-2">Frequently Asked</h2>
<ul class="space-y-1">
<li><a class="link text-lg font-bold" href="#0">Who can speak?</a></li>
<li><a class="link text-lg font-bold" href="#0">Is Bristol JS free to attend?</a></li>
</ul>
</div>
</template>

View file

@ -0,0 +1,91 @@
<template>
<div class="bg-black">
<div class="max-w-6xl mx-auto py-6 px-4">
<div class="flex justify-between">
<div class="w-1/2 flex items-center">
<a class="text-lg text-white font-black" href="#" v-text="name"></a>
</div>
<div class="w-1/2 flex justify-end md:hidden">
<button class="text-white focus:text-yellow" type="button" @click="isOpen = !isOpen">
<span class="sr-only">Toggle mobile nav</span>
<svg
class="h-8 w-8"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<nav class="hidden space-x-6 md:block">
<a
class="
font-body text-xs font-bold uppercase
hover:text-yellow
focus:text-yellow
"
href="#"
v-for="(link, i) in links"
:class="{
'text-white': !link.isActive,
'text-yellow': link.isActive
}"
:key="i"
>
{{ link.text }}
</a>
</nav>
</div>
</div>
<div :class="{ hidden: !isOpen }" class="absolute w-full bg-black md:hidden">
<nav class="py-3 border-white border-t">
<a
class="
px-4 py-3 block text-xs font-bold uppercase
hover:text-yellow
focus:text-yellow
"
href="#"
v-for="(link, i) in links"
:class="{
'text-yellow': link.isActive,
'text-white': !link.isActive
}"
:key="i"
>
{{ link.text }}
</a>
</nav>
</div>
</div>
</template>
<script>
export default {
name: 'Navbar',
props: {
name: {
type: String,
required: true
}
},
data() {
return {
links: [
{ text: 'Home', isActive: true },
{ text: 'Talks', isActive: false },
{ text: 'Contact', isActive: false }
],
isOpen: false
}
}
}
</script>

View file

@ -0,0 +1,38 @@
<template>
<section>
<h2 class="text-2xl font-bold uppercase text-center">Our sponsors</h2>
<div class="mt-10">
<div class="max-w-6xl mx-auto px-4">
<div class="grid grid-cols-1 gap-16 sm:grid-cols-2 md:grid-cols-3">
<div v-for="(sponsor, i) in sponsors" :key="i">
<sponsor :sponsor="sponsor"/>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
import Sponsor from '@/components/our-sponsors/sponsor'
import { getSponsors } from '@/services/sponsor-service'
export default {
name: 'OurSponsors',
components: {
Sponsor
},
data() {
return {
sponsors: []
}
},
created() {
this.sponsors = getSponsors()
}
}
</script>

View file

@ -0,0 +1,26 @@
<template>
<div>
<a href="#">
<img
:src="sponsor.logo"
:alt="`${sponsor.name} logo`"
style="max-height: 100px; max-width: 80%"
/>
<span v-text="sponsor.name" class="sr-only"/>
</a>
</div>
</template>
<script>
export default {
name: 'Sponsor',
props: {
sponsor: {
type: Object,
required: true
}
}
}
</script>

View file

@ -0,0 +1,34 @@
<template>
<section class="py-4">
<div class="mx-auto px-4">
<h2 class="text-2xl font-bold uppercase text-center">Recent Talks</h2>
<div class="mt-2 grid grid-cols-1 gap-y-6 gap-x-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<recent-talk v-for="(talk, i) in talks" :key="i" :talk="talk"/>
</div>
</div>
</section>
</template>
<script>
import RecentTalk from '@/components/recent-talks/recent-talk'
import { getTalks } from '@/services/talk-service'
export default {
name: 'RecentTalks',
components: {
RecentTalk
},
data() {
return {
talks: []
}
},
created() {
this.talks = getTalks()
}
}
</script>

View file

@ -0,0 +1,27 @@
<template>
<div class="flex flex-col flex-col-reverse justify-end space-y-5 space-y-reverse">
<div class="py-2 text-lg font-bold border-t-2 border-b-2">
{{ talk.title }}
</div>
<div class="block relative h-0 overflow-hidden aspect-ratio-16/9">
<iframe
class="absolute w-full h-full inset-0 border-0"
:src="`https://www.youtube.com/embed/${talk.videoId}`"
/>
</div>
</div>
</template>
<script>
export default {
name: 'RecentTalk',
props: {
talk: {
type: Object,
required: true
}
}
}
</script>

View file

@ -0,0 +1,28 @@
{
"sponsors": [
{
"name": "Novate IT",
"logo": "http://bristoljs.org/assets/img/sponsors/novate.png"
},
{
"name": "POTATO",
"logo": "http://bristoljs.org/assets/img/sponsors/potato.png"
},
{
"name": "Pusher",
"logo": "http://bristoljs.org/assets/img/sponsors/pusher.png"
},
{
"name": "Just Eat",
"logo": "http://bristoljs.org/assets/img/sponsors/just-eat.png"
},
{
"name": "basekit",
"logo": "http://bristoljs.org/assets/img/sponsors/basekit.png"
},
{
"name": "cxpartners",
"logo": "http://bristoljs.org/assets/img/sponsors/cx-partners.png"
}
]
}

View file

@ -0,0 +1,44 @@
{
"talks": [
{
"title": "ES6 & JSPM",
"videoId": "mIBqsXLXmc0"
},
{
"title": "Libraries.io",
"videoId": "2tNH-JLbXGk"
},
{
"title": "Hardware Hacking",
"videoId": "a_u3OdqeYvI"
},
{
"title": "Libraries.io",
"videoId": "ROUvsRJipUs"
},
{
"title": "Building OS X apps with JavaScript",
"videoId": "og6K_3kEfQk"
},
{
"title": "Web Audio API",
"videoId": "avEVbuv62U8"
},
{
"title": "Open Source Everyday",
"videoId": "XnLMKu-l_do"
},
{
"title": "Style Matters",
"videoId": "zYFBptgX9FY"
},
{
"title": "Responsive copy writing & smart formatting",
"videoId": "kp1IC_Oi5_8"
},
{
"title": "IndexDB",
"videoId": "6vGiCYy0hug"
}
]
}

8
bristol-js/src/main.js Normal file
View file

@ -0,0 +1,8 @@
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')

View file

@ -0,0 +1,5 @@
import sponsors from '@/data/sponsors.json'
export function getSponsors() {
return sponsors.sponsors
}

View file

@ -0,0 +1,5 @@
import talks from '@/data/talks.json'
export function getTalks() {
return talks.talks
}

View file

@ -0,0 +1,42 @@
module.exports = {
purge: {
mode: 'layers',
content: [
'public/index.html',
'src/**/*.vue'
]
},
theme: {
aspectRatio: {
'16/9': [16, 9]
},
colors: {
black: '#222',
gray: {
50: '#f7f7f7'
},
blue: {
500: '#337ab7',
550: '#286090',
600: '#204d74'
},
white: '#fff',
yellow: '#fde546'
},
fontFamily: {
display: ['Raleway'],
body: ['Lato']
},
extend: {},
},
variants: {},
plugins: [
require('tailwindcss-aspect-ratio')
],
experimental: {
applyComplexClasses: true
},
future: {
purgeLayersByDefault: true
}
}

8627
bristol-js/yarn.lock Normal file

File diff suppressed because it is too large Load diff