Merge pull request #23 from Keksike/master

Add Yhdistys-page with membership-form
This commit is contained in:
Cihan Bebek
2017-07-12 11:57:09 +03:00
committed by GitHub
17 changed files with 733 additions and 183 deletions

View File

@@ -8,6 +8,8 @@
"scripts": {
"start": "rm -rf public && gulp",
"build": "rm -rf public && gulp build",
"dev": "SERVER=http://localhost:9000/ ENV=development npm start",
"prod": "ENV=production npm start",
"lint": "eslint src",
"test": "mocha src/**/__tests__/*.js --compilers js:babel-core/register --require test/test-helper"
},
@@ -22,8 +24,10 @@
"http-server": "^0.8.0",
"lodash": "^3.9.1",
"parse-github-event": "^0.2.0",
"prop-types": "^15.5.10",
"react": "^0.14.3",
"react-dom": "^0.14.3",
"react-stripe-checkout": "^2.4.0",
"timeago": "^0.2.0",
"twitter-text": "^1.11.0"
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

16
src/config.js Normal file
View File

@@ -0,0 +1,16 @@
var development = {
stripe: {
publicKey: "pk_test_OmNve9H1OuORlmD4rblpjgzh"
}
}
var production = {
stripe: {
publicKey: "pk_live_xrnwdLNXbt20LMxpIDffJnnC"
}
}
module.exports = function () {
return process.env.ENV == 'development' ? development : production;
}

View File

