Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ff31ecbf6 | |||
| c48da71cd5 | |||
| 8e35e81e8f | |||
| 95aae1c050 | |||
| 3f910f937b | |||
| 3ed6121a0b | |||
| 5d9e965597 | |||
| e296de27ef | |||
| 5c7a96912b | |||
| 195f270064 | |||
| 3d592c5c76 | |||
| 08104d32db | |||
| cc7c024892 | |||
| 3eb452aeab | |||
| f46a654184 | |||
| 863409aed9 | |||
| 052137a697 |
@@ -14,7 +14,7 @@ server {
|
||||
}
|
||||
|
||||
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?)$ {
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Flex } from "@chakra-ui/react";
|
||||
import { Footer } from "./components/footer/Footer";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { API_BASE } from "@/config/api.config";
|
||||
import { ContactPage } from "./pages/ContactPage";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
@@ -80,6 +81,7 @@ function App() {
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/my-loans" element={<MyLoansPage />} />
|
||||
<Route path="/landingpage" element={<Landingpage />} />
|
||||
<Route path="/contact" element={<ContactPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
MoreVertical,
|
||||
Languages,
|
||||
Table,
|
||||
ContactRound,
|
||||
} from "lucide-react";
|
||||
import { useUserContext } from "@/states/Context";
|
||||
import { useState } from "react";
|
||||
@@ -155,6 +156,16 @@ export const Header = () => {
|
||||
</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.Item
|
||||
value="logout"
|
||||
@@ -287,6 +298,17 @@ export const Header = () => {
|
||||
</HStack>
|
||||
</Button>
|
||||
</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">
|
||||
<HStack gap={2}>
|
||||
<LogOut size={18} />
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -121,10 +121,28 @@ export const MyLoansPage = () => {
|
||||
|
||||
const formatDate = (iso: string | null) => {
|
||||
if (!iso) return "-";
|
||||
const m = iso.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/);
|
||||
if (!m) return iso;
|
||||
const [, y, M, d, h, min] = m;
|
||||
return `${d}.${M}.${y} ${h}:${min}`;
|
||||
const date = new Date(iso);
|
||||
if (isNaN(date.getTime())) return iso;
|
||||
return date.toLocaleString("de-DE", {
|
||||
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) => {
|
||||
@@ -151,7 +169,7 @@ export const MyLoansPage = () => {
|
||||
setLoans((prev) =>
|
||||
prev.map((loan) =>
|
||||
loan.loan_code === loanCode
|
||||
? { ...loan, take_date: new Date().toISOString() }
|
||||
? { ...loan, take_date: dateAndTime(true) }
|
||||
: loan,
|
||||
),
|
||||
);
|
||||
@@ -191,7 +209,7 @@ export const MyLoansPage = () => {
|
||||
setLoans((prev) =>
|
||||
prev.map((loan) =>
|
||||
loan.loan_code === loanCode
|
||||
? { ...loan, returned_date: new Date().toISOString() }
|
||||
? { ...loan, returned_date: dateAndTime(true) }
|
||||
: loan,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"sure-delete-loan-2": "Für den Admin bleibt sie weiterhin sichtbar.",
|
||||
"delete": "Löschen",
|
||||
"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",
|
||||
"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.",
|
||||
@@ -68,7 +68,7 @@
|
||||
"admin-status": "Admin-Status",
|
||||
"first-name": "Vorname",
|
||||
"last-name": "Nachname",
|
||||
"app-title": "Ausleihsystem (demo)",
|
||||
"app-title": "Ausleihsystem",
|
||||
"last-borrowed-person": "Zuletzt ausgeliehen von",
|
||||
"currently-borrowed-by": "Derzeit ausgeliehen von",
|
||||
"back": "Zurückgehen",
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"sure-delete-loan-2": "It will remain visible to the admin.",
|
||||
"delete": "Delete",
|
||||
"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",
|
||||
"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.",
|
||||
@@ -68,7 +68,7 @@
|
||||
"admin-status": "Admin status",
|
||||
"first-name": "First name",
|
||||
"last-name": "Last name",
|
||||
"app-title": "Borrow System (demo)",
|
||||
"app-title": "Borrow System",
|
||||
"last-borrowed-person": "Last borrowed by",
|
||||
"currently-borrowed-by": "Currently borrowed by",
|
||||
"back": "Go back",
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ server {
|
||||
}
|
||||
|
||||
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?)$ {
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"backend-info": {
|
||||
"version": "v2.2 (demo)"
|
||||
"version": "v2.2"
|
||||
},
|
||||
"frontend-info": {
|
||||
"version": "v2.2 (demo)"
|
||||
"version": "v2.2"
|
||||
},
|
||||
"admin-panel-info": {
|
||||
"version": "v1.4 (demo)"
|
||||
"version": "v1.4"
|
||||
}
|
||||
}
|
||||
@@ -29,14 +29,14 @@ export const createUser = async (
|
||||
};
|
||||
|
||||
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 };
|
||||
return { success: false };
|
||||
};
|
||||
|
||||
export const changePassword = async (username, newPassword) => {
|
||||
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],
|
||||
);
|
||||
if (result.affectedRows > 0) return { success: true };
|
||||
@@ -52,7 +52,7 @@ export const editUserById = async (
|
||||
is_admin,
|
||||
) => {
|
||||
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],
|
||||
);
|
||||
if (result.affectedRows > 0) return { success: true };
|
||||
@@ -61,7 +61,7 @@ export const editUserById = async (
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
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 };
|
||||
return { success: false };
|
||||
@@ -69,7 +69,7 @@ export const getAllUsers = async () => {
|
||||
|
||||
export const getUserById = async (userId) => {
|
||||
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],
|
||||
);
|
||||
if (rows.length === 0) {
|
||||
|
||||
@@ -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');
|
||||
@@ -11,7 +11,6 @@ CREATE TABLE users (
|
||||
is_admin bool NOT NULL DEFAULT false,
|
||||
entry_created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
entry_updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
secret_user bool NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
|
||||
+8
-17
@@ -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
|
||||
|
||||
- **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
|
||||
|
||||
- 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 bug: #13
|
||||
- Fixed bug for messaging when server has an error
|
||||
- Fixed footer height
|
||||
-
|
||||
|
||||
---
|
||||
|
||||
## 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
@@ -1,35 +1,35 @@
|
||||
services:
|
||||
demo_usr_frontend:
|
||||
container_name: demo_borrow_system-usr-frontend
|
||||
usr-frontend_v2:
|
||||
container_name: borrow_system-usr-frontend
|
||||
networks:
|
||||
- proxynet
|
||||
build: ./FrontendV2
|
||||
restart: unless-stopped
|
||||
|
||||
demo_admin_frontend:
|
||||
container_name: demo_borrow_system-admin-frontend
|
||||
admin-frontend:
|
||||
container_name: borrow_system-admin-frontend
|
||||
networks:
|
||||
- proxynet
|
||||
build: ./admin
|
||||
restart: unless-stopped
|
||||
|
||||
demo_backend_v2:
|
||||
container_name: demo_borrow_system-backend_v2
|
||||
backend_v2:
|
||||
container_name: borrow_system-backend_v2
|
||||
networks:
|
||||
- proxynet
|
||||
build: ./backendV2
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
DB_HOST: demo_mysql_v2
|
||||
DB_HOST: mysql_v2
|
||||
DB_USER: root
|
||||
DB_PASSWORD: ${DB_PASSWORD_V2}
|
||||
DB_NAME: borrow_system_new
|
||||
depends_on:
|
||||
- demo_mysql_v2
|
||||
- mysql_v2
|
||||
restart: unless-stopped
|
||||
|
||||
demo_mysql_v2:
|
||||
container_name: demo_borrow_system-mysql-v2
|
||||
mysql_v2:
|
||||
container_name: borrow_system-mysql-v2
|
||||
networks:
|
||||
- proxynet
|
||||
image: mysql:8.0
|
||||
@@ -39,13 +39,13 @@ services:
|
||||
MYSQL_DATABASE: borrow_system_new
|
||||
TZ: Europe/Berlin
|
||||
volumes:
|
||||
- demo_mysql-v2-data:/var/lib/mysql
|
||||
- mysql-v2-data:/var/lib/mysql
|
||||
- ./mysql-timezone.cnf:/etc/mysql/conf.d/timezone.cnf:ro
|
||||
|
||||
no-as-a-service:
|
||||
container_name: borrow_system-naas
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
- proxynet
|
||||
build:
|
||||
context: ./no-as-a-service
|
||||
dockerfile: Dockerfile
|
||||
@@ -53,7 +53,7 @@ services:
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
demo_mysql-v2-data:
|
||||
mysql-v2-data:
|
||||
|
||||
networks:
|
||||
proxynet:
|
||||
|
||||
Reference in New Issue
Block a user