diff --git a/ludos/annotation/README.md b/ludos/annotation/README.md index 9a505dd2..7ae61ece 100644 --- a/ludos/annotation/README.md +++ b/ludos/annotation/README.md @@ -1 +1,6 @@ -# LUDOS Annotation Api +# LUDOS Annotation Server + +## How to run? +```WORKDIR=./ludos/annotation```
+1. Run ```docker compose up --build```
+2. Now, the api is available with localhost:8090 base url. diff --git a/ludos/backend/README.md b/ludos/backend/README.md index fcf8c96d..14537c4c 100644 --- a/ludos/backend/README.md +++ b/ludos/backend/README.md @@ -1,5 +1,5 @@ # LUDOS Backend Api -Deployed Swagger Documentation: http://3.125.225.39:8080/api +Deployed Swagger Documentation: http://164.92.195.35:8080/api ## How to run? ```WORKDIR=./ludos/backend```
1. Create a .env file for the environment variables. Please ask for the variables. The name of the variables are included in .env.example file.
diff --git a/ludos/frontend/src/components/ForumTopic.js b/ludos/frontend/src/components/ForumTopic.js index 6f443846..655d8c5c 100644 --- a/ludos/frontend/src/components/ForumTopic.js +++ b/ludos/frontend/src/components/ForumTopic.js @@ -171,28 +171,26 @@ function ForumTopic(data) { ))} - - - {data.topic.title} - - - + + {}, []); + useEffect(() => { }, []); return ( @@ -138,7 +138,7 @@ function ForumTopic(data) { > @ - {data.topic.user.username} + {data.topic.user?.username} @@ -175,7 +175,7 @@ function ForumTopic(data) { }} > - {data.topic.game.title} + {data.topic.game?.title} {data.topic.upcomingTitle != null && data.topic.upcomingTitle.isUpcomingTitle && ( @@ -190,7 +190,7 @@ function ForumTopic(data) { {data.topic && - data.topic.tags.map((tag1, index1) => ( + data.topic.tags?.map((tag1, index1) => ( - - + + {data.topic.title} - - + + - @{data.topic.user.username} + @{data.topic.user?.username} - {data.topic.createdAt.split("T")[0]}{" "} - {data.topic.createdAt.split("T")[1].split(".")[0]} + {data.topic.createdAt?.split("T")[0]}{" "} + {data.topic.createdAt?.split("T")[1].split(".")[0]} { + const myComponentRef = useRef(null); const navigate = useNavigate(); const [searchValue, setSearchValue] = useState(""); const [searchKey, setSearchKey] = useState(""); @@ -18,6 +34,194 @@ const ForumsPage = () => { new Set(mergedThreads.map((item) => item.title)), ); const [trendingTopics, setTrendingTopics] = useState([]); + const [detailSearch, setDetailSearch] = useState(false); + const [nameSearch, setNameSearch] = useState(""); + const [tags, setTags] = useState([]) + const [currTag, setCurrTag] = useState(""); + const [detailGames, setDetailGames] = useState([]); + const [searchGame, setSearchGame] = useState(""); + const [searchGroup, setSearchGroup] = useState(""); + const [groups, setGroups] = useState([]); + const [sortBy, setSortBy] = useState("numberOfLikes"); + const [sortOrder, setSortOrder] = useState("ASC"); + const [searchUser, setSearchUser] = useState(""); + const [users, setUsers] = useState([]); + const [refresh, setRefresh] = useState(false); + const [page, setPage] = useState(1); + const [auth, setAuth] = useState(false); + const [detailThreads, setDetailThreads] = useState([]); + const [pageCount, setPageCount] = useState(1); + + const handleDetailSearch = () => { + setDetailSearch((prevDetailSearch) => !prevDetailSearch); + }; + + const handleNameSearchChange = (event) => { + setNameSearch(event.target.value); + } + + const handleDeleteTag = (item, index) => { + let arr = [...tags]; + arr.splice(index, 1); + console.log(item); + setTags(arr); + }; + + const handleTagsChange = (e) => { + setCurrTag(e.target.value); + }; + + const handleKeyUp = (e) => { + if (e.keyCode == 13) { + setTags((oldState) => [...oldState, e.target.value]); + setCurrTag(""); + } + }; + + const handleGameChange = (event, option) => { + if (option) { + setSearchGame(option.value); + } else { + setSearchGame(""); + } + }; + + const handleGameSearch = (event) => { + if (event?.target?.value) { + const link = `http://${process.env.REACT_APP_API_URL}/game?searchKey=${event.target.value}`; + axios + .get(link, { + headers: { + Authorization: "Bearer " + localStorage.getItem("accessToken"), + }, + }) + .then((response) => { + console.log(response); + setDetailGames(response.data.items); + }) + .catch((error) => { + console.log(error); + }); + } else { + setDetailGames([]); + } + }; + + const handleGroupChange = (event, option) => { + if (option) { + setSearchGroup(option.value); + } else { + setSearchGroup(""); + } + }; + + const handleGroupSearch = (event) => { + if (event?.target?.value) { + const link = `http://${process.env.REACT_APP_API_URL}/group?searchKey=${event.target.value}`; + axios + .get(link, { + headers: { + Authorization: "Bearer " + localStorage.getItem("accessToken"), + }, + }) + .then((response) => { + console.log(response); + setGroups(response.data.items); + console.log(groups); + }) + .catch((error) => { + console.log(error); + }); + } else { + setGroups([]); + } + }; + + const handleUserChange = (event, option) => { + if (option) { + setSearchUser(option.value); + } else { + setSearchUser(""); + } + }; + + const handleUserSearch = (event) => { + if (event?.target?.value) { + const link = `http://${process.env.REACT_APP_API_URL}/search/${event.target.value}`; + axios + .get(link, { + headers: { + Authorization: "Bearer " + localStorage.getItem("accessToken"), + }, + }) + .then((response) => { + console.log(response); + setUsers(response.data.users); + }) + .catch((error) => { + console.log(error); + }); + } else { + setUsers([]); + } + }; + + const handleSortByChange = (event) => { + setSortBy(event.target.value); + }; + + const handleSortOrderChange = (event) => { + setSortOrder(event.target.value); + }; + + const handleFilterButtonClick = () => { + setPage(1); + setRefresh(!refresh); + }; + + useEffect(() => { + if (localStorage.getItem("accessToken")) { + const link1 = `http://${process.env.REACT_APP_API_URL}/user/info`; + axios + .get(link1, { + headers: { + Authorization: "Bearer " + localStorage.getItem("accessToken"), + }, + }) + .then(() => { + setAuth(true); + }) + .catch((error) => { + console.log(error); + setAuth(false); + }); + } else { + setAuth(false); + } + const tagsString = tags.join("%2C"); + const link = `http://${process.env.REACT_APP_API_URL}/post?page=${page}&searchKey=${nameSearch}&tags=${tagsString}&gameId=${searchGame}&ownerUserId=${searchUser}&order=${sortOrder}&orderByKey=${sortBy}`; + console.log(link); + axios + .get(link, { + headers: { + Authorization: "Bearer " + localStorage.getItem("accessToken"), + }, + }) + .then((response) => { + console.log(response.data.items); + setDetailThreads(response.data.items); + setPageCount(response.data.meta.totalPages); + }) + .catch((error) => { + console.log(error); + }); + }, [refresh]); + + const handlePageChange = (event, value) => { + setPage(value); + setRefresh(!refresh); + }; + const handleThreadSearch = (threadId) => { //value should be the id of the thread @@ -240,6 +444,16 @@ const ForumsPage = () => { }, // Add more topics as needed... ]; */ + + const paginStyle = { + backgroundColor: "rgba(204, 204, 255, 0.9)", + borderRadius: "10px", + border: "4px solid rgba(51, 153, 255, 1)", // Çerçeve rengi ve genişliği + boxSizing: "border-box", // Kutu modelini içerir + fontFamily: "Trebuchet MS, sans-serif", + width: "auto", + marginTop: "10px", + }; return (
{ width: "100%", }} /> +
+
+ +
+ + + +
+ + +
+ {detailSearch && ( +
+ + + Detailed Search + + {/* Search Input */} + + Thread Name: + + + + + Filter with Tags: + +
+ +
+ {tags.map((item, index) => ( + handleDeleteTag(item, index)} + label={item} + /> + ))} +
+ +
+
+ + Filter with Game: + + ({ + label: game.title, + value: game.id, + }))} + getOptionLabel={(option) => option.label || ""} + onInputChange={handleGameSearch} + required + renderInput={(params) => ( + + )} + style={{ + marginBottom: "10px", + backgroundColor: "white", + borderRadius: "10px", + }} + /> + + Filter with Group: + + ({ + label: group.name, + value: group.id, + }))} + getOptionLabel={(option) => option.label || ""} + onInputChange={handleGroupSearch} + required + renderInput={(params) => ( + + )} + style={{ + marginBottom: "10px", + backgroundColor: "white", + borderRadius: "10px", + }} + /> + + + Filter with User: + + ({ + label: user.username, + value: user.id, + }))} + getOptionLabel={(option) => option.label || ""} + onInputChange={handleUserSearch} + required + renderInput={(params) => ( + + )} + style={{ + marginBottom: "10px", + backgroundColor: "white", + borderRadius: "10px", + }} + /> + + + Sort By: + + + + Sort Order: + + + + {/* Main Content */} + {detailThreads.map((topic, index) => ( + + ))} + +
+ + + +
+ )} +
+
+ + { - + ); }; diff --git a/ludos/frontend/src/pages/GamesPage.js b/ludos/frontend/src/pages/GamesPage.js index fd495249..ce0488af 100644 --- a/ludos/frontend/src/pages/GamesPage.js +++ b/ludos/frontend/src/pages/GamesPage.js @@ -56,6 +56,37 @@ const convertToSlug = (text) => { .replace(/--+/g, "-"); // Replace multiple dashes with single dash }; +const predefinedTags = [ + "Action", + "Adventure", + "RPG", + "Strategy", + "Simulation", + "Sports", + "Fighting", + "Horror", + "Puzzle", + "Multiplayer", + "Indie", + "RTS", + "Racing", + "Open World", + "Educational", + "VR", + "Survival", + "Story-Driven", + "Retro", + "Anime", + "Hack and Slash", + "Mystery", + "Historical", + "Sci-Fi", + "Fantasy", + "Comedy", + "Artistic", + "Puzzle-Platformer", +]; + export default function GamesPage() { const myComponentRef = useRef(null); const [searchValue, setSearchValue] = useState(""); @@ -76,6 +107,7 @@ export default function GamesPage() { const [auth, setAuth] = useState(false); const [detailGames, setDetailGames] = useState([]); const [pageCount, setPageCount] = useState(1); + const [isTagSelected, setIsTagSelected] = useState(false); const [gameHighlight, setGameHighlight] = useState([]); @@ -142,6 +174,10 @@ export default function GamesPage() { const handleGameRoute = (value) => { navigate(`/game/${convertToSlug(value)}`); }; + const handleTagSelect = (selectedTags) => { + setIsTagSelected(selectedTags.length > 0); + setTags(selectedTags); + }; useEffect(() => { if (localStorage.getItem("accessToken")) { @@ -416,19 +452,31 @@ export default function GamesPage() { style={{ display: "flex", justifyContent: "flex-start", - alignItems: "center", marginLeft: "20px", marginBottom: "10px", }} > - + + {detailSearch ? (
@@ -482,38 +530,29 @@ export default function GamesPage() { > Filter with Tags: -
- -
- {tags.map((item, index) => ( - handleDeleteTag(item, index)} - label={item} - /> + - -
+ )} + > + {predefinedTags.map((tag) => ( + + {tag} + + ))} + { - + {/* Main Content */} {groups.map((topic, index) => ( diff --git a/ludos/frontend/src/pages/LoginPage.js b/ludos/frontend/src/pages/LoginPage.js index 9903d042..ffd4945d 100644 --- a/ludos/frontend/src/pages/LoginPage.js +++ b/ludos/frontend/src/pages/LoginPage.js @@ -15,12 +15,11 @@ import axios from "axios"; import MuiAlert from "@mui/material/Alert"; import LoginIcon from "@mui/icons-material/Login"; import { useNavigate } from "react-router-dom"; -import Visibility from '@mui/icons-material/Visibility'; -import VisibilityOff from '@mui/icons-material/VisibilityOff'; -import IconButton from '@mui/material/IconButton'; -import InputAdornment from '@mui/material/InputAdornment'; -import FormControl from '@mui/material/FormControl'; - +import Visibility from "@mui/icons-material/Visibility"; +import VisibilityOff from "@mui/icons-material/VisibilityOff"; +import IconButton from "@mui/material/IconButton"; +import InputAdornment from "@mui/material/InputAdornment"; +import FormControl from "@mui/material/FormControl"; const Alert = React.forwardRef(function Alert(props, ref) { return ; @@ -31,7 +30,7 @@ const backgroundImage = require("../assets/logo.png"); export default function Login() { useEffect(() => { window.scrollTo(0, 0); -}, []); + }, []); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); @@ -118,6 +117,8 @@ export default function Login() { flexDirection: "column", alignItems: "center", backgroundColor: "#0C1929", + maxHeight: "100%", + justifyContent: "center", }} > { setPasswordEmpty(false); setPassword(e.target.value); @@ -249,7 +252,11 @@ export default function Login() { xs sx={{ display: "flex", alignItems: "flex-start" }} > - + Forgot password? diff --git a/ludos/semantic-search/README.md b/ludos/semantic-search/README.md new file mode 100644 index 00000000..e0ace9a3 --- /dev/null +++ b/ludos/semantic-search/README.md @@ -0,0 +1,6 @@ +# LUDOS Semantic Search Server + +## How to run? +```WORKDIR=./ludos/semantic-search```
+1. Run ```docker compose up --build```
+2. Now, the api is available with localhost:8000 base url.