@@ -1,150 +1,79 @@
doctype html
html
head
title Koodiklinikka
// inject:css
// endinject
meta(name='description', content='Koodiklinikka on suomalainen Slack-yhteisö ohjelmistoalan harrastajille ja ammattilaisille.')
meta(name='keywords', content='ohjelmointi,frontend,open source,devaus,suomi,javascript,clojure,go,java,node.js,io.js,angular.js,web')
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
meta(name='apple-mobile-web-app-capable', content='yes')
extends templates/head
script.
if(location.hostname === 'koodiklinikka.fi' && location.protocol !== 'https:') {
location.protocol = 'https';
}
link(rel='apple-touch-icon', sizes='57x57', href='icons/apple-touch-icon-57x57.png')
link(rel='apple-touch-icon', sizes='114x114', href='icons/apple-touch-icon-114x114.png')
link(rel='apple-touch-icon', sizes='72x72', href='icons/apple-touch-icon-72x72.png')
link(rel='apple-touch-icon', sizes='144x144', href='icons/apple-touch-icon-144x144.png')
link(rel='apple-touch-icon', sizes='60x60', href='icons/apple-touch-icon-60x60.png')
link(rel='apple-touch-icon', sizes='120x120', href='icons/apple-touch-icon-120x120.png')
link(rel='apple-touch-icon', sizes='76x76', href='icons/apple-touch-icon-76x76.png')
link(rel='apple-touch-icon', sizes='152x152', href='icons/apple-touch-icon-152x152.png')
link(rel='apple-touch-icon', sizes='180x180', href='icons/apple-touch-icon-180x180.png')
link(rel='icon', type='image/png', href='icons/favicon-192x192.png', sizes='192x192')
link(rel='icon', type='image/png', href='icons/favicon-160x160.png', sizes='160x160')
link(rel='icon', type='image/png', href='icons/favicon-96x96.png', sizes='96x96')
link(rel='icon', type='image/png', href='icons/favicon-16x16.png', sizes='16x16')
link(rel='icon', type='image/png', href='icons/favicon-32x32.png', sizes='32x32')
link(rel='shortcut icon', href='icons/favicon.ico')
link(rel='icon', href='icons/favicon.ico')
meta(name='msapplication-TileColor', content='#10558c')
meta(name='msapplication-TileImage', content='icons/mstile-144x144.png')
meta(property='og:image', content='images/logo.png')
script(src='//use.typekit.net/scb5xny.js')
script.
try{Typekit.load();}catch(e){};
block title
| Koodiklinikka
body
.site
.container
.header
video(autoplay, loop, poster='images/poster.jpg', class='header__video-bg')
source(src='videos/jumbo.mp4', type='video/mp4')
.header__container
.header__headline
.header__logo
h1.header__title <a target="_blank" href="https://slack.com/">Slack</a>-yhteisö kaikille ohjelmoinnista ja ohjelmistoalasta kiinnostuneille harrastajille ja&nbsp;ammattilaisille.
block header_content
video(autoplay, loop, poster='images/poster.jpg', class='header__video-bg')
source(src='videos/jumbo.mp4', type='video/mp4')
.header__container
.header__nav
a(href='/') etusivu
a(href='/yhdistys.html') yhdistys
.header__headline
.header__logo
h1.header__title <a target="_blank" href="https://slack.com/">Slack</a>-yhteisö kaikille ohjelmoinnista ja ohjelmistoalasta kiinnostuneille harrastajille ja&nbsp;ammattilaisille.
.content
section
.row
h3 Tule mukaan
#invite-form
block content
.content.with-feed
section
.row
h3 Tule mukaan
#invite-form.form
section
.row
.bread
.column.column1-2
h3 Yhteisö ohjelmoinnista kiinnostuneille
p.
Koodiklinikka on Suomen suurin ohjelmistoalan yhteisö, joka kokoaa työntekijät, harrastajat ja vasta-alkajat yhteen.
Tarkoituksenamme on yhdistää ja kasvattaa suomalaista ohjelmointiyhteisöä, sekä tarjota apua ja uusia kontakteja ohjelmoinnista innostuneille nuorille.
p.
Mukaan liittyminen on ilmaista ja helppoa. Jätä sähköpostiosoitteesi ylläolevaan kenttään ja lähetämme sinulle kutsun Slack-yhteisöömme.
.column.column1-2
a(href='images/slack.png', target='_blank')
img(src='images/slack.png')
section
.row
.bread
.column.column1-2
h3 Yhteisö ohjelmoinnista kiinnostuneille
p.
Koodiklinikka on Suomen suurin ohjelmistoalan yhteisö, joka kokoaa työntekijät, harrastajat ja vasta-alkajat yhteen.
Tarkoituksenamme on yhdistää ja kasvattaa suomalaista ohjelmointiyhteisöä, sekä tarjota apua ja uusia kontakteja ohjelmoinnista innostuneille nuorille.
p.
Mukaan liittyminen on ilmaista ja helppoa. Jätä sähköpostiosoitteesi ylläolevaan kenttään ja lähetämme sinulle kutsun Slack-yhteisöömme.
.column.column1-2
a(href='images/slack.png', target='_blank')
img(src='images/slack.png')
.row
.bread
.column.column2-5
img(src='images/octocat.png')
.row
.bread
.column.column2-5
img(src='images/octocat.png')
.column.column3-5
h3 Avoin lähdekoodi
p
|Suosimme avointa lähdekoodia ja kaikki käyttämämme koodi on vapaasti saatavilla ja hyödynnettävissä <a href="https://github.com/koodiklinikka">Github-organisaatiomme sivulta</a>.
|Organisaation jäseneksi otamme kaikki Slack-yhteisömme jäsenet ja kontribuutio projekteihimme otetaan lämpimästi vastaan.
.column.column3-5
h3 Avoin lähdekoodi
p
|Suosimme avointa lähdekoodia ja kaikki käyttämämme koodi on vapaasti saatavilla ja hyödynnettävissä <a href="https://github.com/koodiklinikka">Github-organisaatiomme sivulta</a>.
|Organisaation jäseneksi otamme kaikki Slack-yhteisömme jäsenet ja kontribuutio projekteihimme otetaan lämpimästi vastaan.
#members
#members
.row
h2 Potilaiden projekteja
.bread
.column.column2-5
a(href='https://redom.js.org', target='_blank')
img(src='images/redom.svg')
.row
h2 Potilaiden projekteja
.bread
.column.column2-5
a(href='https://redom.js.org', target='_blank')
img(src='images/redom.svg')
.column.column3-5
h4 RE:DOM
.column.column3-5
h4 RE:DOM
p.
Tiny (2 KB) turboboosted JavaScript library for creating user interfaces.
Develop web apps with 100 % JavaScript and web standards.
p.
Tiny (2 KB) turboboosted JavaScript library for creating user interfaces.
Develop web apps with 100 % JavaScript and web standards.
.bread
.column.column2-5
a(href='https://codestats.net/', target='_blank')
img.project-image__codestats(src='images/codestats.png')
.bread
.column.column2-5
a(href='https://codestats.net/', target='_blank')
img.project-image__codestats(src='images/codestats.png')
.column.column3-5
h4 Code::Stats
.column.column3-5
h4 Code::Stats
p.
Code::Stats is a free stats tracking service for programmers
p.
Code::Stats is a free stats tracking service for programmers
#members
#members
#feed
footer
.sponsors
.sponsors__label Yhteistyössä
a(href='http://futurice.com/', target='_blank')
img.sponsor.sponsor__futurice(src='images/futurice.svg')
a(href='http://www.metosin.fi/', target='_blank')
img.sponsor.sponsor__metosin(src='images/metosin.svg')
a(href='https://www.solita.fi/', target='_blank')
img.sponsor(src='images/solita.svg')
a(href='http://leonidasoy.fi/', target='_blank')
img.sponsor.sponsor__leonidas(src='images/leonidas.png')
a(href='https://www.nordea.com/', target='_blank')
img.sponsor.sponsor__nordea(src='images/nordea.png')
.contacts
div
a(href='https://koodiklinikka.slack.com')
i.fa.fa-slack
a(href='https://github.com/koodiklinikka/koodiklinikka.fi')
i.fa.fa-github
a(href='https://twitter.com/koodiklinikka')
i.fa.fa-twitter
a(href='https://www.linkedin.com/groups/12025476')
i.fa.fa-linkedin
a(href='https://www.facebook.com/koodiklinikka')
i.fa.fa-facebook
div#email
#fader
// inject:js
// endinject
#feed

