[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.

Finished how images look on profile, settings page start

KH (Mar 13, 2018, 9:55 PM +0100) 2569d861 7911f737

+632 -81
+152 -1
web/js/forms.js
··· 112 112 hide(); 113 113 }); 114 114 $(window).on("dragleave", (e) => { 115 - console.log(e); 116 115 e = e.originalEvent; 117 116 if (e.relatedTarget == null || $(e.target).hasClass("upload-form")) { 118 117 hide(); ··· 221 220 }); 222 221 223 222 }); 223 + 224 + fold("settings form", () => { 225 + 226 + fold("file select", () => { 227 + 228 + // click "select file" button opens file select dialog 229 + $("body").on("click", ".settings-form button.files", () => { 230 + $(".settings-form input#files").click(); 231 + }); 232 + 233 + function containsAFile(e) { 234 + if (e.originalEvent) e = e.originalEvent; 235 + const dtTypes = e.dataTransfer.types; 236 + if (dtTypes.length == 1 && dtTypes[0] == "Files") { 237 + return true; 238 + } 239 + return false; 240 + } 241 + 242 + // setup 243 + const setupEvents = "drag dragstart dragend dragover dragenter dragleave drop"; 244 + $(window).on(setupEvents, (e) => { 245 + if ($(e.target).inOrIs(".upload-avatar-container")) { 246 + e.preventDefault(); 247 + e.stopPropagation(); 248 + } 249 + }); 250 + function show() { 251 + $(".settings-form .drop-to-select-file").removeClass("hidden"); 252 + $(".settings-form .select-file").addClass("hidden"); 253 + } 254 + function hide() { 255 + $(".settings-form .drop-to-select-file").addClass("hidden"); 256 + $(".settings-form .select-file").removeClass("hidden"); 257 + } 258 + // show 259 + $(window).on("dragenter", (e) => { 260 + if ($(e.target).inOrIs(".upload-avatar-container")) { 261 + if (containsAFile(e)) show(); 262 + } 263 + }); 264 + // hide 265 + $(window).on("dragend", (e) => { 266 + hide(); 267 + }); 268 + $(window).on("dragleave", (e) => { 269 + e = e.originalEvent; 270 + if (e.relatedTarget == null || $(e.target).hasClass("upload-avatar-container")) { 271 + hide(); 272 + } 273 + }); 274 + // drop 275 + $(window).on("drop", (e) => { 276 + hide(); 277 + if (containsAFile(e)) { 278 + const files = e.originalEvent.dataTransfer.files; 279 + if (files[0].type == "image/png" || files[0].type == "image/jpeg") { 280 + handleFiles(files); 281 + } else { // wrong fileExt 282 + 283 + } 284 + } 285 + }); 286 + 287 + $("body").on("change", ".settings-form input#files", function(e) { 288 + const input = $(this); 289 + const files = input.prop("files"); 290 + handleFiles(files); 291 + }); 292 + 293 + // handle files 294 + function handleFiles(files) { 295 + window.uploadData = files; 296 + 297 + const reader = new FileReader(); 298 + reader.onload = (e) => { 299 + const url = e.target.result; 300 + $(".settings-form .account-icon-thumbnail") 301 + .attr("style", `background-image: url("${url}")`); 302 + 303 + }; 304 + reader.readAsDataURL(files[0]); 305 + 306 + } 307 + 308 + }); 309 + 310 + // add tag when comma/enter 311 + $("body").on("keypress", ".upload-form input.add-tag", function(e) { 312 + if (e.which == 44) e.preventDefault(); // comma 313 + if (e.which == 44 || e.which == 13) { // comma || enter 314 + const $inputElement = $(this); 315 + const value = $(this).val(); 316 + $inputElement.val(""); // empty the input 317 + $(` 318 + <div class="tag"> 319 + <div class="tag-text">${value}</div> 320 + <button class="remove-tag">x</div> 321 + </div> 322 + `).insertBefore($inputElement); 323 + } 324 + }); 325 + 326 + // remove tag button 327 + $("body").on("click", ".upload-form .remove-tag", function() { 328 + $(this).parent().remove(); 329 + }); 330 + 331 + // clicking the tags-box focuses the add-tag input element 332 + $("body").on("click", ".upload-form .tags-box", (e) => { 333 + if (e.target == e.currentTarget) { 334 + $(".upload-form input.add-tag").focus(); 335 + } 336 + }); 337 + 338 + function upload() { 339 + 340 + const data = new FormData(); 341 + data.append("image", uploadData[0], uploadData[0].name); 342 + data.append("title", $(".upload-form input.title").val()); 343 + data.append("description", $(".upload-form textarea.description").val()); 344 + 345 + const tagsArray = []; 346 + $(".upload-form .tags-box .tag").each((i, obj) => { 347 + const tagText = $(obj).find(".tag-text").html(); 348 + tagsArray.push(tagText); 349 + }); 350 + data.append("tags", JSON.stringify(tagsArray)); 351 + 352 + console.log(data.get("image")); 353 + console.log(data.get("title")); 354 + console.log(data.get("description")); 355 + console.log(data.get("tags")); 356 + 357 + xhr(data, "/upload", { 358 + contentType: "none", 359 + }, (res, err) => { 360 + if (err); // http status code not 2xx 361 + console.log(res); 362 + if (res.errors.length == 0) { 363 + console.log("success!"); 364 + } 365 + }); 366 + 367 + } 368 + 369 + // upload button click 370 + $("body").on("click", ".upload-form button.upload", () => { 371 + upload(); 372 + }); 373 + 374 + });
+6 -3
web/js/user.js
··· 9 9 if (res.errors.length == 0) { 10 10 for (let i = 0; i < res.images.length; i++) { 11 11 const image = res.images[i]; 12 - let imageElement = $("a.sample-image").clone(); 12 + let imageElement = $(".sample-image").clone(); 13 13 imageElement.removeClass("sample-image").addClass("image"); 14 - imageElement.attr("href", "/i/"+image.fileID); 15 - imageElement.find("img").attr("src", "/i/"+image.filename); 14 + imageElement.find("a.image-link").attr("href", "/i/"+image.fileID); 15 + imageElement.find("img.image").attr("src", "/i/"+image.filename); 16 + imageElement.find("img.profile-picture").attr("src", image.userID.profilePictureURL); 17 + imageElement.find("a.row-left").attr("href", image.userID.username); 18 + imageElement.find("p.displayname").html(image.userID.displayname); 16 19 $(".images-container .col-"+i%3).append(imageElement); 17 20 } 18 21 }
+13 -4
web/node/format-date.js
··· 11 11 // MMMM 12 12 result = result.replace("MMMM", months[date.getMonth()]); 13 13 14 + // MMM 15 + result = result.replace("MMM", months[date.getMonth()].substr(0,3)); 16 + 17 + let dayOfMonth = date.getDate(); 18 + 14 19 // Dth 15 - let dayOfMonth = date.getDate(); 16 20 let th = "th"; 17 - if (dayOfMonth == 1) th = "st"; 18 - if (dayOfMonth == 2) th = "nd"; 19 - if (dayOfMonth == 3) th = "rd"; 21 + if (dayOfMonth == 1 || dayOfMonth == 21 || dayOfMonth == 31 ) th = "st"; 22 + if (dayOfMonth == 2 || dayOfMonth == 22 ) th = "nd"; 23 + if (dayOfMonth == 3 || dayOfMonth == 23 ) th = "rd"; 20 24 result = result.replace("Dth", dayOfMonth+th); 25 + 26 + // D 27 + result = result.replace("D", dayOfMonth); 28 + 29 + 21 30 return result; 22 31 }
+4 -1
web/node/mongoose-models.js
··· 25 25 }); 26 26 27 27 const imageSchema = new Schema({ 28 - userID: String, 28 + userID: { 29 + type: mongoose.Schema.Types.ObjectId, 30 + ref: "User", 31 + }, 29 32 fileID: String, 30 33 filename: String, 31 34 title: String,
+18 -4
web/node/routes.js
··· 234 234 235 235 app.post("/getUsersImages", (req, res) => { 236 236 const errors = []; 237 + // Image.find({userID:req.body.userID}, null, { 238 + // skip: req.body.skip, 239 + // limit: req.body.limit, 240 + // sort: { 241 + // date: -1, 242 + // }, 243 + // }, (err, resultImages) => { 244 + // res.json({ 245 + // errors: errors, 246 + // images: resultImages, 247 + // }); 248 + // }); 237 249 Image.find({userID:req.body.userID}, null, { 238 250 skip: req.body.skip, 239 251 limit: req.body.limit, 240 252 sort: { 241 253 date: -1, 242 254 }, 243 - }, (err, resultImages) => { 255 + }).populate("userID").exec((err, resultImages) => { 244 256 res.json({ 245 257 errors: errors, 246 258 images: resultImages, ··· 257 269 get("/login", "login"); 258 270 get("/register", "register"); 259 271 get("/", "home"); 260 - 261 - // logged in 262 - get("/upload", "upload"); 263 272 get("/u/:username", "user", (req, res, callback) => { 264 273 check.ifUsernameExists(req.params.username).then((user) => { 265 274 user.formattedDate = formatDate(user.dateCreated, "MMMM Dth, YYYY"); ··· 278 287 }); 279 288 }); 280 289 }); 290 + get("/i/:image", "image"); 291 + 292 + // logged in 293 + get("/upload", "upload"); 294 + get("/settings", "settings"); 281 295 282 296 }
+16
web/pug/logged-in/settings.pug
··· 1 + .form-container.settings-form.page-width 2 + .form 3 + .upload-avatar-container 4 + .account-icon-thumbnail(style= 'background-image:url("'+profilePictureURL+'")') 5 + .upload-box 6 + .select-file.container 7 + button.button.files Select file 8 + .drop-to-select-file.container.hidden 9 + p Drop to select the file 10 + .main-form 11 + input(type="file" name="files" id="files", accept="image/jpeg,image/png") 12 + label(for="displayname") Displayname 13 + input.form-field.displayname(type="text", name="displayname" id="displayname") 14 + label(for="bio") Bio 15 + textarea.form-field.auto-resize.bio(type="text", name="bio" id="bio", rows="3") 16 + button.button.upload(tabIndex="0") Upload
+1 -1
web/pug/logged-out/home.pug
··· 1 1 .center-container.page-width 2 2 p.center-logo Lumix 3 - p.tagline The place you put your art 3 + p.tagline Where art belongs
web/pug/logged-out/image.pug

This is a binary file and will not be displayed.

+13 -4
web/pug/logged-out/user.pug
··· 3 3 .profile-container 4 4 //- p.displayname=user.displayname 5 5 p.displayname= user.displayname 6 - p.followers <span>!{user.followers}</span> followers 7 - p.date= "Joined "+user.formattedDate 6 + .row 7 + p.followers <span>!{user.followers}</span> followers 8 + p.date= "Joined "+user.formattedDate 8 9 p.bio= user.bio 9 10 .images-container 10 11 //- each image in images ··· 13 14 .column.col-0 14 15 .column.col-1 15 16 .column.col-2 16 - a.sample-image 17 - img 17 + .sample-image 18 + a.row.row-left 19 + img.profile-picture 20 + p.displayname 21 + .row.row-right 22 + .icon.like 23 + .icon.download 24 + a.image-link 25 + img.image 26 + .gradient
+1
web/sass/defaults.sass
··· 17 17 section, audio, video, input, button, textarea 18 18 color: $black 19 19 font: inherit 20 + line-height: normal 20 21 margin: 0 21 22 padding: 0 22 23 border: 0
+36 -4
web/sass/forms.sass
··· 20 20 border-radius: 5px 21 21 width: 250px 22 22 background-color: $white-dark 23 - &.login-form 24 - &.register-form 23 + input#files 24 + display: none 25 25 .form-container.upload-form 26 26 .container 27 27 position: absolute ··· 57 57 background-position: center 58 58 width: 100% 59 59 height: 100% 60 - input#files 61 - display: none 62 60 input.form-field, textarea.form-field, .tags-box 63 61 width: 600px 64 62 .tags-box ··· 107 105 background-color: transparent 108 106 button.upload 109 107 margin: auto 108 + .form-container.settings-form 109 + .upload-avatar-container 110 + display: flex 111 + justify-content: center 112 + align-items: center 113 + margin-bottom: 15px 114 + .account-icon-thumbnail 115 + min-width: 100px 116 + width: 100px 117 + height: 100px 118 + background-position: center 119 + background-size: contain 120 + background-repeat: no-repeat 121 + .upload-box 122 + width: 100% 123 + height: 100px 124 + position: relative 125 + .container 126 + position: absolute 127 + width: 100% 128 + height: 100% 129 + z-index: 1 130 + opacity: 1 131 + display: flex 132 + align-items: center 133 + justify-content: center 134 + transition: $transition-20 all 135 + &.hidden 136 + opacity: 0 137 + pointer-events: none 138 + button.files 139 + margin: auto 140 + button.upload 141 + margin: auto
+1
web/sass/global.sass
··· 10 10 @import "user.sass" 11 11 @import "buttons.sass" 12 12 @import "forms.sass" 13 + @import "images.sass" 13 14 // @import "buttons.sass" 14 15 // @import "cards.sass"
+83
web/sass/images.sass
··· 1 + .images-container 2 + display: flex 3 + $image-spacing: 24px 4 + .column 5 + width: 100% 6 + margin-right: $image-spacing 7 + &:first-child 8 + margin-left: $image-spacing 9 + .image 10 + display: block 11 + width: 100% 12 + margin-bottom: $image-spacing 13 + position: relative 14 + &:hover 15 + .row.row-left 16 + opacity: 0.8 17 + .row.row-right 18 + opacity: 1 19 + .gradient 20 + opacity: 1 21 + .icon 22 + background-position: center 23 + background-size: 24px 24 + background-repeat: no-repeat 25 + height: 24px 26 + width: 24px 27 + cursor: pointer 28 + .row 29 + opacity: 0 30 + transition: $transition-15 all 31 + display: flex 32 + position: absolute 33 + align-items: center 34 + bottom: 0px 35 + z-index: 1 36 + &.row-left 37 + left: 0px 38 + padding: 4px 4px 39 + margin: 8px 8px 40 + opacity: 0 41 + transition: $transition-15 all 42 + &:hover 43 + opacity: 1 44 + img.profile-picture 45 + width: 24px 46 + height: 24px 47 + p.displayname 48 + margin-left: 12px 49 + color: white 50 + font-size: 15px 51 + &.row-right 52 + right: 0px 53 + .like, .download 54 + padding: 4px 4px 55 + margin: 8px 8px 56 + .like 57 + margin-right: 0px 58 + opacity: 0.8 59 + transition: $transition-15 all 60 + &:hover 61 + opacity: 1 62 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"/></svg>') 63 + .liked 64 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>') 65 + .download 66 + margin-left: 0px 67 + opacity: 0.8 68 + &:hover 69 + opacity: 1 70 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>') 71 + a.image-link 72 + img.image 73 + width: 100% 74 + .gradient 75 + opacity: 0 76 + position: absolute 77 + pointer-events: none 78 + width: 100% 79 + height: 100% 80 + top: 0px 81 + background-image: linear-gradient(180deg, transparent 0, transparent 60%, rgba(#000000, 0.3)) 82 + .sample-image 83 + display: none
+10 -25
web/sass/user.sass
··· 12 12 margin-left: 50px 13 13 p.displayname 14 14 font-size: 32px 15 - margin-bottom: 16px 16 - p.followers 17 - span 18 - font-weight: 500 19 - display: inline 20 - p.date 21 - display: inline 22 - margin-left: 64px 15 + .row 16 + display: flex 17 + margin: 16px 0px 18 + p.followers 19 + span 20 + font-weight: 500 21 + display: inline 22 + p.date 23 + display: inline 24 + margin-left: 64px 23 25 p.bio 24 - margin-top: 16px 25 26 font-size: 15px 26 - .images-container 27 - display: flex 28 - $image-spacing: 24px 29 - .column 30 - width: 100% 31 - margin-right: $image-spacing 32 - &:first-child 33 - margin-left: $image-spacing 34 - a.image 35 - display: block 36 - width: 100% 37 - margin-bottom: $image-spacing 38 - img 39 - width: 100% 40 - .sample-image 41 - display: none
-1
web/sass/variables.sass
··· 29 29 // $shadow-5: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22) 30 30 31 31 // transitions 32 - $transition: .15s cubic-bezier(0.4, 0.0, 0.2, 1.0) 33 32 $transition-15: .15s cubic-bezier(0.4, 0.0, 0.2, 1.0) 34 33 35 34 $transition-10: .10s cubic-bezier(0.4, 0.0, 0.2, 1.0)
+130 -29
web/static/global.css
··· 22 22 section, audio, video, input, button, textarea { 23 23 color: #3F3F3F; 24 24 font: inherit; 25 + line-height: normal; 25 26 margin: 0; 26 27 padding: 0; 27 28 border: 0; ··· 189 190 width: 500px; 190 191 margin-left: 50px; } 191 192 html header.profile-header .profile-container p.displayname { 192 - font-size: 32px; 193 - margin-bottom: 16px; } 194 - html header.profile-header .profile-container p.followers { 195 - display: inline; } 196 - html header.profile-header .profile-container p.followers span { 197 - font-weight: 500; } 198 - html header.profile-header .profile-container p.date { 199 - display: inline; 200 - margin-left: 64px; } 193 + font-size: 32px; } 194 + html header.profile-header .profile-container .row { 195 + display: flex; 196 + margin: 16px 0px; } 197 + html header.profile-header .profile-container .row p.followers { 198 + display: inline; } 199 + html header.profile-header .profile-container .row p.followers span { 200 + font-weight: 500; } 201 + html header.profile-header .profile-container .row p.date { 202 + display: inline; 203 + margin-left: 64px; } 201 204 html header.profile-header .profile-container p.bio { 202 - margin-top: 16px; 203 205 font-size: 15px; } 204 - 205 - html .images-container { 206 - display: flex; } 207 - html .images-container .column { 208 - width: 100%; 209 - margin-right: 24px; } 210 - html .images-container .column:first-child { 211 - margin-left: 24px; } 212 - html .images-container .column a.image { 213 - display: block; 214 - width: 100%; 215 - margin-bottom: 24px; } 216 - html .images-container .column a.image img { 217 - width: 100%; } 218 - html .images-container .sample-image { 219 - display: none; } 220 206 221 207 html .button { 222 208 padding: 12px 8px; ··· 261 247 border-radius: 5px; 262 248 width: 250px; 263 249 background-color: rgba(0, 0, 0, 0.05); } 250 + html .form-container .form input#files { 251 + display: none; } 264 252 265 253 html .form-container.upload-form .container { 266 254 position: absolute; ··· 299 287 width: 100%; 300 288 height: 100%; } 301 289 302 - html .form-container.upload-form input#files { 303 - display: none; } 304 - 305 290 html .form-container.upload-form input.form-field, html .form-container.upload-form textarea.form-field, html .form-container.upload-form .tags-box { 306 291 width: 600px; } 307 292 ··· 350 335 351 336 html .form-container.upload-form button.upload { 352 337 margin: auto; } 338 + 339 + html .form-container.settings-form .upload-avatar-container { 340 + display: flex; 341 + justify-content: center; 342 + align-items: center; 343 + margin-bottom: 15px; } 344 + html .form-container.settings-form .upload-avatar-container .account-icon-thumbnail { 345 + min-width: 100px; 346 + width: 100px; 347 + height: 100px; 348 + background-position: center; 349 + background-size: contain; 350 + background-repeat: no-repeat; } 351 + html .form-container.settings-form .upload-avatar-container .upload-box { 352 + width: 100%; 353 + height: 100px; 354 + position: relative; } 355 + html .form-container.settings-form .upload-avatar-container .upload-box .container { 356 + position: absolute; 357 + width: 100%; 358 + height: 100%; 359 + z-index: 1; 360 + opacity: 1; 361 + display: flex; 362 + align-items: center; 363 + justify-content: center; 364 + transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1) all; } 365 + html .form-container.settings-form .upload-avatar-container .upload-box .container.hidden { 366 + opacity: 0; 367 + pointer-events: none; } 368 + html .form-container.settings-form .upload-avatar-container .upload-box .container button.files { 369 + margin: auto; } 370 + 371 + html .form-container.settings-form button.upload { 372 + margin: auto; } 373 + 374 + html .images-container { 375 + display: flex; } 376 + html .images-container .column { 377 + width: 100%; 378 + margin-right: 24px; } 379 + html .images-container .column:first-child { 380 + margin-left: 24px; } 381 + html .images-container .column .image { 382 + display: block; 383 + width: 100%; 384 + margin-bottom: 24px; 385 + position: relative; } 386 + html .images-container .column .image:hover .row.row-left { 387 + opacity: 0.8; } 388 + html .images-container .column .image:hover .row.row-right { 389 + opacity: 1; } 390 + html .images-container .column .image:hover .gradient { 391 + opacity: 1; } 392 + html .images-container .column .image .icon { 393 + background-position: center; 394 + background-size: 24px; 395 + background-repeat: no-repeat; 396 + height: 24px; 397 + width: 24px; 398 + cursor: pointer; } 399 + html .images-container .column .image .row { 400 + opacity: 0; 401 + transition: 0.15s cubic-bezier(0.4, 0, 0.2, 1) all; 402 + display: flex; 403 + position: absolute; 404 + align-items: center; 405 + bottom: 0px; 406 + z-index: 1; } 407 + html .images-container .column .image .row.row-left { 408 + left: 0px; 409 + padding: 4px 4px; 410 + margin: 8px 8px; 411 + opacity: 0; 412 + transition: 0.15s cubic-bezier(0.4, 0, 0.2, 1) all; } 413 + html .images-container .column .image .row.row-left:hover { 414 + opacity: 1; } 415 + html .images-container .column .image .row.row-left img.profile-picture { 416 + width: 24px; 417 + height: 24px; } 418 + html .images-container .column .image .row.row-left p.displayname { 419 + margin-left: 12px; 420 + color: white; 421 + font-size: 15px; } 422 + html .images-container .column .image .row.row-right { 423 + right: 0px; } 424 + html .images-container .column .image .row.row-right .like, html .images-container .column .image .row.row-right .download { 425 + padding: 4px 4px; 426 + margin: 8px 8px; } 427 + html .images-container .column .image .row.row-right .like { 428 + margin-right: 0px; 429 + opacity: 0.8; 430 + transition: 0.15s cubic-bezier(0.4, 0, 0.2, 1) all; 431 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"/></svg>'); } 432 + html .images-container .column .image .row.row-right .like:hover { 433 + opacity: 1; } 434 + html .images-container .column .image .row.row-right .like .liked { 435 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>'); } 436 + html .images-container .column .image .row.row-right .download { 437 + margin-left: 0px; 438 + opacity: 0.8; 439 + background-image: url('data:image/svg+xml;utf8,<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'); } 440 + html .images-container .column .image .row.row-right .download:hover { 441 + opacity: 1; } 442 + html .images-container .column .image a.image-link img.image { 443 + width: 100%; } 444 + html .images-container .column .image .gradient { 445 + opacity: 0; 446 + position: absolute; 447 + pointer-events: none; 448 + width: 100%; 449 + height: 100%; 450 + top: 0px; 451 + background-image: linear-gradient(180deg, transparent 0, transparent 60%, rgba(0, 0, 0, 0.3)); } 452 + html .images-container .sample-image { 453 + display: none; }
+148 -4
web/static/global.js
··· 307 307 hide(); 308 308 }); 309 309 $(window).on("dragleave", function (e) { 310 - console.log(e); 311 310 e = e.originalEvent; 312 311 if (e.relatedTarget == null || $(e.target).hasClass("upload-form")) { 313 312 hide(); ··· 408 407 }); 409 408 }); 410 409 410 + fold("settings form", function () { 411 + 412 + fold("file select", function () { 413 + 414 + // click "select file" button opens file select dialog 415 + $("body").on("click", ".settings-form button.files", function () { 416 + $(".settings-form input#files").click(); 417 + }); 418 + 419 + function containsAFile(e) { 420 + if (e.originalEvent) e = e.originalEvent; 421 + var dtTypes = e.dataTransfer.types; 422 + if (dtTypes.length == 1 && dtTypes[0] == "Files") { 423 + return true; 424 + } 425 + return false; 426 + } 427 + 428 + // setup 429 + var setupEvents = "drag dragstart dragend dragover dragenter dragleave drop"; 430 + $(window).on(setupEvents, function (e) { 431 + if ($(e.target).inOrIs(".upload-avatar-container")) { 432 + e.preventDefault(); 433 + e.stopPropagation(); 434 + } 435 + }); 436 + function show() { 437 + $(".settings-form .drop-to-select-file").removeClass("hidden"); 438 + $(".settings-form .select-file").addClass("hidden"); 439 + } 440 + function hide() { 441 + $(".settings-form .drop-to-select-file").addClass("hidden"); 442 + $(".settings-form .select-file").removeClass("hidden"); 443 + } 444 + // show 445 + $(window).on("dragenter", function (e) { 446 + if ($(e.target).inOrIs(".upload-avatar-container")) { 447 + if (containsAFile(e)) show(); 448 + } 449 + }); 450 + // hide 451 + $(window).on("dragend", function (e) { 452 + hide(); 453 + }); 454 + $(window).on("dragleave", function (e) { 455 + e = e.originalEvent; 456 + if (e.relatedTarget == null || $(e.target).hasClass("upload-avatar-container")) { 457 + hide(); 458 + } 459 + }); 460 + // drop 461 + $(window).on("drop", function (e) { 462 + hide(); 463 + if (containsAFile(e)) { 464 + var files = e.originalEvent.dataTransfer.files; 465 + if (files[0].type == "image/png" || files[0].type == "image/jpeg") { 466 + handleFiles(files); 467 + } else {// wrong fileExt 468 + 469 + } 470 + } 471 + }); 472 + 473 + $("body").on("change", ".settings-form input#files", function (e) { 474 + var input = $(this); 475 + var files = input.prop("files"); 476 + handleFiles(files); 477 + }); 478 + 479 + // handle files 480 + function handleFiles(files) { 481 + window.uploadData = files; 482 + 483 + var reader = new FileReader(); 484 + reader.onload = function (e) { 485 + var url = e.target.result; 486 + $(".settings-form .account-icon-thumbnail").attr("style", "background-image: url(\"" + url + "\")"); 487 + }; 488 + reader.readAsDataURL(files[0]); 489 + } 490 + }); 491 + 492 + // add tag when comma/enter 493 + $("body").on("keypress", ".upload-form input.add-tag", function (e) { 494 + if (e.which == 44) e.preventDefault(); // comma 495 + if (e.which == 44 || e.which == 13) { 496 + // comma || enter 497 + var $inputElement = $(this); 498 + var value = $(this).val(); 499 + $inputElement.val(""); // empty the input 500 + $("\n <div class=\"tag\">\n <div class=\"tag-text\">" + value + "</div>\n <button class=\"remove-tag\">x</div>\n </div>\n ").insertBefore($inputElement); 501 + } 502 + }); 503 + 504 + // remove tag button 505 + $("body").on("click", ".upload-form .remove-tag", function () { 506 + $(this).parent().remove(); 507 + }); 508 + 509 + // clicking the tags-box focuses the add-tag input element 510 + $("body").on("click", ".upload-form .tags-box", function (e) { 511 + if (e.target == e.currentTarget) { 512 + $(".upload-form input.add-tag").focus(); 513 + } 514 + }); 515 + 516 + function upload() { 517 + 518 + var data = new FormData(); 519 + data.append("image", uploadData[0], uploadData[0].name); 520 + data.append("title", $(".upload-form input.title").val()); 521 + data.append("description", $(".upload-form textarea.description").val()); 522 + 523 + var tagsArray = []; 524 + $(".upload-form .tags-box .tag").each(function (i, obj) { 525 + var tagText = $(obj).find(".tag-text").html(); 526 + tagsArray.push(tagText); 527 + }); 528 + data.append("tags", JSON.stringify(tagsArray)); 529 + 530 + console.log(data.get("image")); 531 + console.log(data.get("title")); 532 + console.log(data.get("description")); 533 + console.log(data.get("tags")); 534 + 535 + xhr(data, "/upload", { 536 + contentType: "none" 537 + }, function (res, err) { 538 + if (err) ; // http status code not 2xx 539 + console.log(res); 540 + if (res.errors.length == 0) { 541 + console.log("success!"); 542 + } 543 + }); 544 + } 545 + 546 + // upload button click 547 + $("body").on("click", ".upload-form button.upload", function () { 548 + upload(); 549 + }); 550 + }); 551 + 411 552 /***/ }), 412 553 /* 4 */ 413 554 /***/ (function(module, exports, __webpack_require__) { ··· 426 567 if (res.errors.length == 0) { 427 568 for (var i = 0; i < res.images.length; i++) { 428 569 var image = res.images[i]; 429 - var imageElement = $("a.sample-image").clone(); 570 + var imageElement = $(".sample-image").clone(); 430 571 imageElement.removeClass("sample-image").addClass("image"); 431 - imageElement.attr("href", "/i/" + image.fileID); 432 - imageElement.find("img").attr("src", "/i/" + image.filename); 572 + imageElement.find("a.image-link").attr("href", "/i/" + image.fileID); 573 + imageElement.find("img.image").attr("src", "/i/" + image.filename); 574 + imageElement.find("img.profile-picture").attr("src", image.userID.profilePictureURL); 575 + imageElement.find("a.row-left").attr("href", image.userID.username); 576 + imageElement.find("p.displayname").html(image.userID.displayname); 433 577 $(".images-container .col-" + i % 3).append(imageElement); 434 578 } 435 579 }
web/static/kglogo.png

This is a binary file and will not be displayed.