Compare commits

..
23 Commits
Author SHA1 Message Date
theis.gaedigk 5759666ef7 Merge branch 'dev' into host 2026-07-15 15:41:10 +02:00
theis.gaedigk 929ec5ef10 fix: Fix issue/ticket #17 2026-07-15 15:40:08 +02:00
theis.gaedigk 67c704009e refactored loan code creation function 2026-05-13 19:42:54 +02:00
theis.gaedigk 831de8b610 added new loan code function - NOT TESTED YET 2026-05-13 14:04:12 +02:00
theis.gaedigk fd43e84c0c refactored code 2026-05-11 22:40:34 +02:00
theis.gaedigk 1ce8d33b0d pulled naas 2026-05-09 23:32:12 +02:00
theis.gaedigk 3ff31ecbf6 Merge branch 'dev' into host 2026-05-09 11:39:26 +02:00
theis.gaedigk c48da71cd5 improved translation 2026-05-09 11:37:44 +02:00
theis.gaedigk 8e35e81e8f Fixed bug: #16 2026-05-09 11:35:13 +02:00
theis.gaedigk 95aae1c050 cleaned changelog 2026-05-01 13:41:30 +02:00
theis.gaedigk 3f910f937b edited port on nginx config 2026-05-01 12:55:29 +02:00
theis.gaedigk 3ed6121a0b fixed version infos 2026-05-01 12:47:21 +02:00
theis.gaedigk 5d9e965597 fixed docker compose 2026-05-01 12:39:32 +02:00
theis.gaedigk e296de27ef Merge branch 'dev' into host 2026-05-01 12:35:45 +02:00
theis.gaedigk 5c7a96912b Merge branch 'dev' into debian12 2026-04-18 15:00:51 +02:00
theis.gaedigk 195f270064 Merge branch 'dev' into debian12 2026-02-22 23:46:35 +01:00
theis.gaedigk 3d592c5c76 Merge branch 'dev' into debian12 2026-02-22 23:44:46 +01:00
theis.gaedigk 08104d32db Merge branch 'dev' into debian12 2026-02-20 16:30:34 +01:00
theis.gaedigk cc7c024892 Merge branch 'dev' into debian12 2026-02-07 17:48:44 +01:00
theis.gaedigk 3eb452aeab fixed version 2026-02-07 17:41:09 +01:00
theis.gaedigk f46a654184 Merge branch 'dev' into debian12 2026-02-07 17:40:47 +01:00
theis.gaedigk 863409aed9 Merge branch 'dev' into debian12 2026-02-04 13:47:04 +01:00
theis.gaedigk 052137a697 removed ports 2026-02-01 15:50:52 +01:00
18 changed files with 214 additions and 184 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ server {
} }
location /backend/ { location /backend/ {
proxy_pass http://demo_borrow_system-backend_v2:8004/; proxy_pass http://borrow_system-backend_v2:8004/;
} }
location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
+2
View File
@@ -16,6 +16,7 @@ import { Flex } from "@chakra-ui/react";
import { Footer } from "./components/footer/Footer"; import { Footer } from "./components/footer/Footer";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { API_BASE } from "@/config/api.config"; import { API_BASE } from "@/config/api.config";
import { ContactPage } from "./pages/ContactPage";
const queryClient = new QueryClient(); const queryClient = new QueryClient();
@@ -80,6 +81,7 @@ function App() {
<Route path="/" element={<HomePage />} /> <Route path="/" element={<HomePage />} />
<Route path="/my-loans" element={<MyLoansPage />} /> <Route path="/my-loans" element={<MyLoansPage />} />
<Route path="/landingpage" element={<Landingpage />} /> <Route path="/landingpage" element={<Landingpage />} />
<Route path="/contact" element={<ContactPage />} />
</Route> </Route>
<Route path="/login" element={<LoginPage />} /> <Route path="/login" element={<LoginPage />} />
+22
View File
@@ -23,6 +23,7 @@ import {
MoreVertical, MoreVertical,
Languages, Languages,
Table, Table,
ContactRound,
} from "lucide-react"; } from "lucide-react";
import { useUserContext } from "@/states/Context"; import { useUserContext } from "@/states/Context";
import { useState } from "react"; import { useState } from "react";
@@ -155,6 +156,16 @@ export const Header = () => {
</HStack> </HStack>
} }
/> />
<Menu.Item
value="contact"
onSelect={() => navigate("/contact", { replace: true })}
children={
<HStack gap={3}>
<ContactRound size={16} />
<Text as="span">{t("contact")}</Text>
</HStack>
}
/>
<Menu.Separator /> <Menu.Separator />
<Menu.Item <Menu.Item
value="logout" value="logout"
@@ -287,6 +298,17 @@ export const Header = () => {
</HStack> </HStack>
</Button> </Button>
</a> </a>
<Button
variant={"outline"}
onClick={() => navigate("/contact", { replace: true })}
>
<HStack gap={2}>
<ContactRound size={18} />
<Text as="span">{t("contact")}</Text>
</HStack>
</Button>
<Button onClick={logout} variant="outline" colorScheme="red"> <Button onClick={logout} variant="outline" colorScheme="red">
<HStack gap={2}> <HStack gap={2}>
<LogOut size={18} /> <LogOut size={18} />
+111
View File
@@ -0,0 +1,111 @@
import {
Field,
Textarea,
Button,
Alert,
Container,
Text,
VStack,
Spinner,
} from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import { API_BASE } from "@/config/api.config";
import Cookies from "js-cookie";
import { Header } from "@/components/Header";
interface Alert {
type: "info" | "warning" | "success" | "error" | "neutral";
headline: string;
text: string;
}
export const ContactPage = () => {
const { t } = useTranslation();
const [message, setMessage] = useState("");
const [isSending, setIsSending] = useState(false);
const [alert, setAlert] = useState<Alert | null>(null);
const sendMessage = async () => {
setIsSending(true);
if (message.trim() === "") {
setAlert({
type: "error",
headline: t("contactPage_messageErrorHeadline"),
text: t("contactPage_messageErrorText2"),
});
setIsSending(false);
return;
}
// Logic to send the message
const result = await fetch(`${API_BASE}/api/users/contact`, {
method: "POST",
headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ message }),
});
if (result.ok) {
setAlert({
type: "success",
headline: t("contactPage_successHeadline"),
text: t("contactPage_successText"),
});
setMessage("");
} else if (result.status === 503) {
setAlert({
type: "error",
headline: t("serviceDeactivatedHeadline"),
text: t("contactPage_serviceDeactivatedText"),
});
} else {
setAlert({
type: "error",
headline: t("contactPage_errorHeadline"),
text: t("contactPage_errorText"),
});
}
setIsSending(false);
};
return (
<Container className="px-6 sm:px-8 pt-10">
<Header />
<Field.Root invalid={message === ""}>
<Field.Label>
<Text>{t("contactPage_messageDescription")}</Text>
<Field.RequiredIndicator />
</Field.Label>
<Textarea
placeholder={t("contactPage_messagePlaceholder")}
variant="subtle"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
{message === "" && (
<Field.ErrorText>{t("contactPage_messageErrorText")}</Field.ErrorText>
)}
</Field.Root>
{alert && (
<Alert.Root status={alert.type}>
<Alert.Indicator />
<Alert.Content>
<Alert.Title>{alert.headline}</Alert.Title>
<Alert.Description>{alert.text}</Alert.Description>
</Alert.Content>
</Alert.Root>
)}
{isSending && (
<VStack colorPalette="teal">
<Spinner color="colorPalette.600" />
<Text color="colorPalette.600">{t("loading")}</Text>
</VStack>
)}
<Button onClick={sendMessage}>{t("contactPage_sendButton")}</Button>
</Container>
);
};
+24 -6
View File
@@ -121,10 +121,28 @@ export const MyLoansPage = () => {
const formatDate = (iso: string | null) => { const formatDate = (iso: string | null) => {
if (!iso) return "-"; if (!iso) return "-";
const m = iso.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/); const date = new Date(iso);
if (!m) return iso; if (isNaN(date.getTime())) return iso;
const [, y, M, d, h, min] = m; return date.toLocaleString("de-DE", {
return `${d}.${M}.${y} ${h}:${min}`; timeZone: "Europe/Berlin",
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
});
};
const dateAndTime = (isISO: boolean) => {
const date = new Date();
if (isISO) {
return date.toISOString();
}
if (!isISO) {
return date;
}
}; };
const handleTakeAction = async (loanCode: string) => { const handleTakeAction = async (loanCode: string) => {
@@ -151,7 +169,7 @@ export const MyLoansPage = () => {
setLoans((prev) => setLoans((prev) =>
prev.map((loan) => prev.map((loan) =>
loan.loan_code === loanCode loan.loan_code === loanCode
? { ...loan, take_date: new Date().toISOString() } ? { ...loan, take_date: dateAndTime(true) }
: loan, : loan,
), ),
); );
@@ -191,7 +209,7 @@ export const MyLoansPage = () => {
setLoans((prev) => setLoans((prev) =>
prev.map((loan) => prev.map((loan) =>
loan.loan_code === loanCode loan.loan_code === loanCode
? { ...loan, returned_date: new Date().toISOString() } ? { ...loan, returned_date: dateAndTime(true) }
: loan, : loan,
), ),
); );
+2 -2
View File
@@ -60,7 +60,7 @@
"sure-delete-loan-2": "Für den Admin bleibt sie weiterhin sichtbar.", "sure-delete-loan-2": "Für den Admin bleibt sie weiterhin sichtbar.",
"delete": "Löschen", "delete": "Löschen",
"change-language": "Sprache ändern", "change-language": "Sprache ändern",
"timezone-info": "Die angezeigten Daten und Uhrzeiten werden in deutscher Zeitzone dargestellt und müssen auch so eingegeben werden.", "timezone-info": "Die angezeigten Daten und Uhrzeiten werden in deutscher Zeitzone dargestellt und müssen auch so eingegeben werden. Das gesamte System ist auf die deutsche Zeitzone eingestellt.",
"optional-note": "Optionale Notiz", "optional-note": "Optionale Notiz",
"note": "Notiz", "note": "Notiz",
"user-info-desc": "Hier können Sie Ihre persönlichen Informationen einsehen und das Passwort ändern. Falls Sie weitere Änderungen benötigen, wenden Sie sich bitte an einen Administrator.", "user-info-desc": "Hier können Sie Ihre persönlichen Informationen einsehen und das Passwort ändern. Falls Sie weitere Änderungen benötigen, wenden Sie sich bitte an einen Administrator.",
@@ -68,7 +68,7 @@
"admin-status": "Admin-Status", "admin-status": "Admin-Status",
"first-name": "Vorname", "first-name": "Vorname",
"last-name": "Nachname", "last-name": "Nachname",
"app-title": "Ausleihsystem (demo)", "app-title": "Ausleihsystem",
"last-borrowed-person": "Zuletzt ausgeliehen von", "last-borrowed-person": "Zuletzt ausgeliehen von",
"currently-borrowed-by": "Derzeit ausgeliehen von", "currently-borrowed-by": "Derzeit ausgeliehen von",
"back": "Zurückgehen", "back": "Zurückgehen",
+2 -2
View File
@@ -60,7 +60,7 @@
"sure-delete-loan-2": "It will remain visible to the admin.", "sure-delete-loan-2": "It will remain visible to the admin.",
"delete": "Delete", "delete": "Delete",
"change-language": "Change language", "change-language": "Change language",
"timezone-info": "The displayed dates and times are shown in Berlin timezone and must also be entered as such.", "timezone-info": "The displayed dates and times are shown in Berlin timezone and must also be entered as such. The entire system is set to Berlin timezone.",
"optional-note": "Optional note", "optional-note": "Optional note",
"note": "Note", "note": "Note",
"user-info-desc": "Here you can view your personal information and change your password. If you need to make further changes, please contact an administrator.", "user-info-desc": "Here you can view your personal information and change your password. If you need to make further changes, please contact an administrator.",
@@ -68,7 +68,7 @@
"admin-status": "Admin status", "admin-status": "Admin status",
"first-name": "First name", "first-name": "First name",
"last-name": "Last name", "last-name": "Last name",
"app-title": "Borrow System (demo)", "app-title": "Borrow System",
"last-borrowed-person": "Last borrowed by", "last-borrowed-person": "Last borrowed by",
"currently-borrowed-by": "Currently borrowed by", "currently-borrowed-by": "Currently borrowed by",
"back": "Go back", "back": "Go back",
+1 -1
View File
@@ -14,7 +14,7 @@ server {
} }
location /backend/ { location /backend/ {
proxy_pass http://demo_borrow_system-backend_v2:8102/; proxy_pass http://borrow_system-backend_v2:8102/;
} }
location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
+3 -3
View File
@@ -1,11 +1,11 @@
{ {
"backend-info": { "backend-info": {
"version": "v2.2 (demo)" "version": "v2.2"
}, },
"frontend-info": { "frontend-info": {
"version": "v2.2 (demo)" "version": "v2.2"
}, },
"admin-panel-info": { "admin-panel-info": {
"version": "v1.4 (demo)" "version": "v1.4"
} }
} }
@@ -12,7 +12,7 @@ const pool = mysql
.promise(); .promise();
export const getAllLoans = async () => { export const getAllLoans = async () => {
const [rows] = await pool.query("SELECT * FROM loans"); const [rows] = await pool.query("SELECT * FROM loans WHERE deleted_admin = 0;");
return { success: true, data: rows }; return { success: true, data: rows };
}; };
@@ -29,14 +29,14 @@ export const createUser = async (
}; };
export const deleteUserById = async (userId) => { export const deleteUserById = async (userId) => {
const [result] = await pool.query("DELETE FROM users WHERE id = ? AND secret_user = false", [userId]); const [result] = await pool.query("DELETE FROM users WHERE id = ?", [userId]);
if (result.affectedRows > 0) return { success: true }; if (result.affectedRows > 0) return { success: true };
return { success: false }; return { success: false };
}; };
export const changePassword = async (username, newPassword) => { export const changePassword = async (username, newPassword) => {
const [result] = await pool.query( const [result] = await pool.query(
"UPDATE users SET password = ?, entry_updated_at = NOW() WHERE username = ? AND secret_user = false", "UPDATE users SET password = ?, entry_updated_at = NOW() WHERE username = ?",
[newPassword, username], [newPassword, username],
); );
if (result.affectedRows > 0) return { success: true }; if (result.affectedRows > 0) return { success: true };
@@ -52,7 +52,7 @@ export const editUserById = async (
is_admin, is_admin,
) => { ) => {
const [result] = await pool.query( const [result] = await pool.query(
"UPDATE users SET first_name = ?, last_name = ?, role = ?, email = ?, is_admin = ?, entry_updated_at = NOW() WHERE id = ? AND secret_user = false", "UPDATE users SET first_name = ?, last_name = ?, role = ?, email = ?, is_admin = ?, entry_updated_at = NOW() WHERE id = ?",
[first_name, last_name, role, email, is_admin, userId], [first_name, last_name, role, email, is_admin, userId],
); );
if (result.affectedRows > 0) return { success: true }; if (result.affectedRows > 0) return { success: true };
@@ -61,7 +61,7 @@ export const editUserById = async (
export const getAllUsers = async () => { export const getAllUsers = async () => {
const [result] = await pool.query( const [result] = await pool.query(
"SELECT id, username, first_name, last_name, role, email, is_admin, entry_created_at, entry_updated_at FROM users WHERE secret_user = false", "SELECT id, username, first_name, last_name, role, email, is_admin, entry_created_at, entry_updated_at FROM users",
); );
if (result.length > 0) return { success: true, data: result }; if (result.length > 0) return { success: true, data: result };
return { success: false }; return { success: false };
@@ -69,7 +69,7 @@ export const getAllUsers = async () => {
export const getUserById = async (userId) => { export const getUserById = async (userId) => {
const [rows] = await pool.query( const [rows] = await pool.query(
"SELECT id, username, first_name, last_name, role, email, is_admin FROM users WHERE id = ? AND secret_user = false", "SELECT id, username, first_name, last_name, role, email, is_admin FROM users WHERE id = ?",
[userId], [userId],
); );
if (rows.length === 0) { if (rows.length === 0) {
-8
View File
@@ -119,14 +119,6 @@ export const setTakeDateV2 = async (loanCode) => {
return { message: "Failed to set take date", success: false }; return { message: "Failed to set take date", success: false };
}; };
export const getAllLoansV2 = async () => {
const [result] = await pool.query("SELECT * FROM loans;");
if (result.length > 0) {
return { success: true, data: result };
}
return { success: false };
};
export const openDoor = async (doorKey) => { export const openDoor = async (doorKey) => {
const [result] = await pool.query( const [result] = await pool.query(
"SELECT safe_nr, id FROM items WHERE door_key = ?;", "SELECT safe_nr, id FROM items WHERE door_key = ?;",
@@ -63,11 +63,9 @@ export const createLoanInDatabase = async (
}; };
} }
const itemNames = itemIds const itemNames = itemIds.map(
.map( (id) => itemsRows.find((r) => Number(r.id) === Number(id)).item_name,
(id) => itemsRows.find((r) => Number(r.id) === Number(id))?.item_name, );
)
.filter(Boolean);
// Build lockers array (unique, only 2-digit numbers from safe_nr) // Build lockers array (unique, only 2-digit numbers from safe_nr)
const lockers = [ const lockers = [
@@ -109,27 +107,24 @@ export const createLoanInDatabase = async (
}; };
} }
// Generate unique loan_code (retry a few times) let index = false;
let loanCode = null; let candidate;
for (let i = 0; i < 6; i++) { let loanCode;
const candidate = Math.floor(100000 + Math.random() * 899999); // 6 digits
const [exists] = await conn.query( // Generates 6-digit loan code
"SELECT 1 FROM loans WHERE loan_code = ? LIMIT 1", do {
candidate = Math.floor(100000 + Math.random() * 899999);
const [rows] = await conn.query(
"SELECT 1 FROM loans where loan_code = ? LIMIT 1",
[candidate], [candidate],
); );
if (exists.length === 0) {
if (rows.length == 0) {
index = true;
loanCode = candidate; loanCode = candidate;
break;
} }
} } while (index === false);
if (!loanCode) {
await conn.rollback();
return {
success: false,
code: "SERVER_ERROR",
message: "Failed to generate unique loan code",
};
}
// Insert loan (now includes lockers) // Insert loan (now includes lockers)
const [insertRes] = await conn.query( const [insertRes] = await conn.query(
-100
View File
@@ -1,100 +0,0 @@
USE borrow_system_new;
-- USERS
INSERT INTO users (username, password, email, first_name, last_name, role, is_admin)
VALUES
('user1', 'passwordhash1', 'user1@example.com', 'First1', 'Last1', 1, false),
('user2', 'passwordhash2', 'user2@example.com', 'First2', 'Last2', 1, false),
('user3', 'passwordhash3', 'user3@example.com', 'First3', 'Last3', 2, false),
('admin1', 'passwordhash4', 'admin1@example.com', 'Admin', 'One', 9, true),
('admin2', 'passwordhash5', 'admin2@example.com', 'Admin', 'Two', 9, true);
-- ITEMS
INSERT INTO items (item_name, can_borrow_role, in_safe, safe_nr, door_key, last_borrowed_person, currently_borrowing)
VALUES
('Item1', 1, true, 1, 101, NULL, NULL),
('Item2', 1, true, 2, 102, 'user1', 'user1'),
('Item3', 2, true, 3, 103, 'user2', NULL),
('Item4', 1, false, NULL, NULL, NULL, NULL),
('Item5', 2, false, NULL, NULL, 'user3', 'user3');
-- LOANS
INSERT INTO loans (
username,
lockers,
loan_code,
start_date,
end_date,
take_date,
returned_date,
created_at,
loaned_items_id,
loaned_items_name,
deleted,
note
)
VALUES
(
'user1',
JSON_ARRAY('Locker1', 'Locker2'),
'123456',
'2026-02-01 09:00:00',
'2026-02-10 17:00:00',
'2026-02-01 09:15:00',
NULL,
'2026-02-01 09:00:00',
JSON_ARRAY(1, 2),
JSON_ARRAY('Item1', 'Item2'),
false,
'Erste allgemeine Ausleihe'
),
(
'user2',
JSON_ARRAY('Locker3'),
'234567',
'2026-02-02 10:00:00',
'2026-02-05 16:00:00',
'2026-02-02 10:05:00',
'2026-02-05 15:30:00',
'2026-02-02 10:00:00',
JSON_ARRAY(3),
JSON_ARRAY('Item3'),
false,
'Zurückgegeben vor Enddatum'
),
(
'user3',
JSON_ARRAY(),
'345678',
'2026-02-03 08:30:00',
'2026-02-15 18:00:00',
NULL,
NULL,
'2026-02-03 08:30:00',
JSON_ARRAY(5),
JSON_ARRAY('Item5'),
false,
'Noch ausgeliehen'
),
(
'user1',
JSON_ARRAY('Locker4'),
'456789',
'2025-12-01 09:00:00',
'2025-12-03 17:00:00',
'2025-12-01 09:10:00',
'2025-12-03 16:45:00',
'2025-12-01 09:00:00',
JSON_ARRAY(1),
JSON_ARRAY('Item1'),
true,
'Alte, gelöschte Ausleihe'
);
-- API KEYS
INSERT INTO apiKeys (api_key, entry_name)
VALUES
('10000001', 'Entry1'),
('10000002', 'Entry2'),
('10000003', 'Entry3'),
('10000004', 'Entry4');
-1
View File
@@ -11,7 +11,6 @@ CREATE TABLE users (
is_admin bool NOT NULL DEFAULT false, is_admin bool NOT NULL DEFAULT false,
entry_created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP, entry_created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
entry_updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, entry_updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
secret_user bool NOT NULL DEFAULT false,
PRIMARY KEY (id) PRIMARY KEY (id)
) ENGINE=InnoDB; ) ENGINE=InnoDB;
+8 -17
View File
@@ -1,37 +1,28 @@
# Changelog for upcoming version: v2.2 # Changelog for upcoming version: vX.X
This update provides some new features for the design. It also contains some improvements and I have also fixed some bugs. Introduction
## New features ## New features
- **Deactivatable services:** I have added the ability to deactivate services, which can be useful for maintenance or other purposes. The admin can activate and deactivate services in the admin panel. If a service is deactivated, it will not be available for users and they will get an error message if they try to use it. They will also get an warning banner on the homepage. -
- **New Animations:** I have added some new animations to the frontend, which make the user experience more enjoyable.
- **New Icon:** I have added a new icon for the frontend, which is now also used in the header and the favicon. It is a dark version of the old icon, which fits better to the overall design. I have made it with Icon Composer. The old icon is still used for the admin panel, which has a light design. (Maybe I will change the admin panel design in the future...)
- **New Button:** When you go to your user card (over the user icon in the header) you have a new button "Click me". If you click it, you will get an message... _I am just saying: I have implemented the no-as-a-service code in to my Backend._
## Improvements ## Improvements
- The overview page now shows the note column and is overall better organised. -
- Improved error logging
- If you try to delete a loan that has not been returned yet, you will get an 507 error code.
- When the admin deletes a loan, the loan will be still visible in the database, but it will be marked as deleted. This is to prevent data loss and to keep track of deleted loans.
- Mailer improvements: The mailer is now more clearly organised. Two large code files are now split into five smaller code files which are easier to maintain. Also the design of the mails has improved.
## Fixed bugs ## Fixed bugs
- Fixed bug: #13 -
- Fixed bug for messaging when server has an error
- Fixed footer height
--- ---
## New version numbers ## New version numbers
**Backend:** v2.2 **Backend:** vX.X
**Frontend:** v2.2 **Frontend:** vX.X
**Admin panel:** v1.4 **Admin panel:** vX.X
--- ---
+14 -14
View File
@@ -1,35 +1,35 @@
services: services:
demo_usr_frontend: usr-frontend_v2:
container_name: demo_borrow_system-usr-frontend container_name: borrow_system-usr-frontend
networks: networks:
- proxynet - proxynet
build: ./FrontendV2 build: ./FrontendV2
restart: unless-stopped restart: unless-stopped
demo_admin_frontend: admin-frontend:
container_name: demo_borrow_system-admin-frontend container_name: borrow_system-admin-frontend
networks: networks:
- proxynet - proxynet
build: ./admin build: ./admin
restart: unless-stopped restart: unless-stopped
demo_backend_v2: backend_v2:
container_name: demo_borrow_system-backend_v2 container_name: borrow_system-backend_v2
networks: networks:
- proxynet - proxynet
build: ./backendV2 build: ./backendV2
environment: environment:
NODE_ENV: production NODE_ENV: production
DB_HOST: demo_mysql_v2 DB_HOST: mysql_v2
DB_USER: root DB_USER: root
DB_PASSWORD: ${DB_PASSWORD_V2} DB_PASSWORD: ${DB_PASSWORD_V2}
DB_NAME: borrow_system_new DB_NAME: borrow_system_new
depends_on: depends_on:
- demo_mysql_v2 - mysql_v2
restart: unless-stopped restart: unless-stopped
demo_mysql_v2: mysql_v2:
container_name: demo_borrow_system-mysql-v2 container_name: borrow_system-mysql-v2
networks: networks:
- proxynet - proxynet
image: mysql:8.0 image: mysql:8.0
@@ -39,13 +39,13 @@ services:
MYSQL_DATABASE: borrow_system_new MYSQL_DATABASE: borrow_system_new
TZ: Europe/Berlin TZ: Europe/Berlin
volumes: volumes:
- demo_mysql-v2-data:/var/lib/mysql - mysql-v2-data:/var/lib/mysql
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro - ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
no-as-a-service: no-as-a-service:
container_name: borrow_system-naas container_name: borrow_system-naas
ports: networks:
- "3000:3000" - proxynet
build: build:
context: ./no-as-a-service context: ./no-as-a-service
dockerfile: Dockerfile dockerfile: Dockerfile
@@ -53,7 +53,7 @@ services:
volumes: volumes:
mysql-data: mysql-data:
demo_mysql-v2-data: mysql-v2-data:
networks: networks:
proxynet: proxynet: