From bcbb195c21466df915e105415fd08a9a96c8280b Mon Sep 17 00:00:00 2001 From: Andre Beging Date: Thu, 4 Nov 2021 14:07:45 +0100 Subject: [PATCH] Update foodsharing_planner.user.js --- foodsharing_planner.user.js | 283 ++++++++++++++++++------------------ 1 file changed, 145 insertions(+), 138 deletions(-) diff --git a/foodsharing_planner.user.js b/foodsharing_planner.user.js index 0b52d2b..f34d39b 100644 --- a/foodsharing_planner.user.js +++ b/foodsharing_planner.user.js @@ -1,13 +1,19 @@ // ==UserScript== // @name Foodsharing Planner // @namespace http://tampermonkey.net/ -// @version 0.1 -// @updateURL https://github.com/TroogS/userscripts/raw/master/foodsharing_planner.user.js -// @downloadURL https://github.com/TroogS/userscripts/raw/master/foodsharing_planner.user.js -// @description Use stackoverflow full width, optional night mode +// @version 0.2 +// @updateURL https://github.com/TroogS/userscripts/blob/master/foodsharing_planner.user.js +// @downloadURL https://github.com/TroogS/userscripts/blob/master/foodsharing_planner.user.js +// @description Generate a calendar like view as addition to the foodsharing website germany, austria and switzerland // @author A. Beging // @match https://foodsharing.de* // @match https://foodsharing.de/* +// @match https://foodsharing.at* +// @match https://foodsharing.at/* +// @match https://foodsharingschweiz.ch* +// @match https://foodsharingschweiz.ch/* +// @match https://foodsharing.network* +// @match https://foodsharing.network/* // @grant none // ==/UserScript== @@ -18,6 +24,9 @@ function GM_addStyle (cssStr) { } var token; +var gPickupData; +var gLoaded = false; +var gFirstDayDate; (function() { 'use strict'; @@ -70,43 +79,84 @@ a.navbar-brand.brand span:nth-child(2) span{ .day .pickup { border: 1px solid #533a20; + border-left-width: 5px; margin: 5px; border-radius: 5px; padding: 5px; } -.day .pickup.available { - border-color: #64ae25; +.day .pickup.pickup-green { + border-left-color: #64ae24; +} + +.day .pickup.pickup-yellow { + border-left-color: #ffc107 +} + +.day .pickup.pickup-red { + border-left-color: #dc3545; } .day .pickup .img-container { display: flex; } -.day .pickup .img-container div { +.day .pickup .img-container > div { padding-right: 5px; } +.day .pickup .img-container > div img { + width: 35px; + height: 35px; + border-radius: 5px; +} + +.day .pickup .img-container .empty-slot { + width: 34px; + display: flex; + height: 34px; + justify-content: center; + align-items: center; + border: 1px solid #533a20; + text-decoration: none; + margin-right: 5px; + border-radius: 5px; +} + +.day .pickup .img-container .empty-slot:hover i { + color: #533a20; +} + ` ); async function BuildPlannerAsync() { - var data = await LoadPickupsAsync(); - console.log(data); - + gFirstDayDate = GetFirstDay(); var mainPanel = document.querySelectorAll(".fspl")[0]; - var mon = CreateColumn("1", "Montag"); - var tue = CreateColumn("2", "Tuesday"); - var wed = CreateColumn("3", "Wednesday"); - var thu = CreateColumn("4", "Thursday"); - var fri = CreateColumn("5", "Friday"); - var sat = CreateColumn("6", "Saturday"); - var sun = CreateColumn("7", "Sunday"); + var mon = CreateColumn(0, "Montag", ' ', null); + var tue = CreateColumn(1, "Dienstag"); + var wed = CreateColumn(2, "Mittwoch"); + var thu = CreateColumn(3, "Donnerstag"); + var fri = CreateColumn(4, "Freitag"); + var sat = CreateColumn(5, "Samstag"); + var sun = CreateColumn(6, "Sonntag", null, ' '); - data.sort(function(a, b){return a.pickup.date > b.pickup.date}); - data.forEach(pickup => { + mainPanel.append(mon); + mainPanel.append(tue); + mainPanel.append(wed); + mainPanel.append(thu); + mainPanel.append(fri); + mainPanel.append(sat); + mainPanel.append(sun); - if(pickup.pickup.date > GetFirstDay() && pickup.pickup.date < GetLastDay()) { + if(!gLoaded) gPickupData = await LoadPickupsAsync(); + + var lastDayDate = GetLastDay(gFirstDayDate); + + gPickupData.sort(function(a, b){return a.pickup.date > b.pickup.date}); + gPickupData.forEach(pickup => { + + if(pickup.pickup.date > gFirstDayDate && pickup.pickup.date < lastDayDate) { var pickupDiv = CreatePickupDiv(pickup); switch (pickup.pickup.date.getDay()) { @@ -134,50 +184,8 @@ async function BuildPlannerAsync() { } } }); - - mainPanel.append(mon); - mainPanel.append(tue); - mainPanel.append(wed); - mainPanel.append(thu); - mainPanel.append(fri); - mainPanel.append(sat); - mainPanel.append(sun); } -/*function BuildPlanner() { - - - - console.log(22); - return; - console.log(11); - LoadPickups().then(function(data){ - - - console.log(1); - console.log(data); - console.log(2); - - data.forEach(store => { - store.pickups.forEach(pickup => { - var pickupDiv = CreatePickupDiv(store.name, "19"); - mon.append(pickupDiv); - }); - }); - - mainPanel.append(mon); - mainPanel.append(tue); - mainPanel.append(wed); - mainPanel.append(thu); - mainPanel.append(fri); - mainPanel.append(sat); - mainPanel.append(sun); - - return; - }); - -}*/ - function GetFirstDay() { var curr = new Date(); var first = curr.getDate() - curr.getDay() + 1; @@ -187,8 +195,8 @@ function GetFirstDay() { return firstDay; } -function GetLastDay() { - var curr = new Date(); +function GetLastDay(firstDayDate) { + var curr = new Date(firstDayDate); var last = curr.getDate() - curr.getDay() + 7; var lastDay = new Date(curr.setDate(last)); lastDay.setHours(23,59,59,999); @@ -198,7 +206,10 @@ function GetLastDay() { function CreatePickupDiv(data) { var elementClass = "pickup"; - if(data.pickup.isAvailable) elementClass += " available"; + if(data.pickup.occupiedSlots.length == data.pickup.totalSlots) elementClass += " pickup-green"; + if(data.pickup.occupiedSlots.length < data.pickup.totalSlots && data.pickup.occupiedSlots.length > 0) elementClass += " pickup-yellow"; + if(data.pickup.occupiedSlots.length == 0) elementClass += " pickup-red"; + var element = CreateElement("div", elementClass); var headerSpan = CreateElement("div", "font-weight-bold", data.store.name); @@ -210,17 +221,34 @@ function CreatePickupDiv(data) { var timeSpan = CreateElement("div", "", timeString); element.append(timeSpan); - if(data.pickup.occupiedSlots.length > 0) { - var imgContainer = CreateElement("div", "img-container"); - data.pickup.occupiedSlots.forEach(slot => { - var imgDiv = CreateElement("div"); - imgDiv.innerHTML = ''; - imgContainer.append(imgDiv); - }); + var imgContainer = CreateElement("div", "img-container"); - element.append(imgContainer); - } + // Occupies slots + if(data.pickup.occupiedSlots.length > 0) { + + data.pickup.occupiedSlots.forEach(slot => { + var imgUrl = 'images/mini_q_' + slot.profile.avatar; + if(slot.profile.avatar.startsWith('/api/')) imgUrl = slot.profile.avatar + '?w=35&h=35'; + + var imgDiv = CreateElement("div"); + imgDiv.innerHTML = ''; + imgContainer.append(imgDiv); + }); + } + + // Free slots + for (let i = 0; i < data.pickup.freeSlots; i++) { + var freeSlotA = CreateElement("a", "empty-slot"); + freeSlotA.setAttribute("href", "https://" + window.location.hostname + "/?page=fsbetrieb&id=" + data.store.id); + freeSlotA.setAttribute("target", "_blank"); + + freeSlotA.innerHTML = ''; + + imgContainer.append(freeSlotA); + } + + element.append(imgContainer); return element; @@ -228,7 +256,7 @@ function CreatePickupDiv(data) { async function LoadPickupsAsync() { - var pickupData = new Array(); + let pickupData = new Array(); var apiStoreData = await ApiGetCallAsync("user/current/stores"); await asyncForEach(apiStoreData, async (store) => { @@ -238,6 +266,7 @@ async function LoadPickupsAsync() { apiPickups.pickups.forEach(pickup => { pickup.date = new Date(pickup.date); + pickup.freeSlots = pickup.totalSlots - pickup.occupiedSlots.length; var obj = { store: { @@ -252,6 +281,7 @@ async function LoadPickupsAsync() { } }); + gLoaded = true; return pickupData; } @@ -261,52 +291,44 @@ async function asyncForEach(array, callback) { } } -function LoadPickups() { - - return new Promise(function(resolve, reject){ - - var storeData = new Array(); - - // Retrieve stores - ApiGetCall('user/current/stores').then(function(apiStoreData){ - apiStoreData.forEach(store => { - - // Retrieve pickups for store - ApiGetCall('stores/' + store.id + '/pickups').then(function(apiPickups) { - if(apiPickups.pickups.length > 0) { - - apiPickups.pickups.forEach(pickup => { - pickup.date = new Date(pickup.date); - }); - - // Add storedata only if pickups available - var obj = { - id: store.id, - name: store.name, - pickups: apiPickups.pickups, - pickupStatus: store.pickupStatus, - }; - - - storeData.push(obj); - } - }); - }); - - resolve(storeData); - }); - }); - -} - -function CreateColumn(num, title) { +function CreateColumn(num, title, htmlPre, htmlSuf) { var titleDiv = CreateElement("div", "day-title text-center", title); + titleDiv.innerHTML = title; + + if(htmlPre) { + titleDiv.innerHTML = htmlPre + titleDiv.innerHTML; + } + if(htmlSuf) { + titleDiv.innerHTML = titleDiv.innerHTML + htmlSuf; + } + + var displayDate = new Date(gFirstDayDate); + displayDate.setDate(gFirstDayDate.getDate() + num); + console.log(displayDate); + + titleDiv.innerHTML = titleDiv.innerHTML + "
" + GetDatetext(displayDate); + var day = CreateElement("div", "day day-" + num, titleDiv); return day; } +function GetDatetext(date) { + return WithLeadingZeros(date.getDate(), 2) + "." + WithLeadingZeros(date.getMonth(), 2) + "." + WithLeadingZeros(date.getYear() + 1900, 4) +} +function WithLeadingZeros(number, length) { + + var stringNumber = number.toString(); + + while(stringNumber.length < length) { + stringNumber = "0" + stringNumber; + } + + return stringNumber; +} + +// Toggle planner visibility. Load data on show function TogglePlanner() { var mainPanel = document.querySelectorAll(".fspl")[0]; @@ -319,6 +341,7 @@ function TogglePlanner() { } } +// Create calendar button for navigation bar function CreateButton() { var i = CreateElement("i", "fas fa-calendar-alt"); var a = CreateElement("a", "nav-link", i); @@ -331,6 +354,7 @@ function CreateButton() { document.querySelectorAll(".navbar-nav.nav-row")[0].append(div); } +// Create element helper function function CreateElement(tagName, classList, content) { var element = document.createElement(tagName); @@ -340,34 +364,17 @@ function CreateElement(tagName, classList, content) { return element; } -function ApiGetCall(endpoint) { - - if(token == null) { token = ReadToken(); } - - return new Promise(function(resolve, reject){ - window.$.ajax({ - url: 'https://foodsharing.de/api/' + endpoint, - beforeSend: function(xhr) { - xhr.setRequestHeader("X-CSRF-Token", token) - }, success: function(data){ - resolve(data) - } - }); - }); -} - +// Api call function async function ApiGetCallAsync(endpoint) { - const res = await getData('https://foodsharing.de/api/' + endpoint); + const res = await window.$.ajax({ + url: 'https://' + window.location.hostname + '/api/' + endpoint, + type: 'GET', + }); + return res; } -function getData(ajaxurl) { - return window.$.ajax({ - url: ajaxurl, - type: 'GET', - }); -}; - +// Read token from cookie function ReadToken() { var nameEQ = "CSRF_TOKEN="; var ca = document.cookie.split(';');