View File

@@ -5,7 +5,7 @@ var React = require('react');
var classSet = require('classnames');
var api = require('../api');
var Loader = require('./loader');
module.exports = React.createClass({
getInitialState() {
return {
@@ -48,6 +48,7 @@ module.exports = React.createClass({
},
render() {
var formClasses = classSet({
'form': true,
'invite-form': true,
'has-success': this.state.submitted,
'has-error': this.state.error,
@@ -76,7 +77,7 @@ module.exports = React.createClass({
}
feedbackMessage = (
<div className='invite-form--message'>
<div className='form--message'>
{messageText}
</div>
);
@@ -98,11 +99,11 @@ module.exports = React.createClass({
disabled={this.state.error || this.state.submitted}>
</button>
<span
className='loader'>
</span>
<div className='invite-form__loader'>
<Loader />
</div>
{feedbackMessage}
</form>
)
);
}
});

View File

@@ -0,0 +1,12 @@
const React = require('react');
module.exports = function Loader() {
return (
<div className='sk-folding-cube'>
<div className='sk-cube1 sk-cube'></div>
<div className='sk-cube2 sk-cube'></div>
<div className='sk-cube4 sk-cube'></div>
<div className='sk-cube3 sk-cube'></div>
</div>
);
};

View File

@@ -7,7 +7,7 @@ var _ = require('lodash');
var api = require('../api');
module.exports = React.createClass({
getInitialState() {
getInitialState() {
return {
members: []
};

View File

@@ -0,0 +1,34 @@
import React from 'react';
import MembershipInfoForm from './membershipInfoForm';
module.exports = React.createClass({
getInitialState() {
return {
paymentSuccess: false
};
},
handlePaymentSuccess() {
this.setState({ paymentSuccess: true });
},
render() {
if(!this.state.paymentSuccess) {
return (
<MembershipInfoForm onPaymentSuccess={this.handlePaymentSuccess} />
);
}
return (
<div>
<svg height='50' width='50' viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'>
<path
fill='#349c4a'
d='M256 6.998c-137.533 0-249 111.467-249 249 0 137.534 111.467 249 249 249s249-111.467 249-249c0-137.534-111.467-249-249-249zm0 478.08c-126.31 0-229.08-102.77-229.08-229.08 0-126.31 102.77-229.08 229.08-229.08 126.31 0 229.08 102.77 229.08 229.08 0 126.31-102.77 229.08-229.08 229.08z' />
<path
fill='#349c4a'
d='M384.235 158.192L216.92 325.518 127.86 236.48l-14.142 14.144 103.2 103.18 181.36-181.47' />
</svg>
<p> Maksu ja rekisteröityminen onnistui.</p>
<p> Tervetuloa Koodiklinikka ry:n jäseneksi!</p>
</div>
);
}
});

View File

@@ -0,0 +1,199 @@
'use strict';
var _ = require('lodash');
var request = require('axios');
var React = require('react');
var classSet = require('classnames');
var StripeCheckout = require('react-stripe-checkout').default;
var api = require('../api');
var Loader = require('./loader');
var config = require('../../config.js')();
var fieldNameTranslations = {
address: { fi: 'Osoite' },
city: { fi: 'Paikkakunta' },
email: { fi: 'Sähköpostiosoite' },
handle: { fi: 'Slack-käyttäjätunnus ' },
name: { fi: 'Koko nimi ' },
postcode: { fi: 'Postinumero' }
};
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
const fieldNames = ['name', 'email', 'handle', 'address', 'city', 'postcode'];
function getUserInfo(state) {
return _.pick(state, fieldNames);
}
module.exports = React.createClass({
getInitialState() {
return {
address: '',
city: '',
email: '',
handle: '',
name: '',
postcode: '',
sending: false,
pristineFields: fieldNames
};
},
onSubmit(token) {
this.setState({
sending: true,
error: null
});
request.post(api('membership'), {
userInfo: getUserInfo(this.state),
stripeToken: token.id
})
.then(() => {
this.setState({ sending: false });
this.props.onPaymentSuccess();
})
.catch((err) => {
this.setState({ error: err, sending: false });
});
},
onChange(e) {
var name = e.target.name;
if (e.target.value === this.state[name]) {
return;
}
this.setState({
[e.target.name]: e.target.value,
pristineFields: this.state.pristineFields.filter((fieldName) => fieldName !== name),
errors: []
});
},
getDataErrors() {
var foundErrors = [];
fieldNames.forEach((fieldName) => {
if (!this.state[fieldName]) {
foundErrors.push({ field: fieldName, type: 'missing' });
}
});
if (this.state.email && !validateEmail(this.state.email)) {
foundErrors.push({ field: 'email', type: 'invalid' });
}
return foundErrors;
},
render() {
const inputErrors = this.getDataErrors();
var formClasses = classSet({
'form': true,
'membership-form': true,
'has-error': inputErrors.length !== 0 || this.state.error,
'sending': this.state.sending
});
function getErrorMessage(err) {
var feedbackText;
if (err.type === 'missing') {
feedbackText = `${fieldNameTranslations[err.field].fi} on pakollinen.`;
} else if (err.type === 'invalid') {
feedbackText = `${fieldNameTranslations[err.field].fi} on virheellinen.`;
}
return <div key={err.field} className='form--message'>{feedbackText}</div>;
}
/* generate error messages */
var visibleErrors = inputErrors
.filter((error) => this.state.pristineFields.indexOf(error.field) === -1);
var fieldsWithErrors = visibleErrors.map(({ field }) => field);
var inputFields = fieldNames.map((fieldName) => {
var inputClasses = classSet({
'input': true,
'has-error': _.includes(fieldsWithErrors, fieldName),
'half': fieldName === 'city' || fieldName === 'postcode',
'left': fieldName === 'city'
});
function showsErrorFor(field) {
if (fieldName === 'city') {
return false;
}
return field === fieldName || fieldName === 'postcode' && field === 'city';
}
return (
<span key={fieldName}>
<input
className={inputClasses}
type={fieldName === 'email' ? 'email' : 'text'}
name={fieldName}
placeholder={fieldNameTranslations[fieldName].fi}
value={this.state[fieldName]}
onChange={this.onChange} />
{
visibleErrors
.filter(({ field }) => showsErrorFor(field))
.map(getErrorMessage)
}
</span>
);
});
if (this.state.sending) {
return (
<div className='membership-form__loader'>
<Loader />
</div>
);
}
return (
<div>
<h3>Liity jäseneksi</h3>
<form className={formClasses}>
{inputFields}
{this.state.error && (
<div className='form--message'>
Jotain meni pieleen! Ota yhteyttä info@koodiklinikka.fi
</div>
)}
<br />
<StripeCheckout
amount={1000}
currency='EUR'
description='Jäsenmaksu'
email={this.state.email}
image='https://avatars3.githubusercontent.com/u/10520119?v=3&s=200'
locale='fi'
name='Koodiklinikka ry'
stripeKey={config.stripe.publicKey}
token={this.onSubmit}
>
<button
type='button'
disabled={inputErrors.length !== 0}
className='btn btn__submit'>
Siirry maksamaan
</button>
</StripeCheckout>
<p>
<small>Seuraava vuosimaksu veloitetaan automaattisesti <br />kortiltasi vuoden kuluttua.</small>
</p>
</form>
</div>
);
}
});

View File

@@ -3,31 +3,49 @@ require('./ga');
let ReactDOM = require('react-dom');
var React = require('react');
var inviteForm = React.createFactory(require('./components/inviteForm'));
var fader = React.createFactory(require('./components/fader'));
var members = React.createFactory(require('./components/members'));
var feed = React.createFactory(require('./components/feed'));
var email = React.createFactory(require('./components/email'));
var membershipForm = React.createFactory(require('./components/membershipForm'));
ReactDOM.render(
inviteForm(),
document.getElementById('invite-form'));
const pathName = window.location.pathname;
ReactDOM.render(
fader(),
document.getElementById('fader'));
document.querySelectorAll('.email').forEach((element) =>
ReactDOM.render(email(), element)
);
if (pathName == '/') {
ReactDOM.render(
inviteForm(),
document.getElementById('invite-form'));
ReactDOM.render(
members(),
document.getElementById('members'));
ReactDOM.render(
fader(),
document.getElementById('fader'));
ReactDOM.render(
members(),
document.getElementById('members'));
ReactDOM.render(
feed(),
document.getElementById('feed'));
ReactDOM.render(
feed(),
document.getElementById('feed'));
ReactDOM.render(
email(),
document.getElementById('email'));
} else if (pathName == '/yhdistys.html') {
ReactDOM.render(
membershipForm(),
document.getElementById('membership-form'));
ReactDOM.render(
fader(),
document.getElementById('fader'));
ReactDOM.render(
React.createElement('div', {}, [
members({ key: 0 }),
members({ key: 1 })
]),
document.getElementById('members'));
}

View File

@@ -1,8 +1,10 @@
headerHeight = 400px
.header
background url('../images/jumbo.jpg')
background-position bottom center
background-size cover
height 400px
height headerHeight
overflow hidden
position relative
width 100%
@@ -23,6 +25,43 @@
vertical-align middle
width 100%
.header__nav
position absolute
right 60px
top 32px
@media screen and (max-width: 1030px)
right 40px
top 20px
a
color white
font-size 16px
font-weight bold
margin-left 16px
text-shadow 0 2px 0 rgba(0,0,0,0.1)
position relative
@media screen and (max-width: 420px)
display block
margin-top 5px
&:last-child
margin-left 1.5em
&:before
content '!'
font-size 11px
line-height 15px
width 14px
height 14px
text-align center
background #ec3d3d
display inline-block
margin-right 5px
top -5px
right -15px
border-radius 100%
position absolute
text-shadow none
.header__headline
display table-cell
padding 0 1em
@@ -85,3 +124,59 @@
@media (min-aspect-ratio: 1/2)
width 100%
height auto
@keyframes spin
0%
top 0
50%
top -(headerHeight)
50.0001%
top headerHeight
100%
top 0
@keyframes spin2
0%
top (headerHeight)
50%
top 0
99.99999%
top -(headerHeight)
100%
top (headerHeight)
.header__members
width 100%
height 100%
z-index -1
position absolute
top 0
left 0
.member
margin 0
border-radius 0
width (100/18)%
@media screen and (min-width: 2000px)
width 5%
@media screen and (max-width: 1200px)
width (100/15)%
@media screen and (max-width: 810px)
width 10%
@media screen and (max-width: 450px)
width 20%
.members
position absolute
overflow hidden
top 0
left 0
right 0
height headerHeight
animation spin 40s infinite linear
&:first-child
z-index 1
&:last-child
animation spin2 40s infinite linear

View File

@@ -30,3 +30,8 @@
.input.has-error
border-color rgba(226, 33, 112, 0.6)
color rgb(226, 33, 112)
.input.half
width 48%
&.left
margin-right 4%

55
src/styles/_loader.styl Normal file
View File

@@ -0,0 +1,55 @@
.sk-folding-cube
margin auto
width 100%
height 100%
position relative
transform rotateZ(45deg)
.sk-folding-cube .sk-cube
float left
width 50%
height 50%
position relative
transform scale(1.1)
.sk-folding-cube .sk-cube:before
content ''
position absolute
top 0
left 0
width 100%
height 100%
background-color linkColor
animation sk-foldCubeAngle 2.4s infinite linear both
transform-origin 100% 100%
.sk-folding-cube .sk-cube2
transform scale(1.1) rotateZ(90deg)
.sk-folding-cube .sk-cube3
transform scale(1.1) rotateZ(180deg)
.sk-folding-cube .sk-cube4
transform scale(1.1) rotateZ(270deg)
.sk-folding-cube .sk-cube2:before
animation-delay 0.3s
.sk-folding-cube .sk-cube3:before
animation-delay 0.6s
.sk-folding-cube .sk-cube4:before
animation-delay 0.9s
@keyframes sk-foldCubeAngle
0%, 10%
transform perspective(140px) rotateX(-180deg)
opacity 0
25%, 75%
transform perspective(140px) rotateX(0deg)
opacity 1
90%, 100%
transform perspective(140px) rotateY(180deg)
opacity 0

View File

@@ -6,6 +6,7 @@ footerHeight = 50px
@require '_input'
@require '_button'
@require '_header'
@require '_loader'
body, html
margin 0
@@ -25,6 +26,9 @@ h1, h2, h3
h2
margin-bottom 1em
h3
font-size 1.25em
p
margin-top 1em
line-height 1.5em
@@ -51,13 +55,17 @@ section
.content
z-index 2
position relative
padding-right feedWidth
min-height 50vh
box-sizing border-box
@media screen and (max-width: 700px)
h3
margin-top 0
&.with-feed
padding-right feedWidth
section:first-child
box-shadow -1px -1px 1px rgba(0, 0, 0, 0.05)
border-bottom 1px solid #EEEEEE
@@ -104,35 +112,55 @@ section:first-child
padding 0
&:first-child
margin-top 0
.form
.btn
background linkColor
border-bottom 2px solid #117280
color rgba(255, 255, 255, 0.9)
&.sending
.btn
display none
.invite-form__loader
display block
.invite-form
position relative
.btn
width 40px
height 32px
background linkColor
padding 0
position absolute
right 8px
top 7px
border-bottom 2px solid #117280
color rgba(255, 255, 255, 0.5)
&:active
border-bottom 0
.loader
.invite-form__loader
display none
width 20px
height 20px
position absolute
right 9px
top 9px
width 0px
height 0px
background transparent url('../images/ajax-loader.gif') no-repeat center center
right 14px
top 14px
.membership-form
.input
margin 8px 0px
.btn
margin-top 12px
.membership-form__loader
width 70px
height 70px
margin auto
.stripe-form
margin 20px 0px
.name
margin-top 20px
text-align left
display block
&.sending
.btn
display none
.loader
width 28px
height 28px
color rgba(0, 0, 0, 0.4)
@keyframes drop
0%
@@ -146,7 +174,7 @@ section:first-child
100%
transform rotateX(0deg)
.invite-form--message
.form--message
background linkColor
color #fff
line-height 40px
@@ -156,8 +184,8 @@ section:first-child
transform-origin 100% 0
animation drop 0.6s linear
.invite-form.has-error
.invite-form--message
.form.has-error
.form--message
background rgb(226, 33, 112)
.members
@@ -182,7 +210,7 @@ footer
justify-content space-between
flex-wrap wrap
text-align center
@media screen and (max-width: 760px)
@media screen and (max-width: 940px)
display block
i
margin 0 0.30em
@@ -194,7 +222,7 @@ footer
display flex
flex-direction column
justify-content center
@media screen and (max-width: 760px)
@media screen and (max-width: 940px)
margin-top 1em
.sponsors
@@ -215,16 +243,17 @@ footer
height 40px
margin-right 1em
vertical-align middle
@media screen and (max-width: 760px)
@media screen and (max-width: 940px)
margin-top 1em
.sponsor__futurice, .sponsor__metosin, .sponsor__leonidas
height 30px
.sponsor__nordea
height 25px
margin-top: -3px
margin-top -3px
@media screen and (max-width: 940px)
margin-top 1em
.feed
width feedWidth
@@ -242,7 +271,7 @@ footer
@media screen and (max-width: 980px)
.feed
width 0
.content
.content.with-feed
padding-right 0
.message
@@ -314,3 +343,24 @@ footer
display block
.column
display block
.bread-img
background url('../images/hp3_bw.jpg')
background-size cover
border-radius 160px
opacity 0.85
width 320px
height 320px
margin auto
@media screen and (max-width: 700px)
.bread-img
display none
.organization
padding-top 3em
.membership-information.column
vertical-align initial
p:first-child
margin-top 37px

84
src/templates/head.jade Normal file
View File

@@ -0,0 +1,84 @@
doctype html
html
head
title
block title
// inject:css
// endinject
meta(name='description', content='Koodiklinikka on suomalainen Slack-yhteisö ohjelmistoalan harrastajille ja ammattilaisille.')
meta(name='keywords', content='ohjelmointi,frontend,open source,devaus,suomi,javascript,clojure,go,java,node.js,io.js,angular.js,web')
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
meta(name='apple-mobile-web-app-capable', content='yes')
script.
if(location.hostname === 'koodiklinikka.fi' && location.protocol !== 'https:') {
location.protocol = 'https';
}
link(rel='apple-touch-icon', sizes='57x57', href='icons/apple-touch-icon-57x57.png')
link(rel='apple-touch-icon', sizes='114x114', href='icons/apple-touch-icon-114x114.png')
link(rel='apple-touch-icon', sizes='72x72', href='icons/apple-touch-icon-72x72.png')
link(rel='apple-touch-icon', sizes='144x144', href='icons/apple-touch-icon-144x144.png')
link(rel='apple-touch-icon', sizes='60x60', href='icons/apple-touch-icon-60x60.png')
link(rel='apple-touch-icon', sizes='120x120', href='icons/apple-touch-icon-120x120.png')
link(rel='apple-touch-icon', sizes='76x76', href='icons/apple-touch-icon-76x76.png')
link(rel='apple-touch-icon', sizes='152x152', href='icons/apple-touch-icon-152x152.png')
link(rel='apple-touch-icon', sizes='180x180', href='icons/apple-touch-icon-180x180.png')
link(rel='icon', type='image/png', href='icons/favicon-192x192.png', sizes='192x192')
link(rel='icon', type='image/png', href='icons/favicon-160x160.png', sizes='160x160')
link(rel='icon', type='image/png', href='icons/favicon-96x96.png', sizes='96x96')
link(rel='icon', type='image/png', href='icons/favicon-16x16.png', sizes='16x16')
link(rel='icon', type='image/png', href='icons/favicon-32x32.png', sizes='32x32')
link(rel='shortcut icon', href='icons/favicon.ico')
link(rel='icon', href='icons/favicon.ico')
meta(name='msapplication-TileColor', content='#10558c')
meta(name='msapplication-TileImage', content='icons/mstile-144x144.png')
meta(property='og:image', content='images/logo.png')
script(src='https://js.stripe.com/v3/')
script(src='//use.typekit.net/scb5xny.js')
script.
try{Typekit.load();}catch(e){};
body
.site
.container
.header
block header_content
block content
footer
.sponsors
.sponsors__label Yhteistyössä
a(href='http://futurice.com/', target='_blank')
img.sponsor.sponsor__futurice(src='images/futurice.svg')
a(href='http://www.metosin.fi/', target='_blank')
img.sponsor.sponsor__metosin(src='images/metosin.svg')
a(href='https://www.solita.fi/', target='_blank')
img.sponsor(src='images/solita.svg')
a(href='http://leonidasoy.fi/', target='_blank')
img.sponsor.sponsor__leonidas(src='images/leonidas.png')
a(href='https://www.nordea.com/', target='_blank')
img.sponsor.sponsor__nordea(src='images/nordea.png')
.contacts
div
a(href='https://koodiklinikka.slack.com')
i.fa.fa-slack
a(href='https://github.com/koodiklinikka/koodiklinikka.fi')
i.fa.fa-github
a(href='https://twitter.com/koodiklinikka')
i.fa.fa-twitter
a(href='https://www.linkedin.com/groups/12025476')
i.fa.fa-linkedin
a(href='https://www.facebook.com/koodiklinikka')
i.fa.fa-facebook
div#email.email
#fader
// inject:js
// endinject

48
src/yhdistys.jade Normal file
View File

@@ -0,0 +1,48 @@
extends templates/head
block title
| Yhdistys
block header_content
.header__container
.header__nav
a(href='/') etusivu
a(href='/yhdistys.html') yhdistys
.header__headline
.header__logo
h1.header__title Koodiklinikka ry
.header__members
#members
block content
.content
section.organization
.row
.bread
.column.column1-2
h3 Rekisteröity yhdistys
p.
Koodiklinikka on nyt rekisteröity yhdistys!
p.
Lähes nelivuotisen taipaleensa aikana Koodiklinikka on kasvanut lähes tuhannen rekisteröityneen jäsenen yhteisöiksi ja näin saavuttanut aseman Suomen suurimpana ohjelmointiaiheisena yhteisönä! Liittymällä Koodiklinikka ry:n jäseneksi tuet toimintaamme, ja tulevaisuudessa yhdistyksen jäsenyys oikeuttaa etuihin Koodiklinikan tapahtumissa.
p.
Yhdistyksen jäsenyys <b>ei ole</b>, eikä tule olemaan, <b>pakollinen</b> Koodiklinikan käyttäjille tai meetuppeihin osallistujille.
.column.column1-2
.bread-img
.row
.bread
.column.column1-2
#membership-form.form
.column.column1-2.membership-information
p.
Kuka tahansa Slack:iin rekisteröitynyt käyttäjä voi liittyä yhdistyksen jäseneksi maksamalla <b>10€</b> vuosittaisen jäsenmaksun.
p.
Jäsenmaksulla tulemme tekemään tapahtumistamme vieläkin mielenkiintoisempia ja kattamaan kustannuksia jäsenmäärämme kasvaessa.
p.
Jos tarvitset Slack-kutsun, siirry <a target="_blank" href="/">etusivulle</a>.
p.
Jäsenrekisterin rekisteriseloste luettavissa <a target="_blank" href="https://docs.google.com/document/d/1w-NZkf1EFYMC8a4LsoZouhpMVKORmPi8UFWRhurr0oM/edit?usp=sharing">Google Drivessä</a>.
p.
Lisätietoa yhdistyksen jäsenyydestä tai vuosimaksusta emaililla <span class="email"></span>