Change userId base session to dependent
No files matched your search
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/libs/libs.iml" filepath="$PROJECT_DIR$/libs/libs.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -99,5 +99,10 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.47.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,5 +1,6 @@
|
||||
package BsK.client.network.handler;
|
||||
|
||||
|
||||
import BsK.client.ui.handler.UIHandler;
|
||||
import BsK.common.packet.Packet;
|
||||
import BsK.common.packet.PacketSerializer;
|
||||
@@ -14,35 +15,84 @@ import io.netty.handler.codec.http.websocketx.*;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
@Slf4j
|
||||
public class ClientHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
|
||||
public static ChannelHandlerContext ctx;
|
||||
public static TextWebSocketFrame frame;
|
||||
public static final ClientHandler INSTANCE = new ClientHandler();
|
||||
|
||||
private static final Map<Class<?>, List<ResponseListener<?>>> listeners = new HashMap<>();
|
||||
|
||||
public static <T> void addResponseListener(Class<T> responseType, ResponseListener<T> listener) {
|
||||
listeners.computeIfAbsent(responseType, k -> new ArrayList<>()).add(listener);
|
||||
}
|
||||
|
||||
public static <T> void removeResponseListener(Class<T> responseType, ResponseListener<T> listener) {
|
||||
var listenerList = listeners.get(responseType);
|
||||
if (listenerList != null) {
|
||||
listenerList.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
|
||||
// log.debug("Received message: {}", frame.text());
|
||||
// var packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
|
||||
// switch (packet) {
|
||||
// case HandshakeCompleteResponse handshakeCompleteResponse -> {
|
||||
// log.info("Handshake complete");
|
||||
// this.ctx = ctx;
|
||||
// this.frame = frame;
|
||||
// }
|
||||
// case ErrorResponse response -> {
|
||||
// log.error("Received error response: {}", response.getError());
|
||||
// switch (response.getError()) {
|
||||
// case USER_ALREADY_EXISTS -> log.error("User already exists");
|
||||
// default -> log.error("Received error response: {}", response.getError());
|
||||
// }
|
||||
// }
|
||||
// case null, default -> log.warn("Unknown message: {}", frame.text());
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
|
||||
log.debug("Received message: {}", frame.text());
|
||||
var packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
|
||||
switch (packet) {
|
||||
case HandshakeCompleteResponse handshakeCompleteResponse -> {
|
||||
|
||||
if (packet != null) {
|
||||
// Handle HandshakeCompleteResponse to initialize ctx and frame
|
||||
if (packet instanceof HandshakeCompleteResponse handshakeResponse) {
|
||||
log.info("Handshake complete");
|
||||
this.ctx = ctx;
|
||||
// var login = new LoginRequest("user", "user");
|
||||
// NetworkUtil.sendPacket(ctx.channel(), login);
|
||||
ClientHandler.ctx = ctx;
|
||||
ClientHandler.frame = frame;
|
||||
return; // No further processing needed for handshake response
|
||||
}
|
||||
case ErrorResponse response -> {
|
||||
log.error("Received error response: {}", response.getError());
|
||||
switch (response.getError()) {
|
||||
case USER_ALREADY_EXISTS -> log.error("User already exists");
|
||||
default -> log.error("Received error response: {}", response.getError());
|
||||
|
||||
|
||||
// Process other packets
|
||||
List<ResponseListener<?>> responseListeners = listeners.get(packet.getClass());
|
||||
if (responseListeners != null) {
|
||||
for (ResponseListener<?> listener : responseListeners) {
|
||||
notifyListener(listener, packet);
|
||||
}
|
||||
} else {
|
||||
log.warn("No listeners registered for response type: {}", packet.getClass().getName());
|
||||
}
|
||||
case LoginSuccessResponse loginSuccessResponse -> log.info("Received login success response");
|
||||
case null, default -> log.warn("Unknown message: {}", frame.text());
|
||||
} else {
|
||||
log.warn("Unknown or null packet received: {}", frame.text());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (evt instanceof IdleStateEvent) {
|
||||
@@ -60,4 +110,14 @@ public class ClientHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void notifyListener(ResponseListener<?> listener, T response) {
|
||||
try {
|
||||
((ResponseListener<T>) listener).onResponse(response);
|
||||
} catch (ClassCastException e) {
|
||||
log.error("Listener type mismatch for response: {}", response.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package BsK.client.network.handler;
|
||||
|
||||
public interface ResponseListener<T> {
|
||||
void onResponse(T response);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package BsK.client.ui.component.CheckUpPage;
|
||||
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
import BsK.client.ui.component.common.RoundedButtonUI;
|
||||
import BsK.client.ui.component.common.RoundedPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class CheckUpPage extends JPanel {
|
||||
private boolean debugMode = false; // Enable debug mode
|
||||
|
||||
public CheckUpPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Sidebar panel
|
||||
JPanel sidebar = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color color1 = new Color(63, 81, 181);
|
||||
Color color2 = new Color(33, 150, 243);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
|
||||
if (debugMode) {
|
||||
drawBoundingBox(g2d, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
sidebar.setBackground(new Color(63, 81, 181));
|
||||
sidebar.setLayout(new GridLayout(15, 1));
|
||||
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
String[] sidebarItems = {"Thống kê","Thăm khám", "Dữ liệu bệnh nhân", "Kho", "Người dùng", "Thông tin"};
|
||||
String[] destination = {"DashboardPage","CheckUpPage", "PatientDataPage", "InventoryPage", "UserPage", "InfoPage"};
|
||||
for(int i = 0; i < sidebarItems.length; i++) {
|
||||
String item = sidebarItems[i];
|
||||
String dest = destination[i];
|
||||
JLabel label = new JLabel(item);
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
|
||||
label.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
|
||||
// Add a mouse listener to handle click events
|
||||
label.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(java.awt.event.MouseEvent e) {
|
||||
// Handle the click event
|
||||
mainFrame.showPage(dest);
|
||||
// JOptionPane.showMessageDialog(null, item + " clicked!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(Color.WHITE); // Restore original color
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.add(label);
|
||||
}
|
||||
|
||||
// Make the sidebar scrollable
|
||||
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
|
||||
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
|
||||
sidebarScrollPane.getViewport().setOpaque(false);
|
||||
sidebarScrollPane.setOpaque(false);
|
||||
|
||||
// Topbar panel
|
||||
JPanel topbar = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (debugMode) {
|
||||
drawBoundingBox((Graphics2D) g, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
topbar.setLayout(new BorderLayout());
|
||||
topbar.setBackground(Color.WHITE);
|
||||
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JLabel title = new JLabel("Check Up");
|
||||
title.setFont(new Font("Arial", Font.BOLD, 18));
|
||||
topbar.add(title, BorderLayout.WEST);
|
||||
|
||||
JLabel userInfo = new JLabel("User Name (Admin)");
|
||||
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
topbar.add(userInfo, BorderLayout.EAST);
|
||||
|
||||
// Main content panel
|
||||
JPanel mainContent = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (debugMode) {
|
||||
drawBoundingBox((Graphics2D) g, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
mainContent.setLayout(new BorderLayout());
|
||||
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Data table inside a RoundedPanel
|
||||
RoundedPanel dataTable1 = new RoundedPanel(20, Color.WHITE, false) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (debugMode) {
|
||||
drawBoundingBox((Graphics2D) g, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RoundedPanel dataTable2 = new RoundedPanel(20, Color.WHITE, false) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (debugMode) {
|
||||
drawBoundingBox((Graphics2D) g, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
JLabel titleText1 = new JLabel();
|
||||
titleText1.setText("Check Up Queue 1");
|
||||
titleText1.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
titleText1.setBackground(Color.WHITE);
|
||||
titleText1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Padding
|
||||
|
||||
JLabel titleText2 = new JLabel();
|
||||
titleText2.setText("Check Up Queue 2");
|
||||
titleText2.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
titleText2.setBackground(Color.WHITE);
|
||||
titleText2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Padding
|
||||
|
||||
dataTable1.setLayout(new BorderLayout());
|
||||
dataTable1.add(titleText1, BorderLayout.NORTH);
|
||||
dataTable1.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 10)); // Adjust padding for better appearance
|
||||
|
||||
dataTable2.setLayout(new BorderLayout());
|
||||
dataTable2.add(titleText2, BorderLayout.NORTH);
|
||||
dataTable2.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 10)); // Adjust padding for better appearance
|
||||
|
||||
String[] columns = {"Name", "Gender", "Course"};
|
||||
String[][] data = {
|
||||
{"John", "Male", "Java"},
|
||||
{"Dara", "Male", "C++"},
|
||||
{"Bora", "Male", "C#"},
|
||||
};
|
||||
JTable table1 = new JTable(data, columns);
|
||||
JScrollPane tableScroll1 = new JScrollPane(table1);
|
||||
tableScroll1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
|
||||
dataTable1.add(tableScroll1, BorderLayout.CENTER);
|
||||
|
||||
JTable table2 = new JTable(data, columns);
|
||||
JScrollPane tableScroll2 = new JScrollPane(table2);
|
||||
tableScroll2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
|
||||
dataTable2.add(tableScroll2, BorderLayout.CENTER);
|
||||
|
||||
UIManager.getDefaults().put("SplitPane.border", BorderFactory.createEmptyBorder()); // Remove border
|
||||
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, dataTable1, dataTable2);
|
||||
splitPane.setResizeWeight(0.5); // Split
|
||||
|
||||
// Add the split pane to the main content
|
||||
mainContent.add(splitPane, BorderLayout.CENTER);
|
||||
// Notice board
|
||||
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
if (debugMode) {
|
||||
drawBoundingBox((Graphics2D) g, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
noticeBoard.setLayout(new BorderLayout());
|
||||
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
|
||||
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
|
||||
noticeText.setEditable(false);
|
||||
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
|
||||
|
||||
//mainContent.add(noticeBoard, BorderLayout.EAST);
|
||||
|
||||
// Adding panels to the frame
|
||||
add(sidebarScrollPane, BorderLayout.WEST);
|
||||
add(topbar, BorderLayout.NORTH);
|
||||
add(mainContent, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void drawBoundingBox(Graphics2D g2d, JComponent component) {
|
||||
g2d.setColor(Color.RED);
|
||||
g2d.setStroke(new BasicStroke(2));
|
||||
g2d.drawRect(0, 0, component.getWidth() - 1, component.getHeight() - 1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// JFrame frame = new JFrame("Dashboard");
|
||||
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
// frame.setSize(800, 600);
|
||||
// frame.add(new CheckUpPage();
|
||||
// frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package BsK.client.ui.component.DashboardPage;
|
||||
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
import BsK.client.ui.component.common.RoundedButtonUI;
|
||||
import BsK.client.ui.component.common.RoundedPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class DashboardPage extends JPanel {
|
||||
public DashboardPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Sidebar panel
|
||||
JPanel sidebar = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color color1 = new Color(63, 81, 181);
|
||||
Color color2 = new Color(33, 150, 243);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
}
|
||||
};
|
||||
sidebar.setBackground(new Color(63, 81, 181));
|
||||
sidebar.setLayout(new GridLayout(15, 1));
|
||||
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
String[] sidebarItems = {"Thống kê","Thăm khám", "Dữ liệu bệnh nhân", "Kho", "Người dùng", "Thông tin"};
|
||||
String[] destination = {"DashboardPage","CheckUpPage", "PatientDataPage", "InventoryPage", "UserPage", "InfoPage"};
|
||||
for(int i = 0; i < sidebarItems.length; i++) {
|
||||
String item = sidebarItems[i];
|
||||
String dest = destination[i];
|
||||
JLabel label = new JLabel(item);
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
|
||||
label.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
|
||||
// Add a mouse listener to handle click events
|
||||
label.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(java.awt.event.MouseEvent e) {
|
||||
// Handle the click event
|
||||
mainFrame.showPage(dest);
|
||||
|
||||
// JOptionPane.showMessageDialog(null, item + " clicked!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(Color.WHITE); // Restore original color
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.add(label);
|
||||
}
|
||||
|
||||
// Make the sidebar scrollable
|
||||
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
|
||||
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
|
||||
sidebarScrollPane.getViewport().setOpaque(false);
|
||||
sidebarScrollPane.setOpaque(false);
|
||||
|
||||
|
||||
|
||||
// Topbar panel
|
||||
JPanel topbar = new JPanel();
|
||||
topbar.setLayout(new BorderLayout());
|
||||
topbar.setBackground(Color.WHITE);
|
||||
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JLabel title = new JLabel("Dashboard / Home");
|
||||
title.setFont(new Font("Arial", Font.BOLD, 18));
|
||||
topbar.add(title, BorderLayout.WEST);
|
||||
|
||||
JLabel userInfo = new JLabel("User Name (Admin)");
|
||||
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
topbar.add(userInfo, BorderLayout.EAST);
|
||||
|
||||
// Main content panel
|
||||
JPanel mainContent = new JPanel();
|
||||
mainContent.setLayout(new BorderLayout());
|
||||
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Top cards
|
||||
JPanel topCards = new JPanel();
|
||||
topCards.setLayout(new GridLayout(1, 4, 20, 20));
|
||||
String[] cardTitles = {"Add Check", "Income", "Expense", "Other Income"};
|
||||
Color[] cardColors = {Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN};
|
||||
|
||||
for (int i = 0; i < cardTitles.length; i++) {
|
||||
JPanel card = new RoundedPanel(20, cardColors[i], true);
|
||||
card.setBackground(cardColors[i]);
|
||||
card.setLayout(new BorderLayout());
|
||||
card.setBorder(BorderFactory.createEmptyBorder(30, 20, 30, 20));
|
||||
|
||||
JLabel cardTitle = new JLabel(cardTitles[i]);
|
||||
cardTitle.setForeground(Color.WHITE);
|
||||
cardTitle.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
card.add(cardTitle, BorderLayout.NORTH);
|
||||
|
||||
JLabel cardValue = new JLabel("Value", SwingConstants.CENTER);
|
||||
cardValue.setForeground(Color.WHITE);
|
||||
cardValue.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
card.add(cardValue, BorderLayout.CENTER);
|
||||
|
||||
topCards.add(card);
|
||||
}
|
||||
|
||||
mainContent.add(topCards, BorderLayout.NORTH);
|
||||
|
||||
// Wrapper panel for spacing
|
||||
JPanel wrapperPanel = new JPanel();
|
||||
wrapperPanel.setLayout(new BorderLayout());
|
||||
wrapperPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); // Add spacing above
|
||||
wrapperPanel.setOpaque(false); // Ensure transparency for background compatibility
|
||||
|
||||
// Data table inside a RoundedPanel
|
||||
RoundedPanel dataTable = new RoundedPanel(20, Color.WHITE, false);
|
||||
dataTable.setLayout(new BorderLayout());
|
||||
dataTable.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Adjust padding for better appearance
|
||||
|
||||
String[] columns = {"Name", "Gender", "Course", "Fees", "Action"};
|
||||
String[][] data = {
|
||||
{"John", "Male", "Java", "$300", "Edit/Delete"},
|
||||
{"Dara", "Male", "C++", "$300", "Edit/Delete"},
|
||||
{"Bora", "Male", "C#", "$300", "Edit/Delete"},
|
||||
};
|
||||
JTable table = new JTable(data, columns);
|
||||
JScrollPane tableScroll = new JScrollPane(table);
|
||||
tableScroll.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
|
||||
dataTable.add(tableScroll, BorderLayout.CENTER);
|
||||
|
||||
// Add RoundedPanel to the wrapper panel
|
||||
wrapperPanel.add(dataTable, BorderLayout.CENTER);
|
||||
|
||||
// Add the wrapper panel to the main content
|
||||
mainContent.add(wrapperPanel, BorderLayout.CENTER);
|
||||
|
||||
|
||||
|
||||
// Notice board
|
||||
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false);
|
||||
noticeBoard.setLayout(new BorderLayout());
|
||||
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
|
||||
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
|
||||
noticeText.setEditable(false);
|
||||
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
|
||||
|
||||
//mainContent.add(noticeBoard, BorderLayout.EAST);
|
||||
|
||||
// Adding panels to the frame
|
||||
add(sidebarScrollPane, BorderLayout.WEST);
|
||||
add(topbar, BorderLayout.NORTH);
|
||||
add(mainContent, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// JFrame frame = new JFrame("Dashboard");
|
||||
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
// frame.setSize(800, 600);
|
||||
// frame.add(new DashboardPage());
|
||||
// frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package BsK.client.ui.component.DashboardPage;
|
||||
|
||||
import BsK.client.ui.component.common.RoundedPanel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class SchoolUI {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Create the main frame
|
||||
JFrame frame = new JFrame("School UI");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(1200, 800);
|
||||
|
||||
// Main layout
|
||||
frame.setLayout(new BorderLayout());
|
||||
|
||||
// Sidebar panel
|
||||
JPanel sidebar = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color color1 = new Color(63, 81, 181);
|
||||
Color color2 = new Color(33, 150, 243);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, 0, height, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
}
|
||||
};
|
||||
sidebar.setBackground(new Color(63, 81, 181));
|
||||
sidebar.setLayout(new GridLayout(15, 1));
|
||||
sidebar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
String[] sidebarItems = {"Dashboard", "Charts", "Report", "Message", "Staff", "Student", "Library", "Holiday", "Calendar", "Chat App", "Contact", "File Manager", "Our Centres", "Gallery"};
|
||||
|
||||
for (String item : sidebarItems) {
|
||||
JLabel label = new JLabel(item);
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // Change cursor to hand
|
||||
label.setFont(new Font("Arial", Font.BOLD, 14));
|
||||
|
||||
// Add a mouse listener to handle click events
|
||||
label.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(java.awt.event.MouseEvent e) {
|
||||
// Handle the click event
|
||||
System.out.println(item + " clicked!");
|
||||
JOptionPane.showMessageDialog(null, item + " clicked!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(new Color(200, 230, 255)); // Highlight on hover
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(java.awt.event.MouseEvent e) {
|
||||
label.setForeground(Color.WHITE); // Restore original color
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.add(label);
|
||||
}
|
||||
|
||||
// Make the sidebar scrollable
|
||||
JScrollPane sidebarScrollPane = new JScrollPane(sidebar);
|
||||
sidebarScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
sidebarScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
sidebarScrollPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
|
||||
sidebarScrollPane.getViewport().setOpaque(false);
|
||||
sidebarScrollPane.setOpaque(false);
|
||||
|
||||
|
||||
|
||||
// Topbar panel
|
||||
JPanel topbar = new JPanel();
|
||||
topbar.setLayout(new BorderLayout());
|
||||
topbar.setBackground(Color.WHITE);
|
||||
topbar.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JLabel title = new JLabel("Dashboard / Home");
|
||||
title.setFont(new Font("Arial", Font.BOLD, 18));
|
||||
topbar.add(title, BorderLayout.WEST);
|
||||
|
||||
JLabel userInfo = new JLabel("User Name (Admin)");
|
||||
userInfo.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
topbar.add(userInfo, BorderLayout.EAST);
|
||||
|
||||
// Main content panel
|
||||
JPanel mainContent = new JPanel();
|
||||
mainContent.setLayout(new BorderLayout());
|
||||
mainContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Top cards
|
||||
JPanel topCards = new JPanel();
|
||||
topCards.setLayout(new GridLayout(1, 4, 20, 20));
|
||||
String[] cardTitles = {"New Student", "Income", "Expense", "Other Income"};
|
||||
Color[] cardColors = {Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN};
|
||||
|
||||
for (int i = 0; i < cardTitles.length; i++) {
|
||||
JPanel card = new RoundedPanel(20, cardColors[i], true);
|
||||
card.setBackground(cardColors[i]);
|
||||
card.setLayout(new BorderLayout());
|
||||
card.setBorder(BorderFactory.createEmptyBorder(30, 20, 30, 20));
|
||||
|
||||
JLabel cardTitle = new JLabel(cardTitles[i]);
|
||||
cardTitle.setForeground(Color.WHITE);
|
||||
cardTitle.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
card.add(cardTitle, BorderLayout.NORTH);
|
||||
|
||||
JLabel cardValue = new JLabel("Value", SwingConstants.CENTER);
|
||||
cardValue.setForeground(Color.WHITE);
|
||||
cardValue.setFont(new Font("Arial", Font.BOLD, 16));
|
||||
card.add(cardValue, BorderLayout.CENTER);
|
||||
|
||||
topCards.add(card);
|
||||
}
|
||||
|
||||
mainContent.add(topCards, BorderLayout.NORTH);
|
||||
|
||||
// Wrapper panel for spacing
|
||||
JPanel wrapperPanel = new JPanel();
|
||||
wrapperPanel.setLayout(new BorderLayout());
|
||||
wrapperPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); // Add spacing above
|
||||
wrapperPanel.setOpaque(false); // Ensure transparency for background compatibility
|
||||
|
||||
// Data table inside a RoundedPanel
|
||||
RoundedPanel dataTable = new RoundedPanel(20, Color.WHITE, false);
|
||||
dataTable.setLayout(new BorderLayout());
|
||||
dataTable.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Adjust padding for better appearance
|
||||
|
||||
String[] columns = {"Name", "Gender", "Course", "Fees", "Action"};
|
||||
String[][] data = {
|
||||
{"John", "Male", "Java", "$300", "Edit/Delete"},
|
||||
{"Dara", "Male", "C++", "$300", "Edit/Delete"},
|
||||
{"Bora", "Male", "C#", "$300", "Edit/Delete"},
|
||||
};
|
||||
JTable table = new JTable(data, columns);
|
||||
JScrollPane tableScroll = new JScrollPane(table);
|
||||
tableScroll.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // Inner padding
|
||||
dataTable.add(tableScroll, BorderLayout.CENTER);
|
||||
|
||||
// Add RoundedPanel to the wrapper panel
|
||||
wrapperPanel.add(dataTable, BorderLayout.CENTER);
|
||||
|
||||
// Add the wrapper panel to the main content
|
||||
mainContent.add(wrapperPanel, BorderLayout.CENTER);
|
||||
|
||||
|
||||
|
||||
// Notice board
|
||||
JPanel noticeBoard = new RoundedPanel(20, Color.WHITE, false);
|
||||
noticeBoard.setLayout(new BorderLayout());
|
||||
noticeBoard.setBorder(BorderFactory.createTitledBorder("Notice Board"));
|
||||
noticeBoard.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JTextArea noticeText = new JTextArea("04/10/2021\nHidemode Now\n\n03/10/2021\nFurther Reading\n");
|
||||
noticeText.setEditable(false);
|
||||
noticeBoard.add(new JScrollPane(noticeText), BorderLayout.CENTER);
|
||||
|
||||
//mainContent.add(noticeBoard, BorderLayout.EAST);
|
||||
|
||||
// Adding panels to the frame
|
||||
frame.add(sidebarScrollPane, BorderLayout.WEST);
|
||||
frame.add(topbar, BorderLayout.NORTH);
|
||||
frame.add(mainContent, BorderLayout.CENTER);
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package BsK.client.ui.component.LandingPage;
|
||||
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class LandingPage extends JPanel {
|
||||
public LandingPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Left and middle panel with background image and tint
|
||||
JPanel leftMiddlePanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
ImageIcon icon = new ImageIcon("/Users/lethanhdat/Documents/GitHub/ldS_BsK/src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
|
||||
Image image = icon.getImage();
|
||||
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
|
||||
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
|
||||
g2d.setColor(tint);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
};
|
||||
leftMiddlePanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
|
||||
JLabel titleLabel = new JLabel("BSK");
|
||||
titleLabel.setForeground(Color.WHITE);
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 50));
|
||||
leftMiddlePanel.add(titleLabel, gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
JLabel authorLabel = new JLabel("by lds217 and miti99");
|
||||
authorLabel.setForeground(Color.WHITE);
|
||||
authorLabel.setFont(new Font("Arial", Font.PLAIN, 12));
|
||||
leftMiddlePanel.add(authorLabel, gbc);
|
||||
|
||||
// Right panel with blue gradient and buttons
|
||||
JPanel rightPanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color color1 = new Color(0, 0, 255);
|
||||
Color color2 = new Color(173, 216, 230);
|
||||
GradientPaint gp = new GradientPaint(0, 0, color1, width, height, color2);
|
||||
g2d.setPaint(gp);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
}
|
||||
};
|
||||
rightPanel.setLayout(new GridBagLayout());
|
||||
rightPanel.setPreferredSize(new Dimension(300, getHeight())); // Set preferred size for the right panel
|
||||
gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
|
||||
JButton loginButton = new RoundedButton("Login");
|
||||
JButton registerButton = new RoundedButton("Register");
|
||||
|
||||
// Set the same preferred size for both buttons
|
||||
Dimension buttonSize = new Dimension(150, 40);
|
||||
loginButton.setPreferredSize(buttonSize);
|
||||
registerButton.setPreferredSize(buttonSize);
|
||||
|
||||
rightPanel.add(loginButton, gbc);
|
||||
gbc.gridy++;
|
||||
rightPanel.add(registerButton, gbc);
|
||||
|
||||
add(leftMiddlePanel, BorderLayout.CENTER);
|
||||
add(rightPanel, BorderLayout.EAST);
|
||||
|
||||
// Action listeners for buttons
|
||||
loginButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showPage("LoginPage");
|
||||
}
|
||||
});
|
||||
|
||||
registerButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showPage("RegisterPage");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Custom button class with rounded edges and stroke
|
||||
private static class RoundedButton extends JButton {
|
||||
public RoundedButton(String text) {
|
||||
super(text);
|
||||
setContentAreaFilled(false);
|
||||
setFocusPainted(false);
|
||||
setOpaque(false);
|
||||
setBorderPainted(false); // Ensure the border is not painted
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
// Do not call super.paintComponent(g) to avoid painting the background
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2.setColor(getBackground());
|
||||
g2.fillRoundRect(0, 0, getWidth(), getHeight(), 30, 30);
|
||||
g2.dispose();
|
||||
super.paintComponent(g); // Call super to paint the text
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBorder(Graphics g) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2.setColor(Color.WHITE);
|
||||
g2.setStroke(new BasicStroke(2));
|
||||
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 30, 30);
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getInsets() {
|
||||
return new Insets(10, 20, 10, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package BsK.client.ui.component.LoginPage;
|
||||
|
||||
import BsK.client.network.handler.ClientHandler;
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
import BsK.common.packet.Packet;
|
||||
import BsK.common.packet.PacketSerializer;
|
||||
import BsK.common.packet.req.LoginRequest;
|
||||
import BsK.common.packet.res.ErrorResponse;
|
||||
import BsK.common.packet.res.LoginSuccessResponse;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
@Slf4j
|
||||
public class LoginPage extends JPanel {
|
||||
public LoginPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Panel with background image and tint
|
||||
JPanel backgroundPanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
ImageIcon icon = new ImageIcon("src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
|
||||
Image image = icon.getImage();
|
||||
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
|
||||
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
|
||||
g2d.setColor(tint);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
};
|
||||
backgroundPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(5, 5, 5, 5);
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
gbc.gridwidth = 2; // Span across two columns
|
||||
|
||||
JLabel promptLabel = new JLabel("Please enter your details:");
|
||||
promptLabel.setForeground(Color.WHITE);
|
||||
promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
backgroundPanel.add(promptLabel, gbc);
|
||||
|
||||
gbc.gridwidth = 1; // Reset to default
|
||||
gbc.gridy++;
|
||||
JLabel usernameLabel = new JLabel("Enter Username:");
|
||||
usernameLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(usernameLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JTextField loginField = new JTextField(20);
|
||||
backgroundPanel.add(loginField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
JLabel passwordLabel = new JLabel("Enter Password:");
|
||||
passwordLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(passwordLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JPasswordField passwordField = new JPasswordField(20);
|
||||
backgroundPanel.add(passwordField, gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
JButton loginButton = new JButton("Login");
|
||||
|
||||
loginButton.addActionListener(e -> {
|
||||
char[] passwordChars = passwordField.getPassword();
|
||||
String password = new String(passwordChars);
|
||||
String username = loginField.getText();
|
||||
var loginRequest = new LoginRequest(username, password);
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), loginRequest);
|
||||
});
|
||||
|
||||
// Register listeners for login-related responses
|
||||
ClientHandler.addResponseListener(LoginSuccessResponse.class, response -> {
|
||||
log.info("Login successful, UserId: {}, Role: {}", response.getUserId(), response.getRole());
|
||||
SwingUtilities.invokeLater(() -> mainFrame.showPage("DashboardPage"));
|
||||
});
|
||||
|
||||
ClientHandler.addResponseListener(ErrorResponse.class, response -> {
|
||||
log.error("Login error: {}", response.getError());
|
||||
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(this,
|
||||
"Login failed: " + response.getError(), "Error", JOptionPane.ERROR_MESSAGE));
|
||||
});
|
||||
|
||||
|
||||
backgroundPanel.add(loginButton, gbc);
|
||||
add(backgroundPanel, BorderLayout.CENTER);
|
||||
|
||||
|
||||
JButton backButton = new JButton("Back");
|
||||
backButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showPage("LandingPage");
|
||||
}
|
||||
});
|
||||
add(backButton, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
// Remove listeners to avoid memory leaks
|
||||
ClientHandler.removeResponseListener(LoginSuccessResponse.class, this::handleLoginSuccess);
|
||||
ClientHandler.removeResponseListener(ErrorResponse.class, this::handleErrorResponse);
|
||||
}
|
||||
|
||||
private void handleLoginSuccess(LoginSuccessResponse response) {
|
||||
log.info("Login successful, UserId: {}, Role: {}", response.getUserId(), response.getRole());
|
||||
}
|
||||
|
||||
private void handleErrorResponse(ErrorResponse response) {
|
||||
log.error("Error response: {}", response.getError());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package BsK.client.ui.component;
|
||||
|
||||
import BsK.client.ui.component.CheckUpPage.CheckUpPage;
|
||||
import BsK.client.ui.component.DashboardPage.DashboardPage;
|
||||
import BsK.client.ui.component.LandingPage.LandingPage;
|
||||
import BsK.client.ui.component.LoginPage.LoginPage;
|
||||
import BsK.client.ui.component.RegisterPage.RegisterPage;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MainFrame extends JFrame {
|
||||
private CardLayout cardLayout;
|
||||
private JPanel mainPanel;
|
||||
|
||||
public MainFrame() {
|
||||
setTitle("BSK");
|
||||
setSize(800, 600);
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
cardLayout = new CardLayout();
|
||||
mainPanel = new JPanel(cardLayout);
|
||||
|
||||
// Add pages to the main panel
|
||||
mainPanel.add(new LandingPage(this), "LandingPage");
|
||||
mainPanel.add(new LoginPage(this), "LoginPage");
|
||||
mainPanel.add(new RegisterPage(this), "RegisterPage");
|
||||
mainPanel.add(new DashboardPage(this), "DashboardPage");
|
||||
mainPanel.add(new CheckUpPage(this), "CheckUpPage");
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
public void showPage(String pageName) {
|
||||
cardLayout.show(mainPanel, pageName);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
new MainFrame().setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package BsK.client.ui.component.RegisterPage;
|
||||
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class RegisterPage extends JPanel {
|
||||
public RegisterPage(MainFrame mainFrame) {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
// Panel with background image and tint
|
||||
JPanel backgroundPanel = new JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
ImageIcon icon = new ImageIcon("src/main/java/BsK/client/ui/image/landingpagebg.jpeg");
|
||||
Image image = icon.getImage();
|
||||
g2d.drawImage(image, 0, 0, getWidth(), getHeight(), this);
|
||||
Color tint = new Color(0, 0, 0, 100); // Black tint with transparency
|
||||
g2d.setColor(tint);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
};
|
||||
backgroundPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.insets = new Insets(10, 10, 10, 10);
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 0;
|
||||
gbc.anchor = GridBagConstraints.WEST;
|
||||
|
||||
JLabel promptLabel = new JLabel("Please enter your details:");
|
||||
promptLabel.setForeground(Color.WHITE);
|
||||
promptLabel.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
gbc.gridwidth = 2;
|
||||
backgroundPanel.add(promptLabel, gbc);
|
||||
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridy++;
|
||||
JLabel usernameLabel = new JLabel("Username:");
|
||||
usernameLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(usernameLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JTextField usernameField = new JTextField(20);
|
||||
backgroundPanel.add(usernameField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
JLabel nameLabel = new JLabel("Name:");
|
||||
nameLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(nameLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JTextField nameField = new JTextField(20);
|
||||
backgroundPanel.add(nameField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
JLabel passwordLabel = new JLabel("Password:");
|
||||
passwordLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(passwordLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JPasswordField passwordField = new JPasswordField(20);
|
||||
backgroundPanel.add(passwordField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
JLabel rePasswordLabel = new JLabel("Re-enter your password:");
|
||||
rePasswordLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(rePasswordLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
JPasswordField rePasswordField = new JPasswordField(20);
|
||||
backgroundPanel.add(rePasswordField, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy++;
|
||||
JLabel roleLabel = new JLabel("Role:");
|
||||
roleLabel.setForeground(Color.WHITE);
|
||||
backgroundPanel.add(roleLabel, gbc);
|
||||
|
||||
gbc.gridx = 1;
|
||||
String[] roles = {"user", "admin", "doctor", "nurse"};
|
||||
JComboBox<String> roleComboBox = new JComboBox<>(roles);
|
||||
backgroundPanel.add(roleComboBox, gbc);
|
||||
|
||||
gbc.gridy++;
|
||||
JButton loginButton = new JButton("Register");
|
||||
loginButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showPage("LandingPage");
|
||||
}
|
||||
});
|
||||
backgroundPanel.add(loginButton, gbc);
|
||||
add(backgroundPanel, BorderLayout.CENTER);
|
||||
|
||||
// Back button to return to the landing page
|
||||
JButton backButton = new JButton("Back");
|
||||
backButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
mainFrame.showPage("LandingPage");
|
||||
}
|
||||
});
|
||||
add(backButton, BorderLayout.SOUTH);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Working Directory = " + System.getProperty("user.dir"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package BsK.client.ui.component.common;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicButtonUI;
|
||||
import java.awt.*;
|
||||
|
||||
public class RoundedButtonUI extends BasicButtonUI {
|
||||
private final int cornerRadius;
|
||||
|
||||
public RoundedButtonUI(int cornerRadius) {
|
||||
this.cornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI(JComponent c) {
|
||||
super.installUI(c);
|
||||
JButton button = (JButton) c;
|
||||
button.setOpaque(false);
|
||||
button.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g, JComponent c) {
|
||||
JButton button = (JButton) c;
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
int width = button.getWidth();
|
||||
int height = button.getHeight();
|
||||
g2.setColor(button.getBackground());
|
||||
g2.fillRoundRect(0, 0, width, height, cornerRadius, cornerRadius);
|
||||
g2.setColor(button.getForeground());
|
||||
g2.setFont(button.getFont());
|
||||
FontMetrics fm = g2.getFontMetrics();
|
||||
int stringWidth = fm.stringWidth(button.getText());
|
||||
int stringHeight = fm.getAscent();
|
||||
g2.drawString(button.getText(), (width - stringWidth) / 2, (height + stringHeight) / 2 - 2);
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package BsK.client.ui.component.common;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class RoundedPanel extends JPanel {
|
||||
private int cornerRadius;
|
||||
private Color fillColor;
|
||||
private boolean gradient;
|
||||
|
||||
public RoundedPanel(int radius, Color fillColor, boolean gradient) {
|
||||
super();
|
||||
this.cornerRadius = radius;
|
||||
this.fillColor = fillColor;
|
||||
this.gradient = gradient;
|
||||
setOpaque(false); // Ensures background is transparent outside the rounded area
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Graphics2D graphics = (Graphics2D) g;
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
// Create a gradient paint from white to the fillColor
|
||||
GradientPaint gradientColor = new GradientPaint(
|
||||
-100, -100, Color.WHITE, width, height, fillColor
|
||||
);
|
||||
|
||||
// Apply the gradient as the fill paint
|
||||
if(gradient)
|
||||
graphics.setPaint(gradientColor);
|
||||
else
|
||||
graphics.setColor(fillColor);
|
||||
graphics.fillRoundRect(0, 0, width, height, cornerRadius, cornerRadius);
|
||||
|
||||
// Draw the rounded border
|
||||
// graphics.setColor(getForeground());
|
||||
// graphics.drawRoundRect(0, 0, width - 1, height - 1, cornerRadius, cornerRadius);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package BsK.client.ui.handler;
|
||||
|
||||
import BsK.client.network.handler.ClientHandler;
|
||||
import BsK.client.ui.component.MainFrame;
|
||||
import BsK.common.packet.Packet;
|
||||
import BsK.common.packet.req.LoginRequest;
|
||||
import BsK.common.packet.res.HandshakeCompleteResponse;
|
||||
@@ -31,35 +32,9 @@ public class UIHandler {
|
||||
}
|
||||
|
||||
public void showUI() {
|
||||
JTextField usernameField = new JTextField();
|
||||
JPasswordField passwordField = new JPasswordField();
|
||||
Object[] message = {
|
||||
"Username:", usernameField,
|
||||
"Password:", passwordField
|
||||
};
|
||||
|
||||
int option = JOptionPane.showConfirmDialog(null, message, "Login", JOptionPane.OK_CANCEL_OPTION);
|
||||
if (option == JOptionPane.OK_OPTION) {
|
||||
String username = usernameField.getText();
|
||||
String password = new String(passwordField.getPassword());
|
||||
System.out.println("Username: " + username);
|
||||
System.out.println("Password: " + password);
|
||||
var login = new LoginRequest(username, password);
|
||||
NetworkUtil.sendPacket(ClientHandler.ctx.channel(), login);
|
||||
} else {
|
||||
System.out.println("Login canceled");
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
new MainFrame().setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
// public void onClickButtonLogin() {
|
||||
// if (!readyToLogin) {
|
||||
// // TODO: hiển thị lỗi "Chưa kết nối tới server"
|
||||
// return;
|
||||
// }
|
||||
// var username = "username"; // Đọc từ đâu đó
|
||||
// var password = "password"; // Đọc từ đâu đó
|
||||
//
|
||||
// NetworkUtil.sendPacket(ctx.channel(), login);
|
||||
// NetworkUtil.sendPacket(loginRequest);
|
||||
// }
|
||||
}
|
||||
|
After Width: | Height: | Size: 757 B |
|
After Width: | Height: | Size: 945 B |
|
After Width: | Height: | Size: 970 B |
|
After Width: | Height: | Size: 681 B |
|
After Width: | Height: | Size: 829 B |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 256 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 396 KiB |
@@ -8,6 +8,7 @@ import java.time.LocalDateTime;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
|
||||
public class LoginRequest implements Packet {
|
||||
String username;
|
||||
String password;
|
||||
|
||||
@@ -10,7 +10,11 @@ public class ErrorResponse implements Packet {
|
||||
|
||||
Error error;
|
||||
|
||||
public enum Error {
|
||||
public String getError() {
|
||||
return error.toString();
|
||||
}
|
||||
|
||||
public enum Error {
|
||||
SUCCESS,
|
||||
UNKNOWN,
|
||||
USERNAME_NOT_FOUND,
|
||||
|
||||
@@ -17,48 +17,74 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class Server {
|
||||
private static final int PORT = 1999;
|
||||
static Connection connection;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
EventLoopGroup parentGroup =
|
||||
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
|
||||
EventLoopGroup childGroup =
|
||||
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap bootstrap =
|
||||
new ServerBootstrap()
|
||||
.group(parentGroup, childGroup)
|
||||
.channel(
|
||||
Epoll.isAvailable()
|
||||
? EpollServerSocketChannel.class
|
||||
: NioServerSocketChannel.class)
|
||||
.localAddress(new InetSocketAddress(PORT))
|
||||
.childHandler(
|
||||
new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline()
|
||||
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
|
||||
.addLast(new HttpServerCodec())
|
||||
.addLast(new ChunkedWriteHandler())
|
||||
.addLast(new HttpObjectAggregator(8192))
|
||||
.addLast("ws", new WebSocketServerProtocolHandler("/"))
|
||||
.addLast(new ServerHandler());
|
||||
}
|
||||
});
|
||||
static {
|
||||
try {
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:src/main/resources/database/BSK.db");
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
ChannelFuture f = bootstrap.bind().sync();
|
||||
public static Statement statement;
|
||||
|
||||
log.info("Server started on port {}", PORT);
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
parentGroup.shutdownGracefully();
|
||||
childGroup.shutdownGracefully();
|
||||
static {
|
||||
try {
|
||||
statement = connection.createStatement();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Server() throws SQLException {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, SQLException {
|
||||
EventLoopGroup parentGroup =
|
||||
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
|
||||
EventLoopGroup childGroup =
|
||||
Epoll.isAvailable() ? new EpollEventLoopGroup() : new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap bootstrap =
|
||||
new ServerBootstrap()
|
||||
.group(parentGroup, childGroup)
|
||||
.channel(
|
||||
Epoll.isAvailable()
|
||||
? EpollServerSocketChannel.class
|
||||
: NioServerSocketChannel.class)
|
||||
.localAddress(new InetSocketAddress(PORT))
|
||||
.childHandler(
|
||||
new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline()
|
||||
.addLast(new IdleStateHandler(60 * 30, 0, 0, TimeUnit.SECONDS))
|
||||
.addLast(new HttpServerCodec())
|
||||
.addLast(new ChunkedWriteHandler())
|
||||
.addLast(new HttpObjectAggregator(8192))
|
||||
.addLast("ws", new WebSocketServerProtocolHandler("/"))
|
||||
.addLast(new ServerHandler());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture f = bootstrap.bind().sync();
|
||||
|
||||
log.info("Server started on port {}", PORT);
|
||||
f.channel().closeFuture().sync();
|
||||
} finally {
|
||||
parentGroup.shutdownGracefully();
|
||||
childGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,50 @@
|
||||
package BsK.server.network.entity;
|
||||
|
||||
import BsK.server.network.manager.SessionManager;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static BsK.server.Server.statement;
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
public class User {
|
||||
|
||||
int id;
|
||||
int userId;
|
||||
Channel channel;
|
||||
Role role = Role.GUEST;
|
||||
Role role;
|
||||
|
||||
public User(int id, Channel channel) {
|
||||
this.id = id;
|
||||
int sessionId;
|
||||
|
||||
public User(Channel channel, int sessionId) {
|
||||
this.channel = channel;
|
||||
this.sessionId = sessionId;
|
||||
Role role = Role.GUEST;
|
||||
}
|
||||
|
||||
public void authenticate(String username, String password) {
|
||||
if (username.equals("admin") && password.equals("admin")) {
|
||||
role = Role.ADMIN;
|
||||
} else if (username.equals("user") && password.equals("user")) {
|
||||
role = Role.USER;
|
||||
}
|
||||
try {
|
||||
ResultSet rs = statement.executeQuery("select * from User where user_name = '" + username + "' and password = '" + password + "'");
|
||||
if (!rs.isBeforeFirst()) {
|
||||
System.out.println("No data found in the User table.");
|
||||
} else {
|
||||
while(rs.next())
|
||||
{
|
||||
log.info(rs.getString("name") + " logged in");
|
||||
role = Role.valueOf(rs.getString("role_name"));
|
||||
userId = rs.getInt("user_id");
|
||||
}
|
||||
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
|
||||
@@ -13,7 +13,7 @@ import BsK.common.packet.res.LoginSuccessResponse;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
import BsK.server.database.entity.Patient;
|
||||
import BsK.server.database.entity.Patient.Sex;
|
||||
import BsK.server.network.manager.UserManager;
|
||||
import BsK.server.network.manager.SessionManager;
|
||||
import BsK.server.network.util.UserUtil;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
@@ -32,17 +32,19 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
|
||||
log.debug("Received message: {}", frame.text());
|
||||
Packet packet = PacketSerializer.GSON.fromJson(frame.text(), Packet.class);
|
||||
|
||||
|
||||
if (packet instanceof LoginRequest loginRequest) {
|
||||
log.debug(
|
||||
"Received login request: {}, {}", loginRequest.getUsername(), loginRequest.getPassword());
|
||||
var user = UserManager.getUserByChannel(ctx.channel());
|
||||
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
|
||||
user.authenticate(loginRequest.getUsername(), loginRequest.getPassword());
|
||||
|
||||
if (user.isAuthenticated()) {
|
||||
log.info("User {} authenticated, role {}", user.getId(), user.getRole());
|
||||
UserUtil.sendPacket(user.getId(), new LoginSuccessResponse(user.getId(), user.getRole()));
|
||||
UserUtil.sendPacket(user.getSessionId(), new LoginSuccessResponse(user.getUserId(), user.getRole()));
|
||||
log.info("Send response to client User {} authenticated, role {}", user.getUserId(), user.getRole());
|
||||
} else {
|
||||
log.info("User {} failed to authenticate", user.getId());
|
||||
log.info("User {} failed to authenticate", user.getUserId());
|
||||
}
|
||||
} else if (packet instanceof RegisterRequest registerRequest) {
|
||||
log.debug(
|
||||
@@ -57,19 +59,20 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
}
|
||||
} else {
|
||||
// Gia su packet nay can verify la user da login
|
||||
var user = UserManager.getUserByChannel(ctx.channel());
|
||||
var user = SessionManager.getUserByChannel(ctx.channel().id().asLongText());
|
||||
if (!user.isAuthenticated()) {
|
||||
log.warn("Received packet from unauthenticated user: {}", packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (packet) {
|
||||
case GetPatientInfoReq getPatientInfoReq -> {
|
||||
var patientInfo =
|
||||
new Patient(getPatientInfoReq.getPatientId(), new Date(1999, 01, 01), "test",
|
||||
Sex.MALE);
|
||||
var response = new GetPatientInfoRes(patientInfo);
|
||||
UserUtil.sendPacket(user.getId(), response);
|
||||
UserUtil.sendPacket(user.getUserId(), response);
|
||||
}
|
||||
case null, default -> log.warn("Received unknown packet: {}", packet);
|
||||
}
|
||||
@@ -79,7 +82,7 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (cause instanceof IOException) {
|
||||
UserManager.onUserDisconnect(ctx.channel());
|
||||
SessionManager.onUserDisconnect(ctx.channel());
|
||||
} else {
|
||||
log.error("ERROR: ", cause);
|
||||
}
|
||||
@@ -90,16 +93,16 @@ public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFram
|
||||
if (evt instanceof IdleStateEvent event) {
|
||||
if (event.state() == IdleState.READER_IDLE) {
|
||||
try {
|
||||
UserManager.onUserDisconnect(ctx.channel());
|
||||
SessionManager.onUserDisconnect(ctx.channel());
|
||||
ctx.channel().close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
} else if (evt instanceof HandshakeComplete) {
|
||||
int userId = UserManager.onUserLogin(ctx.channel());
|
||||
log.info("User {} logged in", userId);
|
||||
int SessionId = SessionManager.onUserLogin(ctx.channel());
|
||||
log.info("Session {} logged in", SessionId);
|
||||
|
||||
UserUtil.sendPacket(userId, new HandshakeCompleteResponse());
|
||||
UserUtil.sendPacket(SessionId, new HandshakeCompleteResponse());
|
||||
} else {
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package BsK.server.network.manager;
|
||||
|
||||
import BsK.server.network.entity.User;
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class SessionManager {
|
||||
private static final Map<Integer, String> SESSION_ID_MAP = new ConcurrentSkipListMap<>();
|
||||
|
||||
private static final Map<String, Integer> CHANNEL_SESSION_ID_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<String, User> CHANNEL_TO_USER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static final AtomicInteger SESSION_ID = new AtomicInteger(0);
|
||||
|
||||
|
||||
public static User getUserByChannel(String channel) {
|
||||
return CHANNEL_TO_USER_MAP.get(channel);
|
||||
}
|
||||
|
||||
public static int getSessionByChannelId(String channelId) {
|
||||
return CHANNEL_SESSION_ID_MAP.get(channelId);
|
||||
}
|
||||
|
||||
public static String getChannelBySessionId(int sessionId) {
|
||||
return SESSION_ID_MAP.get(sessionId);
|
||||
}
|
||||
|
||||
public static int onUserLogin(Channel channel) {
|
||||
int sessionId = SESSION_ID.incrementAndGet();
|
||||
var user = new User(channel, sessionId);
|
||||
SESSION_ID_MAP.put(sessionId, channel.id().asLongText());
|
||||
CHANNEL_SESSION_ID_MAP.put(channel.id().asLongText(), sessionId);
|
||||
CHANNEL_TO_USER_MAP.put(channel.id().asLongText(), user);
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public static void onUserDisconnect(Channel channel) {
|
||||
int sessionId = CHANNEL_SESSION_ID_MAP.remove(channel.id().asLongText());
|
||||
SESSION_ID_MAP.remove(sessionId);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package BsK.server.network.manager;
|
||||
|
||||
import BsK.server.network.entity.User;
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class UserManager {
|
||||
private static final Map<Integer, User> USER_MAP = new ConcurrentSkipListMap<>();
|
||||
|
||||
private static final Map<String, Integer> CHANNEL_ID_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static final AtomicInteger USER_ID = new AtomicInteger(0);
|
||||
|
||||
public static User getUserById(int userId) {
|
||||
return USER_MAP.get(userId);
|
||||
}
|
||||
|
||||
public static User getUserByChannelId(String channelId) {
|
||||
return USER_MAP.get(CHANNEL_ID_MAP.get(channelId));
|
||||
}
|
||||
|
||||
public static User getUserByChannel(Channel channel) {
|
||||
return getUserByChannelId(channel.id().asLongText());
|
||||
}
|
||||
|
||||
public static int onUserLogin(Channel channel) {
|
||||
int userId = USER_ID.incrementAndGet();
|
||||
var user = new User(userId, channel);
|
||||
USER_MAP.put(userId, user);
|
||||
CHANNEL_ID_MAP.put(channel.id().asLongText(), userId);
|
||||
return userId;
|
||||
}
|
||||
|
||||
public static void onUserDisconnect(Channel channel) {
|
||||
USER_MAP.remove(CHANNEL_ID_MAP.remove(channel.id().asLongText()));
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,16 @@ package BsK.server.network.util;
|
||||
|
||||
import BsK.common.packet.Packet;
|
||||
import BsK.common.util.network.NetworkUtil;
|
||||
import BsK.server.network.manager.UserManager;
|
||||
import BsK.server.network.manager.SessionManager;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class UserUtil {
|
||||
public static void sendPacket(int userId, Packet packet) {
|
||||
var user = UserManager.getUserById(userId);
|
||||
public static void sendPacket(int sessionId, Packet packet) {
|
||||
String channel = SessionManager.getChannelBySessionId(sessionId);
|
||||
var user = SessionManager.getUserByChannel(channel);
|
||||
if (user == null) return;
|
||||
|
||||
NetworkUtil.sendPacket(user.getChannel(), packet);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package BsK.testing;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class Sample
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// NOTE: Connection and Statement are AutoCloseable.
|
||||
// Don't forget to close them both in order to avoid leaks.
|
||||
try
|
||||
(
|
||||
// create a database connection
|
||||
Connection connection = DriverManager.getConnection("jdbc:sqlite:src/main/resources/database/BSK.db");
|
||||
Statement statement = connection.createStatement();
|
||||
)
|
||||
{
|
||||
System.out.println("Connection established successfully.");
|
||||
|
||||
statement.setQueryTimeout(30); // set timeout to 30 sec.
|
||||
|
||||
ResultSet rs = statement.executeQuery("select * from User");
|
||||
if (!rs.isBeforeFirst()) {
|
||||
System.out.println("No data found in the User table.");
|
||||
} else {
|
||||
while(rs.next())
|
||||
{
|
||||
// read the result set
|
||||
System.out.println("name = " + rs.getString("name"));
|
||||
System.out.println("id = " + rs.getInt("user_id"));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SQLException e)
|
||||
{
|
||||
// if the error message is "out of memory",
|
||||
// it probably means no database file is found
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||