initial commit - code moved to separate repo
This commit is contained in:
223
_doc/GoogleFormsScript.gs
Normal file
223
_doc/GoogleFormsScript.gs
Normal file
@ -0,0 +1,223 @@
|
||||
function main() {
|
||||
var form = FormApp.openById("11VuGKjoywNA0ajrfeRVwdNYDXSM0ge2qAn6bhiXOZj0"); // Replace with your Form's ID
|
||||
var sheet = SpreadsheetApp.openById("17CFpEDZ2Bn5GJSfMUhliwBBdbCaghATxZ5lYwRSbGsY").getSheetByName("Sheet1");
|
||||
var sheetResults = SpreadsheetApp.openById("1jIW27zh-502WIBpFVWGuNSZp7vBuB-SW6L_NPKgf4Ys").getSheetByName("Form Responses 1");
|
||||
|
||||
setNamesDropdownOptions(form, sheet);
|
||||
//updateWeeklyQuestions(form, new Date(2023,11 - 1,1));
|
||||
//mergeColumnsWithSameNames(sheetResults);
|
||||
}
|
||||
|
||||
function setNamesDropdownOptions(form, sheet) {
|
||||
var names = sheet.getRange("A4:A").getValues(); // Replace 'Sheet1' and 'A:A' with your sheet name and range respectively
|
||||
var colAFontWeights = sheet.getRange("A4:A").getFontWeights();
|
||||
|
||||
var flatList = names
|
||||
.flat()
|
||||
.map(function (name) {
|
||||
return normalizeName(name[0]);
|
||||
})
|
||||
.filter(String); // Flatten the array, normalize names, and remove any empty strings
|
||||
|
||||
var title = "Име, Фамилия";
|
||||
var item = form.getItems(FormApp.ItemType.LIST); // or FormApp.ItemType.LIST or MULTIPLE_CHOICE
|
||||
var multipleChoiceItem = item[0].asListItem(); // or .asMultipleChoiceItem()
|
||||
|
||||
var boldValues = [];
|
||||
for (var i = 0; i < colAFontWeights.length; i++) {
|
||||
if (colAFontWeights[i][0] === "bold") {
|
||||
boldValues.push(names[i][0]);
|
||||
}
|
||||
}
|
||||
var bulgarianOrder = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ";
|
||||
|
||||
function customBulgarianSort(a, b) {
|
||||
for (var i = 0; i < Math.min(a.length, b.length); i++) {
|
||||
var indexA = bulgarianOrder.indexOf(a[i]);
|
||||
var indexB = bulgarianOrder.indexOf(b[i]);
|
||||
|
||||
// Default behavior for characters not in the bulgarianOrder string
|
||||
if (indexA === -1 && indexB === -1) {
|
||||
if (a[i] < b[i]) return -1;
|
||||
if (a[i] > b[i]) return 1;
|
||||
}
|
||||
|
||||
if (indexA === -1) return 1;
|
||||
if (indexB === -1) return -1;
|
||||
if (indexA < indexB) return -1;
|
||||
if (indexA > indexB) return 1;
|
||||
}
|
||||
|
||||
if (a.length < b.length) return -1;
|
||||
if (a.length > b.length) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
boldValues.sort(customBulgarianSort);
|
||||
|
||||
multipleChoiceItem.setChoiceValues(boldValues);
|
||||
}
|
||||
|
||||
// Helper function to remove leading, trailing, and consecutive spaces
|
||||
function normalizeName(name) {
|
||||
if (typeof name !== "string") {
|
||||
return ""; // Return an empty string if the name is not a valid string
|
||||
}
|
||||
return name.split(" ").filter(Boolean).join(" ");
|
||||
}
|
||||
|
||||
function ReverseNames(names, destination = "D") {
|
||||
// Reverse the name order for each name
|
||||
var reversedNames = names.map(function (name) {
|
||||
var splitName = name[0].trim().split(" ");
|
||||
if (splitName.length === 2) {
|
||||
// Ensure there's a Lastname and Firstname to swap
|
||||
return [splitName[1] + " " + splitName[0]];
|
||||
} else {
|
||||
return [name[0]]; // Return the original name if it doesn't fit the "Lastname Firstname" format
|
||||
}
|
||||
});
|
||||
|
||||
// Write reversed names to column D
|
||||
sheet.getRange(destination + "4:" + destination + "" + (3 + reversedNames.length)).setValues(reversedNames);
|
||||
}
|
||||
|
||||
function updateWeeklyQuestions(form, forDate) {
|
||||
var items = form.getItems(FormApp.ItemType.CHECKBOX_GRID);
|
||||
|
||||
var today = forDate;
|
||||
var firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
var weeks = getWeeksInMonth(today.getMonth(), today.getFullYear());
|
||||
|
||||
var columns = [];
|
||||
columns.push("Не мога");
|
||||
var weekDays = ["пон", "вт", "ср", "четв", "пет", "съб"];
|
||||
|
||||
//Summer
|
||||
//for (var i = 8; i <= 18; i += 2) {
|
||||
// columns.push("(" + i + "ч-" + (i + 2) + "ч)");
|
||||
//Winter
|
||||
for (var i = 9; i <= 18; i += 1.5) {
|
||||
columns.push("" + formatTime(i) + "-" + formatTime(i + 1.5) + "");
|
||||
}
|
||||
|
||||
for (var i = 0; i < weeks.length; i++) {
|
||||
var week = weeks[i];
|
||||
// Skip weeks that started in the previous month
|
||||
if (week[0].getMonth() !== firstDayOfMonth.getMonth()) {
|
||||
continue;
|
||||
}
|
||||
console.log("Week from " + week[0].getDate());
|
||||
|
||||
var title = "Седмица " + (i + 1) + " (" + week[0].getDate() + "-" + week[5].getDate() + " " + getMonthName(week[0].getMonth()) + ")"; // Always represent Monday to Saturday
|
||||
if (week[5].getMonth() !== week[0].getMonth()) {
|
||||
title = "Седмица " + (i + 1) + " (" + week[0].getDate() + " " + getMonthName(week[0].getMonth()) + " - " + week[5].getDate() + " " + getMonthName(week[5].getMonth()) + ")"; // Always represent Monday to Saturday
|
||||
}
|
||||
if (i < items.length) {
|
||||
// Modify existing checkbox grid
|
||||
var checkboxGrid = items[i].asCheckboxGridItem();
|
||||
checkboxGrid.setTitle(title);
|
||||
checkboxGrid.setColumns(columns);
|
||||
checkboxGrid.setRows(weekDays);
|
||||
} else {
|
||||
// Create a new checkbox grid
|
||||
var checkboxGrid = form.addCheckboxGridItem();
|
||||
checkboxGrid.setTitle(title);
|
||||
checkboxGrid.setColumns(columns);
|
||||
checkboxGrid.setRows(weekDays);
|
||||
checkboxGrid.setRequired(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete extra checkbox grids
|
||||
for (var j = weeks.length; j < items.length; j++) {
|
||||
form.deleteItem(items[j]);
|
||||
}
|
||||
}
|
||||
|
||||
function getWeeksInMonth(month, year) {
|
||||
var weeks = [],
|
||||
firstDate = new Date(year, month, 1),
|
||||
lastDate = new Date(year, month + 1, 0);
|
||||
|
||||
// Find the first Monday of the month
|
||||
while (firstDate.getDay() !== 1) {
|
||||
firstDate.setDate(firstDate.getDate() + 1);
|
||||
}
|
||||
|
||||
var currentDate = new Date(firstDate);
|
||||
|
||||
while (currentDate <= lastDate) {
|
||||
var week = [];
|
||||
|
||||
// For 6 days (Monday to Saturday)
|
||||
for (var i = 0; i < 6; i++) {
|
||||
week.push(new Date(currentDate));
|
||||
currentDate.setDate(currentDate.getDate() + 1);
|
||||
}
|
||||
|
||||
currentDate.setDate(currentDate.getDate() + 1); //Sunday
|
||||
weeks.push(week);
|
||||
|
||||
// If we are already in the next month, break out of the loop
|
||||
if (currentDate.getMonth() !== month) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return weeks;
|
||||
}
|
||||
|
||||
function getMonthName(monthIndex) {
|
||||
var months = ["януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември"];
|
||||
return months[monthIndex];
|
||||
}
|
||||
|
||||
function formatTime(hourDecimal) {
|
||||
var hours = Math.floor(hourDecimal);
|
||||
var minutes = (hourDecimal - hours) * 60;
|
||||
if (minutes === 0) {
|
||||
return hours.toString().padStart(2, "0");
|
||||
}
|
||||
return hours.toString().padStart(2, "0") + ":" + minutes.toString().padStart(2, "0");
|
||||
}
|
||||
|
||||
function mergeColumnsWithSameNames(sheet) {
|
||||
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
|
||||
var uniqueHeaders = [...new Set(headers)]; // Get unique headers
|
||||
|
||||
for (var u = 0; u < uniqueHeaders.length; u++) {
|
||||
var currentHeader = uniqueHeaders[u];
|
||||
var columnsToMerge = [];
|
||||
|
||||
// Identify columns with the same name
|
||||
for (var i = 0; i < headers.length; i++) {
|
||||
if (headers[i] === currentHeader) {
|
||||
columnsToMerge.push(i + 1); // '+1' because column indices are 1-based
|
||||
}
|
||||
}
|
||||
|
||||
if (columnsToMerge.length > 1) {
|
||||
// If there's more than one column with the same name
|
||||
var sumData = [];
|
||||
for (var col of columnsToMerge) {
|
||||
var columnData = sheet.getRange(2, col, sheet.getLastRow() - 1).getValues(); // '-1' to exclude the header
|
||||
for (var j = 0; j < columnData.length; j++) {
|
||||
if (!sumData[j]) sumData[j] = [];
|
||||
sumData[j][0] = (sumData[j][0] || 0) + (columnData[j][0] || 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Write back summed data to the first column in the list
|
||||
sheet.getRange(2, columnsToMerge[0], sumData.length, 1).setValues(sumData);
|
||||
|
||||
// Delete the other duplicate columns
|
||||
for (var k = columnsToMerge.length - 1; k > 0; k--) {
|
||||
sheet.deleteColumn(columnsToMerge[k]);
|
||||
}
|
||||
|
||||
// Adjust headers array to reflect the deleted columns
|
||||
headers = headers.slice(0, columnsToMerge[1] - 1).concat(headers.slice(columnsToMerge[columnsToMerge.length - 1], headers.length));
|
||||
}
|
||||
}
|
||||
}
|
25
_doc/Message.md
Normal file
25
_doc/Message.md
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
1. Щандове. Предлагаме следното:
|
||||
|
||||
А) Да има известно разстояние между нас и щандовете. Целта е да оставим хората свободно да се доближат до количките и ако някой прояви интерес може да се приближим.
|
||||
|
||||
Б) Когато сме двама или трима може да стоим заедно. Ако сме четирима би било хубаво да се разделим по двама на количка и количките да са на известно разстояние една от друга.
|
||||
Моля вижте и прикачените снимки!
|
||||
|
||||
2. Безопасност. Нека се страем зад нас винаги да има защита или препятствие за недобронамерени хора.
|
||||
|
||||
3. Плакати. Моля при придвижване на количките да слагате плакатите така, че илюстрацията да се вижда, когато калъфа е сложен. Целта е снимките да не се търкат в количката, защото се повреждат.
|
||||
|
||||
4. Литература. При проявен интерес на чужд език, използвайте списанията и трактатите на други езици в папките.
|
||||
|
||||
5. График. Моля да ни изпратите вашите предпочитания до 23-то число на месеца. Линк към анкетата:
|
||||
https://docs.google.com/forms/d/e/1FAIpQLSdLpuTi0o9laOYmenGJetY6MJ-CmphD9xFS5ZVz_7ipOxNGUQ/viewform?usp=sf_link
|
||||
|
||||
6. Случки. Ако сте имали хубави случки на количките, моля пишете ни.
|
||||
|
||||
За други въпроси може да се обръщате към брат Янко Ванчев и брат Крейг Смит.
|
||||
|
||||
Много ви благодарим за хубавото сътрудничество и за вашата усърдна работа в службата с подвижните щандове в София! Пожелаваме ви много благословии и радост в този вид служба!
|
||||
|
||||
Ваши братя,
|
||||
Специално свидетелстване на обществени места в София
|
168
_doc/ToDo.md
Normal file
168
_doc/ToDo.md
Normal file
@ -0,0 +1,168 @@
|
||||
# - Authentication : Done
|
||||
# - Fix Location form :
|
||||
- store and generate transport
|
||||
- fix auto generation
|
||||
|
||||
- fix problem with showing Наташа Перчекли available on 7-th november from 10:00-12:30
|
||||
# - fix loading of availabiities in publisher page
|
||||
# - fix importing of availabilities from the last week, when the end is in the next month
|
||||
#? - fix availability start/end borders while searching, as adjasecent shifts are shown as available while they are not
|
||||
# - unit test proximity search for
|
||||
+ 'Елена Йедлинска',
|
||||
+ 'Джейми Лий Смит',
|
||||
+ 'Стела Стоянова'@ 9th november last shift
|
||||
+ 'Юрий Чулак' при импорт достъпностите са ВСЯКА сряда
|
||||
# - защо не се изтриват достъпностите при импорт? заюото не се взимаха от базата за да се итерират
|
||||
# - why are some availabilities imported as weekly : current/next month logic when importing in the current month
|
||||
- show weekly availabilities in calendar publisher list?
|
||||
|
||||
- importing schedule should create availability if not available. importing preferences deletes old availabilities.
|
||||
- add option (checkbox) if it is a family availability
|
||||
|
||||
- on calendar - when click on a publisher - show his availabilities and assihnments in a popup, with the option to move assingments to another shift - where there are free slots or inconfirmed slots.
|
||||
for each shift withing availability - show the current slots and allow to drag and drop to another shift. each shift has maximum 4 slots.
|
||||
|
||||
- прибиране/докаване на количките - да се импортира
|
||||
- fix month end not to last sunday, but to last day of the month in availabilities
|
||||
- да проверя файла с участия
|
||||
|
||||
Run `npm audit` for details.
|
||||
PS D:\DEV\workspace\next-cart-app\next-cart-app> npm update
|
||||
npm WARN deprecated graphql-import@0.7.1: GraphQL Import has been deprecated and merged into GraphQL Tools, so it will no longer get updates. Use GraphQL Tools instead to stay up-to-date! Check out https://www.graphql-tools.com/docs/migration-from-import for migration and https://the-guild.dev/blog/graphql-tools-v6 for new changes.
|
||||
npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
||||
npm WARN deprecated subscriptions-transport-ws@0.9.16: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md
|
||||
npm WARN deprecated graphql-tools@4.0.5: This package has been deprecated and now it only exports makeExecutableSchema.
|
||||
npm WARN deprecated And it will no longer receive updates.
|
||||
npm WARN deprecated We recommend you to migrate to scoped packages such as @graphql-tools/schema, @graphql-tools/utils and etc.
|
||||
npm WARN deprecated Check out https://www.graphql-tools.com to learn what package you should use instead
|
||||
|
||||
added 85 packages, removed 94 packages, changed 50 packages, and audited 1366 packages in 3m
|
||||
|
||||
---
|
||||
три цвята на назначенията: актуални, минали, без потвърждение/от назначенията/автоматични;
|
||||
|
||||
- color code shifts: yellow if 3 publishers, red if <=2 publishers, green if 4 publishers
|
||||
- for a publisher - view all available shfts where there are free slots and allow to move assignments to another shift
|
||||
|
||||
|
||||
- bulk edit for publishers - change type, target shifts.
|
||||
- edit publisher availabilities in grid - isWithTransport
|
||||
|
||||
After meeting with Fabio:
|
||||
- passed training cb
|
||||
- option to search for replacements only for my assignments (directly replace, or ask for help - email)
|
||||
-
|
||||
|
||||
+ see the whole schedule - talk with Yanko
|
||||
|
||||
- sign up
|
||||
|
||||
|
||||
shift reports - show my shifts, store the report to the shift and norify if report already exists.
|
||||
|
||||
!!! make word imports create availability as option during import - create availabilities as tentative and repeat them every month
|
||||
fix import - it adds it to the next day
|
||||
elena qdlinska is always created
|
||||
dariush availabilities are not imported
|
||||
fix availability repeat checks
|
||||
|
||||
|
||||
Упътване потребители:
|
||||
Ако искат винаги да са заедно - може да използват един имейл. Ако не - трябва да имат различни имейли.
|
||||
|
||||
|
||||
|
||||
Упътване отговорен брат:
|
||||
1 - провери всеки вестител за предпочитания/назначения (календара)
|
||||
2 - провери графика за изпуснати вестители - в червено, които не са на разположение за назначението си
|
||||
3 - провери графика за празни смени
|
||||
4 - провери за пропуснати вестители - без назначения за месеца
|
||||
5 - да провери транспорта
|
||||
|
||||
|
||||
|
||||
|
||||
Цялата програма - като от ПДФ.
|
||||
|
||||
меню: пон-петък
|
||||
|
||||
|
||||
"При лошо време"
|
||||
|
||||
да се добави: контакти - янко и крейг
|
||||
|
||||
чекбоксове,
|
||||
до края на месеца
|
||||
динамичен график: да могат да търсят заместници
|
||||
|
||||
Рубен да провери вестителите: дали са според програмата.
|
||||
|
||||
|
||||
2024.02.14:
|
||||
Янко:
|
||||
1. графика на всички. отделно меню.
|
||||
2. разрешение от общината. "разрешително". да има и админ за обновяване?
|
||||
3. линк местоположение
|
||||
4. местоположение - имена
|
||||
5. ipad - scroll na PDF-s 148
|
||||
6. списък с участници.
|
||||
7. отделен вид разположение "заместник"
|
||||
|
||||
Фабио:
|
||||
1. да може участника да види тези, които са на разопложение и да види телефоните.
|
||||
2. да изпращат а) на разположение б) на всички
|
||||
3. желани смени на месец - в "календар"
|
||||
4. да се импортират данните за назначение.
|
||||
|
||||
Краси
|
||||
1. Push notifications
|
||||
|
||||
|
||||
|
||||
-- Bugs:
|
||||
- import all assignments from WORD
|
||||
- respect repetition of availabilities
|
||||
- new api to set availabilities per day (deleting the old ones, based on time periods array)
|
||||
- failover for the server
|
||||
|
||||
|
||||
Fabio:
|
||||
- може да оставим само тези, които са въвели, но от другия месец, за да можем този ако има проблеми да ги оправим. да не стане така, че не приемаме друг начин, а нещо не работи
|
||||
- можем да тестваме с 10=20 човека, и ако няма прооблеми да пратим до всички още този месец.
|
||||
- списък с видове назначение:
|
||||
Вестител
|
||||
Бетелит
|
||||
Редовен Пионер
|
||||
Специален Пионер
|
||||
Мисионер
|
||||
Пътуваща служба
|
||||
|
||||
-------------------------------------------------------
|
||||
|
||||
Янко:
|
||||
1. графика на всички. отделно меню.
|
||||
2. разрешение от общината. "разрешително". да има и админ за обновяване?
|
||||
3. линк местоположение
|
||||
4. местоположение - имена
|
||||
5. ipad - scroll na PDF-s 148
|
||||
6. списък с участници.
|
||||
7. отделен вид разположение "заместник"
|
||||
|
||||
Фабио:
|
||||
1. да може участника да види тези, които са на разопложение и да види телефоните.
|
||||
2. да изпращат а) на разположение б) на всички
|
||||
3. желани смени на месец - в "календар"
|
||||
4. да се импортират данните за назначение.
|
||||
|
||||
Краси
|
||||
1. Push notifications
|
||||
|
||||
--
|
||||
Проблеми: някои използват един и същи имейл - няма как да въведат графика и на двамата.
|
||||
|
||||
- да оправя дневните разположения
|
||||
- да се взимат в предвид повтарящите се разопложения
|
||||
|
||||
--
|
||||
- да оправя дневните разположения
|
||||
- да се взимат в предвид повтарящите се разопложения
|
53
_doc/additionalNotes.mb
Normal file
53
_doc/additionalNotes.mb
Normal file
@ -0,0 +1,53 @@
|
||||
# GIT clone last commit to current folder:
|
||||
git clone --depth 1 https://git.d-popov.com/popov/next-cart-app.git .
|
||||
|
||||
# git clone only /next-cart-app subfolder (the nextjs app)
|
||||
# [git init]
|
||||
# [git remote add origin https://git.d-popov.com/popov/next-cart-app.git]
|
||||
git config core.sparseCheckout true
|
||||
echo "next-cart-app/" >> .git/info/sparse-checkout
|
||||
git clone --depth 1 --branch master https://git.d-popov.com/popov/next-cart-app.git .
|
||||
|
||||
#git fetch --depth=1 origin master
|
||||
#git checkout master
|
||||
#git reset --hard HEAD
|
||||
|
||||
|
||||
|
||||
#Build the Docker Image:
|
||||
docker-compose build
|
||||
#Tag the Image for the Local Registry:
|
||||
docker tag pw-cart 192.168.0.10:5000/pw-cart
|
||||
#Push the Image to the Local Registry
|
||||
docker push 192.168.0.10:5000/pw-cart
|
||||
|
||||
|
||||
# deploy to azure XXX
|
||||
mkdir app2
|
||||
git clone https://git.d-popov.com/popov/next-cart-app.git app2
|
||||
mv app2 app/
|
||||
rm -rf app2
|
||||
# copy to tmp: #rm -rf /tmp/clone && git clone https://git.d-popov.com/popov/next-cart-app.git /tmp/clone
|
||||
# copy to /app: #rm -rf /app/* && cp -R /tmp/clone/next-cart-app/* /app/
|
||||
# cleanup #rm -rf /tmp/clone
|
||||
#[!opt] build: # npm cache clean --force && rm -rf /app/node_modules /app/package-lock.json && npm --silent --prefix /app install /app
|
||||
# cd /app && npm install
|
||||
|
||||
|
||||
####################### GIT ######################
|
||||
# git remove file from repo (ignore and delete)
|
||||
gitignore > + *.zip
|
||||
git commit -m "Ignore all .zip files"
|
||||
--
|
||||
git rm --cached '*.zip'
|
||||
git commit -m "Remove tracked .zip files from repository"
|
||||
git push
|
||||
|
||||
|
||||
## git clean/optimize
|
||||
git gc
|
||||
git prune
|
||||
git repack -ad
|
||||
#!Expire and prune older reflog entries to reduce the number of objects retained for undo purposes.
|
||||
#git reflog expire --expire=now --all
|
||||
#git gc --prune=now
|
78
_doc/auth/auth.md
Normal file
78
_doc/auth/auth.md
Normal file
@ -0,0 +1,78 @@
|
||||
location /authelia {
|
||||
internal;
|
||||
set $upstream_authelia http://authelia:9091/api/verify;
|
||||
proxy_pass_request_body off;
|
||||
proxy_pass $upstream_authelia;
|
||||
proxy_set_header Content-Length "";
|
||||
|
||||
# Timeout if the real server is dead
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
client_body_buffer_size 128k;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 4 32k;
|
||||
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 240;
|
||||
proxy_send_timeout 240;
|
||||
proxy_connect_timeout 240;
|
||||
}
|
||||
|
||||
location / {
|
||||
set $upstream_app $forward_scheme://$server:$port;
|
||||
proxy_pass $upstream_app;
|
||||
|
||||
auth_request /authelia;
|
||||
auth_request_set $target_url https://$http_host$request_uri;
|
||||
auth_request_set $user $upstream_http_remote_user;
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
proxy_set_header Remote-User $user;
|
||||
proxy_set_header Remote-Email $email;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
|
||||
error_page 401 =302 https://auth.d-popov.com/?rd=$target_url;
|
||||
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
||||
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 360;
|
||||
proxy_send_timeout 360;
|
||||
proxy_connect_timeout 360;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection upgrade;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 64 256k;
|
||||
|
||||
set_real_ip_from 172.18.0.0/16;
|
||||
set_real_ip_from 172.19.0.0/16;
|
||||
real_ip_header CF-Connecting-IP;
|
||||
real_ip_recursive on;
|
||||
|
||||
}
|
25
_doc/auth/authelia-authrequest.conf
Normal file
25
_doc/auth/authelia-authrequest.conf
Normal file
@ -0,0 +1,25 @@
|
||||
## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
|
||||
auth_request /authelia;
|
||||
|
||||
## Set the $target_url variable based on the original request.
|
||||
|
||||
## Comment this line if you're using nginx without the http_set_misc module.
|
||||
set_escape_uri $target_url $scheme://$http_host$request_uri;
|
||||
|
||||
## Uncomment this line if you're using NGINX without the http_set_misc module.
|
||||
# set $target_url $scheme://$http_host$request_uri;
|
||||
|
||||
## Save the upstream response headers from Authelia to variables.
|
||||
auth_request_set $user $upstream_http_remote_user;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
auth_request_set $name $upstream_http_remote_name;
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
|
||||
## Inject the response headers from the variables into the request made to the backend.
|
||||
proxy_set_header Remote-User $user;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
proxy_set_header Remote-Name $name;
|
||||
proxy_set_header Remote-Email $email;
|
||||
|
||||
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
|
||||
error_page 401 =302 https://auth.d-popov.com/?redirect=$target_url;
|
36
_doc/auth/authelia-location.conf
Normal file
36
_doc/auth/authelia-location.conf
Normal file
@ -0,0 +1,36 @@
|
||||
set $upstream_authelia http://authelia:9091/api/verify;
|
||||
|
||||
## Virtual endpoint created by nginx to forward auth requests.
|
||||
location /authelia {
|
||||
## Essential Proxy Configuration
|
||||
internal;
|
||||
proxy_pass $upstream_authelia;
|
||||
|
||||
## Headers
|
||||
## The headers starting with X-* are required.
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
proxy_set_header X-Forwarded-Method $request_method;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header Connection "";
|
||||
|
||||
## Basic Proxy Configuration
|
||||
proxy_pass_request_body off;
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 4 32k;
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
## Advanced Proxy Configuration
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 240;
|
||||
proxy_send_timeout 240;
|
||||
proxy_connect_timeout 240;
|
||||
}
|
7
_doc/auth/nginx-protected-app-advanced-tab.conf
Normal file
7
_doc/auth/nginx-protected-app-advanced-tab.conf
Normal file
@ -0,0 +1,7 @@
|
||||
include /snippets/authelia-location.conf;
|
||||
|
||||
location / {
|
||||
include /snippets/proxy.conf;
|
||||
include /snippets/authelia-authrequest.conf;
|
||||
proxy_pass $forward_scheme://$server:$port;
|
||||
}
|
35
_doc/auth/proxy.conf
Normal file
35
_doc/auth/proxy.conf
Normal file
@ -0,0 +1,35 @@
|
||||
## Headers
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
||||
proxy_set_header X-Forwarded-Ssl on;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
## Basic Proxy Configuration
|
||||
client_body_buffer_size 128k;
|
||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead.
|
||||
proxy_redirect http:// $scheme://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_cache_bypass $cookie_session;
|
||||
proxy_no_cache $cookie_session;
|
||||
proxy_buffers 64 256k;
|
||||
|
||||
## Trusted Proxies Configuration
|
||||
## Please read the following documentation before configuring this:
|
||||
## https://www.authelia.com/integration/proxies/nginx/#trusted-proxies
|
||||
# set_real_ip_from 10.0.0.0/8;
|
||||
# set_real_ip_from 172.16.0.0/12;
|
||||
# set_real_ip_from 192.168.0.0/16;
|
||||
# set_real_ip_from fc00::/7;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
## Advanced Proxy Configuration
|
||||
send_timeout 5m;
|
||||
proxy_read_timeout 360;
|
||||
proxy_send_timeout 360;
|
||||
proxy_connect_timeout 360;
|
178
_doc/notes.mb
Normal file
178
_doc/notes.mb
Normal file
@ -0,0 +1,178 @@
|
||||
Nginx:
|
||||
Email: admin@example.com
|
||||
Password: changeme
|
||||
|
||||
google auth:
|
||||
# // owner: dobromir.popov@gmail.com | Специално Свидетелстване София
|
||||
# // https://console.cloud.google.com/apis/credentials/oauthclient/926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com?project=grand-forge-108716
|
||||
|
||||
# to spin up devcontainer:
|
||||
# ensure we have docker:
|
||||
apt-get update && apt-get install -y docker.io
|
||||
|
||||
docker build -t dev-next-cart-app-img .devcontainer
|
||||
docker run -d -v /path/to/your/project:/workspace --name dev-next-cart-app dev-next-cart-app-img
|
||||
docker exec -it dev-next-cart-app /bin/bash
|
||||
|
||||
##### ----------------- compose/deploy ----------------- ###
|
||||
# install docker if inside docker (vscode-server)# apt-get update && apt-get install -y docker.io
|
||||
# .10 > /mnt/apps/DEV/SSS/next-cart-app/next-cart-app/
|
||||
#.11 > cd /mnt/storage/DEV/workspace/repos/git.d-popov.com/next-cart-app/next-cart-app
|
||||
|
||||
# using dockerfile and image:
|
||||
docker build -t jwpw:latest -f _deploy/prod.Dockerfile .
|
||||
# or ----------------------
|
||||
docker build -t jwpw:test -f _deploy/testBuild.Dockerfile .
|
||||
|
||||
#---- or (testing 2 step docker image)
|
||||
docker build -t docker.d-popov.com/jwpw:test -f _deploy/testBuild.Dockerfile .
|
||||
docker run -p 3000:3000 docker.d-popov.com/jwpw:test
|
||||
docker run -it --name browse-jwse --entrypoint sh docker.d-popov.com/jwpw:test
|
||||
docker rm browse-jwpw
|
||||
|
||||
--- TEST
|
||||
docker build -t docker.d-popov.com/jwpw:test -f _deploy/testBuild.Dockerfile .
|
||||
docker push docker.d-popov.com/jwpw:test
|
||||
|
||||
--LATEST/
|
||||
cd /mnt/storage/DEV/workspace/repos/git.d-popov.com/next-cart-app/next-cart-app
|
||||
docker build -t docker.d-popov.com/jwpw:latest -f _deploy/prod.Dockerfile .
|
||||
docker tag docker.d-popov.com/jwpw:latest docker.d-popov.com/jwpw:0.9.94
|
||||
docker push docker.d-popov.com/jwpw:latest
|
||||
docker push docker.d-popov.com/jwpw:0.9.94
|
||||
|
||||
#---
|
||||
|
||||
docker tag jwpw:latest docker.d-popov.com/jwpw:latest
|
||||
docker push docker.d-popov.com/jwpw:latest # docker push registry.example.com/username/my-image:latest #docker login docker.d-popov.com
|
||||
# Tag the image for your local Docker registry
|
||||
docker tag jwpw:0.9 docker.d-popov.com/jwpw:0.9
|
||||
# deploy
|
||||
docker pull docker.d-popov.com/jwpw:latest
|
||||
docker run -p local-port:container-port docker.d-popov.com/jwpw:latest
|
||||
|
||||
|
||||
# docker-compose
|
||||
docker-compose up --build
|
||||
!
|
||||
docker-compose -f test.11.yml up --build # build test on .11:5002
|
||||
docker-compose -f deploy.azure.yml up --build
|
||||
|
||||
# OR git clone ------------------!!!
|
||||
apk add git && rm -rf /tmp/clone
|
||||
apk add git && git clone --depth 1 https://popov:6A5FvrV6jfF2BP@git.d-popov.com/popov/next-cart-app.git /tmp/clone && cp -Rf /tmp/clone/next-cart-app/* /app/
|
||||
# if cloned # cd /tmp/clone && git pull --depth 1
|
||||
cp -Rf /tmp/clone/next-cart-app/* /app/ && cd /app
|
||||
cp -Rf /tmp/clone/next-cart-app/* /mnt/docker_volumes/pw/app/
|
||||
rm -rf /tmp/clone
|
||||
npm cache clean --force && rm -rf /app/node_modules /app/package-lock.json
|
||||
NODE_OPTIONS="--max-old-space-size=4096" npm install
|
||||
|
||||
npm install && npm install -g dotenv-cli && npx prisma generate
|
||||
npm run test
|
||||
|
||||
# OR
|
||||
# copy with SSH
|
||||
# remote: #sudo chown -R azureuser:azureuser /mnt/docker_volumes/pw/app/
|
||||
# local: #rsync -avz ./node_modules/ azureuser@172.160.240.73:/mnt/docker_volumes/pw/app/node_modules/
|
||||
|
||||
# OR (2 cmd deploy PROD)
|
||||
# npm run build
|
||||
rsync -avz --include=".*" .next \
|
||||
.env .env.production \
|
||||
components \
|
||||
pages \
|
||||
prisma \
|
||||
src \
|
||||
styles \
|
||||
package.json \
|
||||
package-lock.json \
|
||||
server.js \
|
||||
azureuser@172.160.240.73:/mnt/docker_volumes/pw/app/
|
||||
|
||||
# or DOCKERFILE
|
||||
docker build -t jw-cart -f prod.Dockerfile .
|
||||
docker build -t jw-cart-prod -f testBuild.Dockerfile .
|
||||
|
||||
#build
|
||||
npm run build
|
||||
|
||||
#install next
|
||||
npm install -g next
|
||||
next build
|
||||
next start
|
||||
## ------------------------------- dev -----------------------------------###
|
||||
|
||||
|
||||
# aider:
|
||||
export OPENAI_API_KEY=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 # personal
|
||||
export OPENAI_API_KEY=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 # dev-bro
|
||||
|
||||
# -------------update PRISMA schema/sync database ------------------------ #
|
||||
# prisma migrate dev --create-only
|
||||
npx prisma generate
|
||||
npx prisma migrate dev --name fix_nextauth_schema --create-only
|
||||
>Prisma Migrate created the following migration without applying it 20231214163235_fix_nextauth_schema
|
||||
>You can now edit it and apply it by running "prisma migrate dev"
|
||||
|
||||
# #production/deploy: npx prisma migrate deploy
|
||||
## Reintrospect: If you have a database that's in the desired state, but your Prisma schema is out of date, you can use prisma db pull to introspect the database and update your Prisma schema to match the current state of the database.
|
||||
npx prisma generate
|
||||
|
||||
# mark migration as applied:
|
||||
npx prisma migrate resolve --applied 20240201214719_assignment_add_repeat_frequency
|
||||
|
||||
# update prisma package
|
||||
npm i prisma@latest
|
||||
npm i @prisma/client@latest
|
||||
|
||||
npx prisma migrate dev --schema "mysql://cart:cart2023@192.168.0.10:3306/cart_dev" # -- does not work
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##########################################
|
||||
# yml leave the container running:
|
||||
command: sh -c "npm run test; tail -f /dev/null"
|
||||
|
||||
|
||||
|
||||
|
||||
fix build errors:
|
||||
cd path\to\your\project
|
||||
--
|
||||
rmdir /s /q node_modules
|
||||
del package-lock.json
|
||||
npm install
|
||||
--
|
||||
Remove-Item -Recurse -Force node_modules
|
||||
Remove-Item package-lock.json
|
||||
npm install
|
||||
|
||||
|
||||
# -- mysql
|
||||
# fix
|
||||
mysql -u root -pi4966cWBtP3xJ7BLsbsgo93C8Q5262
|
||||
--
|
||||
mysqld_safe --skip-grant-tables &
|
||||
mysql -u root
|
||||
FLUSH PRIVILEGES;
|
||||
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('i4966cWBtP3xJ7BLsbsgo93C8Q5262');
|
||||
GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'%' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9' WITH GRANT OPTION;
|
||||
GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'172.22.0.3' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9' WITH GRANT OPTION;
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
exit;
|
||||
|
||||
|
||||
#Install depcheck:
|
||||
npm install --save-dev depcheck
|
||||
npx depcheck
|
||||
npx depcheck --detailed
|
||||
|
||||
#Check for Package Updates
|
||||
npm install -g npm-check-updates
|
||||
ncu
|
||||
ncu -u
|
Reference in New Issue
Block a user