[READ-ONLY] Mirror of https://github.com/probablykasper/lumix. Art website (unfinished)
art website
0

Configure Feed

Select the types of activity you want to include in your feed.

Lots of things. I should've commited earlier

KH (Mar 2, 2018, 8:10 PM +0100) c4b686c4 038b435c

+512 -82
+45
web/js/common.js
··· 1 + window.loopObject = (object, callback) => { 2 + let i = 0; 3 + for (let key in object) { 4 + // skip loop if the property is from prototype 5 + if (!object.hasOwnProperty(key)) continue; 6 + 7 + // callback(object, key); 8 + callback(key, i); 9 + i++; 10 + } 11 + } 12 + window.xhr = (reqContent, url, callback, options = {}) => { 13 + var xhr = new XMLHttpRequest(); 14 + if (options.type == undefined) options.type = "POST"; 15 + if (options.contentType == undefined) options.contentType = "json"; 16 + xhr.open(options.type, url, true); 17 + if (options.type == "GET") { 18 + xhr.send(); 19 + } else if (options.contentType == "values") { 20 + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 21 + xhr.send("data="+JSON.stringify(reqContent)); 22 + } else if (options.contentType == "json") { 23 + xhr.setRequestHeader("Content-type", "application/json"); 24 + xhr.send(JSON.stringify(reqContent)); 25 + } 26 + // else if (options.contentType == "multipart") { 27 + // // xhr.setRequestHeader("Content-type", "multipart/form-data"); 28 + // } 29 + xhr.onreadystatechange = function() { 30 + if (this.readyState == 4) { 31 + let res = JSON.parse(this.responseText); 32 + let err = null; 33 + if (!String(this.status).startsWith("2")) { 34 + console.error("HTTP error "+this.status); 35 + err = this.status; 36 + } 37 + callback(res, err); 38 + } 39 + }; 40 + } 41 + 42 + // self-invoking function replacement (looks cleaner imo) 43 + window.fold = (description, callback) => { 44 + callback(); 45 + }
+18
web/js/forms.js
··· 1 + // register form 2 + if (page == "register") { 3 + $("button.register").on("click", () => { 4 + const req = { 5 + displayname: $(".register-form input.displayname").val(), 6 + username: $(".register-form input.username").val(), 7 + email: $(".register-form input.email").val(), 8 + password: $(".register-form input.password").val(), 9 + } 10 + // const req = 11 + // `email=${email}`+ 12 + // `&password=${password}` 13 + xhr(req, "/register", (res, err) => { 14 + if (err); // http status code not 2xx 15 + console.log(res); 16 + }); 17 + }); 18 + }
+2
web/js/global.js
··· 1 1 $(document).ready(() => { 2 2 3 + require("./common"); 3 4 require("./ui"); 5 + require("./forms"); 4 6 if (loggedIn) { 5 7 6 8 }
+13
web/js/ui.js
··· 20 20 }); 21 21 22 22 } 23 + 24 + // function fullPageElement(element) { 25 + // const headerHeight = $(".site-header").height(); 26 + // let windowHeight = $(window).height(); 27 + // element.height(windowHeight - headerHeight); 28 + // $(window).on("resize", () => { 29 + // windowHeight = $(window).height(); 30 + // element.height(windowHeight - headerHeight); 31 + // }); 32 + // } 33 + // if (page == "home") fullPageElement($(".center-container")); 34 + // if (page == "login") fullPageElement($(".form-container")); 35 + // if (page == "register") fullPageElement($(".form-container"));
+4 -3
web/node/mongoose-models.js
··· 11 11 }, { typeKey: "$Type"}); 12 12 13 13 const userSchema = new Schema({ 14 - displayName: String, 15 - googleId: String, 16 - profilePictureURL: String, 14 + displayname: String, 15 + username: String, 16 + email: String, 17 + password: String, 17 18 // images: [imageSchema], 18 19 }, { typeKey: "$Type" }); 19 20
+61 -20
web/node/passport-setup.js
··· 1 1 const passport = require("passport"); 2 - const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; 2 + // const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy; 3 + const LocalStrategy = require("passport-local").Strategy; 3 4 const keys = require("./keys"); 4 5 const User = require("./mongoose-models").User; 5 6 ··· 13 14 }); 14 15 }); 15 16 16 - passport.use(new GoogleStrategy({ 17 - clientID: keys.google.clientID, 18 - clientSecret: keys.google.clientSecret, 19 - callbackURL: "/auth/google/callback" 20 - }, (accessToken, refreshToken, profile, done) => { 21 - User.findOne({googleId: profile.id}).then((resultUser) => { 22 - if (resultUser) { 23 - // user alreaady exists 24 - console.log(`login: ${resultUser.googleId} ${resultUser.displayName}`); 17 + passport.use(new LocalStrategy({ 18 + usernameField: "username", 19 + passwordField: "password", 20 + }, (username, password, done) => { 21 + User.findOne({ username: username }, function(err, resultUser) { 22 + if (err) { 23 + done(err); 24 + } else if (!resultUser) { 25 + done(null, false, { 26 + message: "Incorrect username." 27 + }); 28 + } else if (!resultUser.validPassword(password)) { 29 + done(null, false, { 30 + message: "Incorrect password." 31 + }); 32 + } else { 25 33 done(null, resultUser); 26 - } else { 27 - // new user 28 - new User({ 29 - displayName: profile.displayName, 30 - googleId: profile.id, 31 - profilePictureURL: profile.photos[0].value 32 - }).save().then((newUser) => { 33 - console.log(`newlogin: ${newUser.googleId} ${newUser.displayName}`); 34 - done(null, newUser); 35 - }); 36 34 } 37 35 }); 38 36 })); 37 + 38 + // passport.use(new GoogleStrategy({ 39 + // clientID: keys.google.clientID, 40 + // clientSecret: keys.google.clientSecret, 41 + // callbackURL: "/auth/google/callback" 42 + // }, (accessToken, refreshToken, profile, done) => { 43 + // User.findOne({googleId: profile.id}).then((resultUser) => { 44 + // if (resultUser) { 45 + // // user alreaady exists 46 + // // console.log(`login: ${resultUser.googleId} ${resultUser.displayName}`); 47 + // done(null, resultUser); 48 + // } else { 49 + // // new user 50 + // new User({ 51 + // displayName: profile.displayName, 52 + // googleId: profile.id, 53 + // profilePictureURL: profile.photos[0].value 54 + // }).save().then((newUser) => { 55 + // // console.log(`newlogin: ${newUser.googleId} ${newUser.displayName}`); 56 + // done(null, newUser); 57 + // }); 58 + // } 59 + // }); 60 + // })); 61 + 62 + 63 + const session = require("express-session"); 64 + const MongoStore = require("connect-mongo")(session); 65 + 66 + module.exports = (app, mongoose) => { 67 + app.use(session({ 68 + secret: keys.passportSessionStoreSecret, 69 + store: new MongoStore({ 70 + mongooseConnection: mongoose.connection, 71 + ttl: 60*60*24*90, 72 + touchAfter: 60*60*24 73 + }), 74 + resave: false, 75 + saveUninitialized: false 76 + })); 77 + app.use(passport.initialize()); 78 + app.use(passport.session()); 79 + }
+76 -4
web/node/routes.js
··· 1 1 "use strict"; 2 2 const passport = require("passport"); 3 + const validator = require("validator"); 4 + const User = require("./mongoose-models").User; 5 + const bcrypt = require("bcryptjs"); 3 6 4 7 function render(app, res, pugFile, variables, callback) { 5 8 app.render(pugFile, variables, (err, html) => { ··· 86 89 }); 87 90 } 88 91 89 - const scope = {scope: ["profile"]}; 90 - app.get("/login", passport.authenticate("google", scope)); 92 + // app.post("/login", passport.authenticate("local", { 93 + // successRedirect: "/", 94 + // failureRedirect: "/login", 95 + // failureFlash: false 96 + // })); 97 + 98 + app.post("/register", (req, res) => { 99 + let displayname = req.body.displayname 100 + let username = req.body.username 101 + let email = req.body.email 102 + let password = req.body.password 103 + let errors = []; 104 + 105 + if (validator.isEmpty(displayname)) errors.push("displayname empty"); 106 + else if (!validator.isLength(displayname, {max: 30})) errors.push("displayname length"); 107 + 108 + const usernameRegex = new RegExp(/^[a-zA-Z0-9]+$/g); 109 + if (validator.isEmpty(username)) errors.push("username empty"); 110 + else if (!username.match(usernameRegex)) errors.push("username chars"); 111 + else if (!validator.isLength(username, {max: 30})) errors.push("username length"); 112 + 113 + if (validator.isEmpty(password)) errors.push("password empty"); 114 + else if (!validator.isLength(password, {min: 6, max: 100})) errors.push("password length"); 91 115 92 - app.get("/auth/google/callback", passport.authenticate("google"), (req, res) => { 93 - res.redirect("/"); 116 + if (validator.isEmpty(email)) errors.push("email empty"); 117 + else if (!validator.isEmail(email)) errors.push("email invalid"); 118 + else if (!validator.isLength(email, {max: 60})) errors.push("email length"); 119 + 120 + if (errors.length == 0) { 121 + User.findOne({email: email}, (err, resultUser) => { 122 + if (err) errors.push("unknown"); 123 + if (resultUser) errors.push("email exists"); 124 + User.findOne({username: username}, (err, resultUser) => { 125 + if (err) errors.push("unknown"); 126 + if (resultUser) errors.push("username exists"); 127 + if (errors.length == 0) { 128 + bcrypt.genSalt(10, (err, salt) => { 129 + if (err) errors.push("unknown"); 130 + bcrypt.hash(password, salt, (err, hashedPassword) => { 131 + if (err) errors.push("unknown"); 132 + new User({ 133 + displayname: displayname, 134 + username: username, 135 + email: email, 136 + password: password, 137 + }).save((err) => { 138 + if (err) errors.push("unknown"); 139 + if (errors.length == 0) { 140 + console.log("success"); 141 + res.json({ 142 + errors: null, 143 + }); 144 + } else { 145 + res.json({ 146 + errors: errors, 147 + }); 148 + } 149 + }); 150 + }); 151 + }); 152 + } else { 153 + res.json({ 154 + errors: errors, 155 + }); 156 + } 157 + }); 158 + }); 159 + } else { 160 + res.json({ 161 + errors: errors, 162 + }); 163 + } 94 164 }); 95 165 96 166 app.get("/logout", (req, res) => { ··· 98 168 res.redirect("/"); 99 169 }); 100 170 171 + get("/login", "login"); 172 + get("/register", "register"); 101 173 get("/", "home"); 102 174 103 175 // get("/balance", "balance");
+3 -1
web/package.json
··· 30 30 "body-parser": "1.18.x", 31 31 32 32 "passport": "0.4.x", 33 - "passport-google-oauth": "1.0.x", 33 + "passport-local": "1.0.x", 34 34 "express-session": "1.15.x", 35 35 "connect-mongo": "2.0.x", 36 + "validator": "9.4.x", 37 + "bcryptjs": "2.4.x", 36 38 37 39 "mongoose": "5.0.x" 38 40 }
+2
web/pug/logged-out/home.pug
··· 1 1 .center-container 2 2 p.center-logo Lumix 3 3 p.tagline The place you put your art 4 + .stuff 5 + p Should probably say something nice about the site right here...
+7
web/pug/logged-out/login.pug
··· 1 + .form-container.login-form 2 + .form 3 + label(for="email") Email 4 + input.form-field.email(type="text", name="email" id="email") 5 + label(for="password") Password 6 + input.form-field.password(type="password", name="password" id="password") 7 + button.button.login(tabIndex="0") Login
+28
web/pug/logged-out/register.pug
··· 1 + //- form(action="/login", method="post") 2 + //- div 3 + //- label Email: 4 + //- input(type="text", name="username") 5 + //- div 6 + //- label Username: 7 + //- input(type="text", name="username") 8 + //- div 9 + //- label Password: 10 + //- input(type="password", name="password") 11 + //- div 12 + //- label Repeat Password: 13 + //- input(type="password", name="password") 14 + //- div 15 + //- input(type="submit", value="Register") 16 + 17 + 18 + .form-container.register-form 19 + .form 20 + label(for="displayname") Displayname 21 + input.form-field.displayname(type="text", name="displayname" id="displayname") 22 + label(for="username") Username 23 + input.form-field.username(type="text", name="username" id="username") 24 + label(for="email") Email 25 + input.form-field.email(type="text", name="email" id="email") 26 + label(for="password") Password 27 + input.form-field.password(type="password", name="password" id="password") 28 + button.button.register(tabIndex="0") Register
+8 -1
web/pug/template.pug
··· 13 13 input(placeholder="Search").search 14 14 .right-side-header 15 15 if !loggedIn 16 - a(href="/login").menu-bar-item Login 16 + a.button.menu-bar-item(href="/register") Register 17 + a.button.menu-bar-item(href="/login") Login 17 18 if loggedIn 18 19 .account-icon-container 19 20 img.account-icon(src=profilePictureURL) 20 21 .account-box 21 22 .spacer 23 + a.account-box-item.settings(href="/profile/"+displayName) 24 + <svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> 25 + <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/> 26 + <path d="M0 0h24v24H0z" fill="none"/> 27 + </svg> 28 + .item-text.settings My profile 22 29 a.account-box-item.settings(href="/settings") 23 30 <svg fill="#3F3F3F" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> 24 31 <path d="M0 0h24v24H0z" fill="none"/>
+51
web/sass/buttons.sass
··· 1 + .button 2 + padding: 12px 8px 3 + position: relative 4 + &:hover::before 5 + width: 50% 6 + &:focus::before 7 + width: 80% 8 + transform: translate(-50%, -2px) 9 + &::before 10 + content: "" 11 + position: absolute 12 + transition: $transition-20 all 13 + background-color: $gray-line 14 + bottom: 0px 15 + transform: translate(-50%, 0px) 16 + left: 50% 17 + height: 2px 18 + width: 0% 19 + border-radius: 5px 20 + 21 + 22 + // .button 23 + // padding: 14px 30px 24 + // position: relative 25 + // background-color: transparent 26 + // &:hover 27 + // &::before 28 + // height: 70% 29 + // &::after 30 + // height: 70% 31 + // &:focus 32 + // &::before 33 + // height: 90% 34 + // transform: translate(4px, -50%) 35 + // &::after 36 + // height: 90% 37 + // transform: translate(-4px, -50%) 38 + // &::before, &::after 39 + // content: "" 40 + // position: absolute 41 + // background-color: $gray-line 42 + // transition: $transition-20 all 43 + // top: 50% 44 + // transform: translate(0px, -50%) 45 + // width: 2px 46 + // height: 50% 47 + // border-radius: 5px 48 + // &::before 49 + // left: 0px 50 + // &::after 51 + // right: 0px
+18 -22
web/sass/defaults.sass
··· 1 1 table 2 2 border-collapse: collapse 3 3 border-spacing: 0 4 - * 5 - color: $black 6 - font: inherit 7 - margin: 0 8 - padding: 0 9 - border: 0 10 - font-size: 16px 11 - vertical-align: baseline 12 - outline: none 13 4 h1 14 5 font-size: 48px 15 6 h2 ··· 18 9 font-size: 28px 19 10 h4 20 11 font-size: 22px 21 - // body, div, span, applet, object, iframe, 22 - // h1, h2, h3, h4, h5, h6, p, blockquote, pre, 23 - // a, abbr, acronym, address, big, cite, code, 24 - // del, dfn, em, img, ins, kbd, q, s, samp, 25 - // small, strike, strong, sub, sup, tt, var, 26 - // b, u, i, center, 27 - // dl, dt, dd, ol, ul, li, 28 - // fieldset, form, label, legend, 29 - // table, caption, tbody, tfoot, thead, tr, th, td, 30 - // article, aside, canvas, details, embed, 31 - // figure, figcaption, footer, header, hgroup, 32 - // menu, nav, output, ruby, section, summary, 33 - // time, mark, audio, video 12 + body, div, img, ol, ul, li, 13 + span, h1, h2, h3, h4, h5, h6, p, a, 14 + form, label, legend, fieldset, 15 + table, tbody, tfoot, thead, tr, th, td, 16 + aside, canvas, footer, header, menu, nav, 17 + section, audio, video, input, button 18 + color: $black 19 + font: inherit 20 + margin: 0 21 + padding: 0 22 + border: 0 23 + font-size: inherit 24 + vertical-align: baseline 25 + outline: none 34 26 img 35 27 display: block 36 28 ··· 57 49 q:before, q:after 58 50 content: '' 59 51 content: none 52 + button 53 + cursor: pointer 54 + label 55 + cursor: text
+21
web/sass/forms.sass
··· 1 + .form-container 2 + position: absolute 3 + height: calc(100% - #{$header-height}) 4 + width: 100% 5 + top: 70px 6 + 7 + display: flex 8 + align-items: center 9 + justify-content: center 10 + flex-direction: column 11 + font-size: 15px 12 + .form 13 + input.form-field 14 + padding: 10px 14px 15 + margin-top: 5px 16 + margin-bottom: 15px 17 + border-radius: 5px 18 + width: 250px 19 + background-color: $white-dark 20 + &.login-form 21 + &.register-form
+2
web/sass/global.sass
··· 7 7 html 8 8 9 9 @import "home.sass" 10 + @import "buttons.sass" 11 + @import "forms.sass" 10 12 // @import "buttons.sass" 11 13 // @import "cards.sass"
+8 -4
web/sass/home.sass
··· 1 1 .center-container 2 2 position: absolute 3 + height: calc(100% - #{$header-height}) 3 4 width: 100% 4 - height: 100% 5 - min-height: 400px 6 - left: 0px 7 - top: 0px 5 + top: 70px 8 6 7 + min-height: 200px 9 8 display: flex 10 9 justify-content: center 11 10 align-items: center ··· 14 13 font-size: 128px 15 14 p.tagline 16 15 font-size: 16px 16 + .stuff 17 + height: 900px 18 + width: 200px 19 + margin: auto 20 + background-color: #FFA65C
+26 -4
web/sass/template.sass
··· 4 4 background-color: $white 5 5 display: grid 6 6 main.page-container 7 - margin: 30px 7 + // margin: 30px 8 8 9 9 header.site-header 10 + font-size: 16px 10 11 z-index: 5 11 12 height: $header-height 12 13 display: flex ··· 24 25 font-size: 38px 25 26 padding: 8px 26 27 input.search 28 + font-size: 15px 27 29 padding: 10px 14px 28 30 border-radius: 5px 29 31 width: 250px ··· 32 34 display: flex 33 35 align-items: center 34 36 justify-content: flex-end 37 + a.menu-bar-item 38 + padding: 12px 8px 39 + position: relative 40 + &:hover::before 41 + width: 50% 42 + &:focus::before 43 + width: 80% 44 + transform: translate(-50%, -2px) 45 + &::before 46 + content: "" 47 + position: absolute 48 + transition: $transition-20 all 49 + background-color: $gray-line 50 + bottom: 0px 51 + transform: translate(-50%, 0px) 52 + left: 50% 53 + height: 2px 54 + width: 0% 55 + border-radius: 5px 35 56 .account-icon-container 36 57 max-height: 100% 37 58 position: relative ··· 53 74 transform-origin: right top 54 75 transition: $transition-20-out all 55 76 &.visible 56 - height: 120px 77 + height: calc(10px + 50px*3 + 10px) 57 78 width: 200px 58 79 pointer-events: all 59 80 transition: $transition-30-in all ··· 67 88 flex-grow: 1 68 89 cursor: pointer 69 90 .item-text 70 - margin-left: 4px 91 + margin-left: 8px 71 92 font-size: 15px 72 93 color: $black 73 94 &:hover 74 - background-color: #F2F2F2 95 + // background-color: #F2F2F2 96 + background-color: $white-dark
+2 -4
web/sass/variables.sass
··· 1 1 $header-height: 70px 2 2 $white: #FFFFFF 3 - $white-dark: #F9F9F9 3 + $white-dark: #F3F3F3 4 + $gray-line: #717171 4 5 $black: #3F3F3F 5 6 $tooltip-bg: #3c4554 6 7 ··· 34 35 35 36 $transition-10: .10s cubic-bezier(0.4, 0.0, 0.2, 1.0) 36 37 $transition-10-in: .10s cubic-bezier(0.0, 0.0, 0.2, 1.0) 37 - $transition-10-in: .10s cubic-bezier(0.0, 0.0, 0.2, 1.0) 38 38 $transition-10-out: .10s cubic-bezier(0.4, 0.0, 1.0, 1.0) 39 39 40 40 $transition-20: .20s cubic-bezier(0.4, 0.0, 0.2, 1.0) 41 - $transition-20-in: .20s cubic-bezier(0.0, 0.0, 0.2, 1.0) 42 41 $transition-20-in: .20s cubic-bezier(0.0, 0.0, 0.2, 1.0) 43 42 $transition-20-out: .20s cubic-bezier(0.4, 0.0, 1.0, 1.0) 44 43 45 44 $transition-30: .30s cubic-bezier(0.4, 0.0, 0.2, 1.0) 46 - $transition-30-in: .30s cubic-bezier(0.0, 0.0, 0.2, 1.0) 47 45 $transition-30-in: .30s cubic-bezier(0.0, 0.0, 0.2, 1.0) 48 46 $transition-30-out: .30s cubic-bezier(0.4, 0.0, 1.0, 1.0)
+20 -18
web/server.js
··· 42 42 43 43 // mongoose 44 44 const mongoose = require("mongoose"); 45 - mongoose.connect("mongodb://db/cryp"); 45 + mongoose.connect("mongodb://db/lumix"); 46 46 const db = mongoose.connection; 47 47 const dbSuc = "\x1b[42m[Mongoose]\x1b[0m "; 48 48 db.on("error", console.error.bind(console, "connection error:")); ··· 51 51 }); 52 52 53 53 // passport 54 - const passport = require("passport"); 55 - const passportSetup = require("./node/passport-setup"); 56 - const session = require("express-session"); 57 - const MongoStore = require("connect-mongo")(session); 58 - app.use(session({ 59 - // key: "sess", 60 - secret: "tomatonanaboy69:o", 61 - store: new MongoStore({ 62 - mongooseConnection: mongoose.connection, 63 - ttl: 60*60*24*90, 64 - touchAfter: 60*60*24 65 - }), 66 - resave: false, 67 - saveUninitialized: false 68 - })); 69 - app.use(passport.initialize()); 70 - app.use(passport.session()); 54 + require("./node/passport-setup.js")(app, mongoose); 55 + 56 + // const passport = require("passport"); 57 + // const passportSetup = require("./node/passport-setup"); 58 + // const session = require("express-session"); 59 + // const MongoStore = require("connect-mongo")(session); 60 + // app.use(session({ 61 + // // key: "sess", 62 + // secret: "tomatonanaboy69:o", 63 + // store: new MongoStore({ 64 + // mongooseConnection: mongoose.connection, 65 + // ttl: 60*60*24*90, 66 + // touchAfter: 60*60*24 67 + // }), 68 + // resave: false, 69 + // saveUninitialized: false 70 + // })); 71 + // app.use(passport.initialize()); 72 + // app.use(passport.session()); 71 73 72 74 // routes 73 75 require("./node/routes")(app);
+1 -1
web/static/global.css
··· 1 - table{border-collapse:collapse;border-spacing:0}*{color:#3f3f3f;font:inherit;margin:0;padding:0;border:0;font-size:16px;vertical-align:baseline;outline:none}h1{font-size:48px}h2{font-size:38px}h3{font-size:28px}h4{font-size:22px}img{display:block}a:active,a:hover,a:link,a:visited{color:inherit;text-decoration:none}article,aside,details,figcaption,figure,footer,header,hgroup,input,menu,nav,section,textarea{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}html{font-family:Rubik,sans-serif}body{background-color:#fff;display:grid}main.page-container{margin:30px}header.site-header{z-index:5;height:70px;display:flex;align-items:center;justify-content:space-between;padding:0 20px;color:#3f3f3f}header.site-header .left-side-header,header.site-header .right-side-header{width:200px;padding:0 8px}header.site-header .left-side-header{display:flex;align-items:center}header.site-header .left-side-header a.header-logo{font-size:38px;padding:8px}header.site-header input.search{padding:10px 14px;border-radius:5px;width:250px;background-color:#f9f9f9}header.site-header .right-side-header{display:flex;align-items:center;justify-content:flex-end}header.site-header .right-side-header .account-icon-container{max-height:100%;position:relative}header.site-header .right-side-header .account-icon-container img.account-icon{margin:10px 0;cursor:pointer}header.site-header .right-side-header .account-icon-container .account-box{z-index:10;background-color:#fff;box-shadow:0 4px 8px 0 rgba(0,0,0,.24);position:absolute;right:0;top:calc(100% - 8px);overflow:hidden;height:0;width:100px;pointer-events:none;transform-origin:right top;transition:all .2s cubic-bezier(.4,0,1,1)}header.site-header .right-side-header .account-icon-container .account-box.visible{height:120px;width:200px;pointer-events:all;transition:all .3s cubic-bezier(0,0,.2,1)}header.site-header .right-side-header .account-icon-container .account-box .spacer{height:10px}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item{height:50px;display:flex;align-items:center;padding:0 18px;flex-grow:1;cursor:pointer}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item .item-text{margin-left:4px;font-size:15px;color:#3f3f3f}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item:hover{background-color:#f2f2f2}html .center-container{position:absolute;width:100%;height:100%;min-height:400px;left:0;top:0;display:flex;justify-content:center;align-items:center;flex-direction:column}html .center-container p.center-logo{font-size:128px}html .center-container p.tagline{font-size:16px} 1 + table{border-collapse:collapse;border-spacing:0}h1{font-size:48px}h2{font-size:38px}h3{font-size:28px}h4{font-size:22px}a,aside,audio,body,button,canvas,div,fieldset,footer,form,h1,h2,h3,h4,h5,h6,header,img,input,label,legend,li,menu,nav,ol,p,section,span,table,tbody,td,tfoot,th,thead,tr,ul,video{color:#3f3f3f;font:inherit;margin:0;padding:0;border:0;font-size:inherit;vertical-align:baseline;outline:none}img{display:block}a:active,a:hover,a:link,a:visited{color:inherit;text-decoration:none}article,aside,details,figcaption,figure,footer,header,hgroup,input,menu,nav,section,textarea{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}button{cursor:pointer}label{cursor:text}html{font-family:Rubik,sans-serif}body{background-color:#fff;display:grid}header.site-header{font-size:16px;z-index:5;height:70px;display:flex;align-items:center;justify-content:space-between;padding:0 20px;color:#3f3f3f}header.site-header .left-side-header,header.site-header .right-side-header{width:200px;padding:0 8px}header.site-header .left-side-header{display:flex;align-items:center}header.site-header .left-side-header a.header-logo{font-size:38px;padding:8px}header.site-header input.search{font-size:15px;padding:10px 14px;border-radius:5px;width:250px;background-color:#f3f3f3}header.site-header .right-side-header{display:flex;align-items:center;justify-content:flex-end}header.site-header .right-side-header a.menu-bar-item{padding:12px 8px;position:relative}header.site-header .right-side-header a.menu-bar-item:hover:before{width:50%}header.site-header .right-side-header a.menu-bar-item:focus:before{width:80%;transform:translate(-50%,-2px)}header.site-header .right-side-header a.menu-bar-item:before{content:"";position:absolute;transition:all .2s cubic-bezier(.4,0,.2,1);background-color:#717171;bottom:0;transform:translate(-50%);left:50%;height:2px;width:0;border-radius:5px}header.site-header .right-side-header .account-icon-container{max-height:100%;position:relative}header.site-header .right-side-header .account-icon-container img.account-icon{margin:10px 0;cursor:pointer}header.site-header .right-side-header .account-icon-container .account-box{z-index:10;background-color:#fff;box-shadow:0 4px 8px 0 rgba(0,0,0,.24);position:absolute;right:0;top:calc(100% - 8px);overflow:hidden;height:0;width:100px;pointer-events:none;transform-origin:right top;transition:all .2s cubic-bezier(.4,0,1,1)}header.site-header .right-side-header .account-icon-container .account-box.visible{height:170px;width:200px;pointer-events:all;transition:all .3s cubic-bezier(0,0,.2,1)}header.site-header .right-side-header .account-icon-container .account-box .spacer{height:10px}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item{height:50px;display:flex;align-items:center;padding:0 18px;flex-grow:1;cursor:pointer}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item .item-text{margin-left:8px;font-size:15px;color:#3f3f3f}header.site-header .right-side-header .account-icon-container .account-box a.account-box-item:hover{background-color:#f3f3f3}html .center-container{position:absolute;height:calc(100% - 70px);width:100%;top:70px;min-height:200px;display:flex;justify-content:center;align-items:center;flex-direction:column}html .center-container p.center-logo{font-size:128px}html .center-container p.tagline{font-size:16px}html .stuff{height:900px;width:200px;margin:auto;background-color:#ffa65c}html .button{padding:12px 8px;position:relative}html .button:hover:before{width:50%}html .button:focus:before{width:80%;transform:translate(-50%,-2px)}html .button:before{content:"";position:absolute;transition:all .2s cubic-bezier(.4,0,.2,1);background-color:#717171;bottom:0;transform:translate(-50%);left:50%;height:2px;width:0;border-radius:5px}html .form-container{position:absolute;height:calc(100% - 70px);width:100%;top:70px;display:flex;align-items:center;justify-content:center;flex-direction:column;font-size:15px}html .form-container .form input.form-field{padding:10px 14px;margin-top:5px;margin-bottom:15px;border-radius:5px;width:250px;background-color:#f3f3f3}
+96
web/static/global.js
··· 73 73 $(document).ready(function () { 74 74 75 75 __webpack_require__(1); 76 + __webpack_require__(2); 77 + __webpack_require__(3); 76 78 if (loggedIn) {} 77 79 }); 78 80 ··· 83 85 "use strict"; 84 86 85 87 88 + window.loopObject = function (object, callback) { 89 + var i = 0; 90 + for (var key in object) { 91 + // skip loop if the property is from prototype 92 + if (!object.hasOwnProperty(key)) continue; 93 + 94 + // callback(object, key); 95 + callback(key, i); 96 + i++; 97 + } 98 + }; 99 + 100 + window.xhr = function (reqContent, url, callback) { 101 + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; 102 + 103 + var xhr = new XMLHttpRequest(); 104 + if (options.type == undefined) options.type = "POST"; 105 + if (options.contentType == undefined) options.contentType = "json"; 106 + xhr.open(options.type, url, true); 107 + if (options.type == "GET") { 108 + xhr.send(); 109 + } else if (options.contentType == "values") { 110 + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 111 + xhr.send("data=" + JSON.stringify(reqContent)); 112 + } else if (options.contentType == "json") { 113 + xhr.setRequestHeader("Content-type", "application/json"); 114 + xhr.send(JSON.stringify(reqContent)); 115 + } 116 + // else if (options.contentType == "multipart") { 117 + // // xhr.setRequestHeader("Content-type", "multipart/form-data"); 118 + // } 119 + xhr.onreadystatechange = function () { 120 + if (this.readyState == 4) { 121 + var res = JSON.parse(this.responseText); 122 + var err = null; 123 + if (!String(this.status).startsWith("2")) { 124 + console.error("HTTP error " + this.status); 125 + err = this.status; 126 + } 127 + callback(res, err); 128 + } 129 + }; 130 + }; 131 + 132 + // self-invoking function replacement (looks cleaner imo) 133 + window.fold = function (description, callback) { 134 + callback(); 135 + }; 136 + 137 + /***/ }), 138 + /* 2 */ 139 + /***/ (function(module, exports, __webpack_require__) { 140 + 141 + "use strict"; 142 + 143 + 86 144 // search, press enter 87 145 var searchField = $(".search")[0]; 88 146 $(".search").keypress(function (e) { ··· 102 160 if (!$(e.target).parents(".account-icon-container").length) { 103 161 $(".account-box").removeClass("visible"); 104 162 } 163 + }); 164 + } 165 + 166 + // function fullPageElement(element) { 167 + // const headerHeight = $(".site-header").height(); 168 + // let windowHeight = $(window).height(); 169 + // element.height(windowHeight - headerHeight); 170 + // $(window).on("resize", () => { 171 + // windowHeight = $(window).height(); 172 + // element.height(windowHeight - headerHeight); 173 + // }); 174 + // } 175 + // if (page == "home") fullPageElement($(".center-container")); 176 + // if (page == "login") fullPageElement($(".form-container")); 177 + // if (page == "register") fullPageElement($(".form-container")); 178 + 179 + /***/ }), 180 + /* 3 */ 181 + /***/ (function(module, exports, __webpack_require__) { 182 + 183 + "use strict"; 184 + 185 + 186 + // register form 187 + if (page == "register") { 188 + $("button.register").on("click", function () { 189 + var req = { 190 + displayname: $(".register-form input.displayname").val(), 191 + username: $(".register-form input.username").val(), 192 + email: $(".register-form input.email").val(), 193 + password: $(".register-form input.password").val() 194 + // const req = 195 + // `email=${email}`+ 196 + // `&password=${password}` 197 + };xhr(req, "/register", function (res, err) { 198 + if (err) ; // http status code not 2xx 199 + console.log(res); 200 + }); 105 201 }); 106 202 } 107 203