Added SteamAPI and achievement searching
This commit is contained in:
parent
b229ff9a15
commit
627cc810ed
61 changed files with 2781 additions and 903 deletions
|
@ -30,10 +30,16 @@ app.get("/login", (req, res) => {
|
|||
res.sendFile(path.join(__dirname + "/webpage/login.html"));
|
||||
});
|
||||
app.get("/", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/index.html"));
|
||||
res.sendFile(path.join(__dirname + "/webpage/search_achievements.html"));
|
||||
});
|
||||
app.get("/about", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/about.html"));
|
||||
app.get("/achievements", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/search_achievements.html"));
|
||||
});
|
||||
app.get("/users", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/search_users.html"));
|
||||
});
|
||||
app.get("/games", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/search_games.html"));
|
||||
});
|
||||
app.get("/profile/:id", (req, res) => {
|
||||
res.sendFile(path.join(__dirname + "/webpage/profile.html"));
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Achievements Project</title>
|
||||
|
||||
<link rel="stylesheet" href="/static/styles/theme.css" />
|
||||
<link rel="stylesheet" href="/static/styles/common.css" />
|
||||
<link rel="stylesheet" href="/static/styles/about.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<template data-template="navbar: List<Basic>">
|
||||
<div id="navbar-section-${section}" class="navbar-section">
|
||||
<template data-template="navbar-section-${section}: List<Basic>">
|
||||
<div id="navbar-item-${item}" class="navbar-item" data-page-name="${item}">
|
||||
${title}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div id="content-body">
|
||||
<div id="about-page" class="page">
|
||||
<div class="page-subsection">
|
||||
<div class="page-header">
|
||||
<p class="page-header-text">About</p>
|
||||
<div class="page-header-separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-subsection">
|
||||
<div class="page-subsection-wrapper">
|
||||
<p id="about-text" class="page-subsection-chunk">Collate achievement data from multiple platforms into a single location. Explore achievement data of yourself and others.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/scripts/template.js"></script>
|
||||
<script src="/static/scripts/common.js"></script>
|
||||
<script src="/static/scripts/about.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -28,6 +28,10 @@
|
|||
<div class="page-header-separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="importing">
|
||||
<p id="importing-text">Contemplating...</p>
|
||||
<img id="importing-loading" class="ap-loading" src="/static/res/loading.svg" alt="Loading Symbol" />
|
||||
</div>
|
||||
<template data-template="profile-page">
|
||||
<div id="profile-section-1">
|
||||
<div id="profile-info" class="page-subsection">
|
||||
|
@ -49,7 +53,7 @@
|
|||
</div>
|
||||
<div id="profile-info-pfp-border" class="page-subsection-chunk">
|
||||
<div id="profile-info-pfp">
|
||||
<img id="profile-info-pfp-img" src="/api/user/${id}/image" alt="User's Profile Picture" />
|
||||
<img id="profile-info-pfp-img" class="lazy-img" data-src="/api/user/${id}/image" alt="User's Profile Picture" />
|
||||
<div id="profile-info-pfp-vignette"></div>
|
||||
<img id="profile-info-pfp-upload" src="/static/res/upload.svg" alt="Upload Image" />
|
||||
<img id="profile-info-pfp-upload-hover" src="/static/res/upload-hover.svg" alt="Upload Image" />
|
||||
|
|
144
frontend/webpage/search_achievements.html
Normal file
144
frontend/webpage/search_achievements.html
Normal file
|
@ -0,0 +1,144 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Achievements Project</title>
|
||||
|
||||
<link rel="stylesheet" href="/static/styles/theme.css" />
|
||||
<link rel="stylesheet" href="/static/styles/common.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search_achievements.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<template data-template="navbar: List<Basic>">
|
||||
<div id="navbar-section-${section}" class="navbar-section">
|
||||
<template data-template="navbar-section-${section}: List<Basic>">
|
||||
<div id="navbar-item-${item}" class="navbar-item" data-page-name="${item}">
|
||||
${title}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div id="content-body">
|
||||
<div id="search-achievements-page" class="search page">
|
||||
<div class="page-subsection">
|
||||
<div class="page-header">
|
||||
<p class="page-header-text">Search Achievements</p>
|
||||
<div class="page-header-separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-subsection">
|
||||
<div id="list-page-search-filters">
|
||||
<div id="list-page-search-dropdown">
|
||||
<div id="search-wrapper" class="page-subsection-wrapper">
|
||||
<div id="list-page-search-pair" class="list-page-search page-subsection-chunk">
|
||||
<label id="achievement-search-button" for="achievement-search">Search</label>
|
||||
<input id="achievement-search-field" type="text" placeholder="Name" name="achievement-search"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="filter-dropdown-wrapper" class="page-subsection-wrapper">
|
||||
<div id="filter-dropdown-stack">
|
||||
<img id="filter-dropdown-button" src="/static/res/dropdown.svg" alt="Dropdown Button"/>
|
||||
<img id="filter-dropdown-button-hover" src="/static/res/dropdown-hover.svg" alt="Dropdown Button"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="list-page-filters-flex">
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">Me</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div id="completed-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">Completed</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">Difficulty</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Min Completion</p>
|
||||
<input id="min-completion-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Max Completion</p>
|
||||
<input id="max-completion-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Min Difficulty</p>
|
||||
<input id="min-difficulty-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Max Difficulty</p>
|
||||
<input id="max-difficulty-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">Quality</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Min Quality</p>
|
||||
<input id="min-quality-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
<div class="list-page-filter">
|
||||
<p class="list-page-filter-label">Max Quality</p>
|
||||
<input id="max-quality-filter" type="text" class="list-page-filter-param"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-partitions">
|
||||
<div class="list-page-list-partition page-subsection-wrapper">
|
||||
<div class="page-subsection-chunk">
|
||||
<div class="list-page-list">
|
||||
<div class="list-page-header">
|
||||
<p class="list-page-entry-icon"></p>
|
||||
<p class="list-page-entry-text achievement-game-name">Game</p>
|
||||
<p class="list-page-entry-text achievement-name">Name</p>
|
||||
<p class="list-page-entry-text achievement-completion">Completion Rate</p>
|
||||
<p class="list-page-entry-text achievement-difficulty">Difficulty</p>
|
||||
<p class="list-page-entry-text achievement-quality">Quality</p>
|
||||
</div>
|
||||
<template id="achievement-list-template" data-template="achievements-page-list: List<Basic>">
|
||||
<div class="list-page-entry">
|
||||
<img class="list-page-entry-icon lazy-img" data-src="/api/achievement/${achievement_id}/image" alt="Achievement Thumbnail"></img>
|
||||
<p class="list-page-entry-text achievement-game-name">${game_name}</p>
|
||||
<p class="list-page-entry-text achievement-name">${achievement_name}</p>
|
||||
<p class="list-page-entry-text achievement-completion">${completion}</p>
|
||||
<p class="list-page-entry-text achievement-difficulty">${difficulty}</p>
|
||||
<p class="list-page-entry-text achievement-quality">${quality}</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img id="loading-results" class="ap-loading" src="/static/res/loading.svg" alt="Loading Symbol" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/scripts/template.js"></script>
|
||||
<script src="/static/scripts/common.js"></script>
|
||||
<script src="/static/scripts/search.js"></script>
|
||||
<script src="/static/scripts/search_achievements.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
<link rel="stylesheet" href="/static/styles/theme.css" />
|
||||
<link rel="stylesheet" href="/static/styles/common.css" />
|
||||
<link rel="stylesheet" href="/static/styles/index.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search_games.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
|
@ -21,10 +22,10 @@
|
|||
</template>
|
||||
</div>
|
||||
<div id="content-body">
|
||||
<div id="index-page" class="page">
|
||||
<div id="search-games-page" class="search page">
|
||||
<div class="page-subsection">
|
||||
<div class="page-header">
|
||||
<p class="page-header-text">Achievements Project</p>
|
||||
<p class="page-header-text">Search Games</p>
|
||||
<div class="page-header-separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -126,6 +127,7 @@
|
|||
</div>
|
||||
<script src="/static/scripts/template.js"></script>
|
||||
<script src="/static/scripts/common.js"></script>
|
||||
<script src="/static/scripts/index.js"></script>
|
||||
<script src="/static/scripts/search.js"></script>
|
||||
<script src="/static/scripts/search_games.js"></script>
|
||||
</body>
|
||||
</html>
|
133
frontend/webpage/search_users.html
Normal file
133
frontend/webpage/search_users.html
Normal file
|
@ -0,0 +1,133 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Achievements Project</title>
|
||||
|
||||
<link rel="stylesheet" href="/static/styles/theme.css" />
|
||||
<link rel="stylesheet" href="/static/styles/common.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search.css" />
|
||||
<link rel="stylesheet" href="/static/styles/search_users.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="navbar">
|
||||
<template data-template="navbar: List<Basic>">
|
||||
<div id="navbar-section-${section}" class="navbar-section">
|
||||
<template data-template="navbar-section-${section}: List<Basic>">
|
||||
<div id="navbar-item-${item}" class="navbar-item" data-page-name="${item}">
|
||||
${title}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div id="content-body">
|
||||
<div id="search-users-page" class="search page">
|
||||
<div class="page-subsection">
|
||||
<div class="page-header">
|
||||
<p class="page-header-text">Search Users</p>
|
||||
<div class="page-header-separator"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-subsection">
|
||||
<div id="list-page-search-filters">
|
||||
<div id="list-page-search-dropdown">
|
||||
<div id="search-wrapper" class="page-subsection-wrapper">
|
||||
<div id="list-page-search-pair" class="list-page-search page-subsection-chunk">
|
||||
<label for="achievement-search">Search</label>
|
||||
<input id="achievement-search" type="text" placeholder="Name" name="achievement-search"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="filter-dropdown-wrapper" class="page-subsection-wrapper">
|
||||
<div id="filter-dropdown-stack">
|
||||
<img id="filter-dropdown-button" src="/static/res/dropdown.svg" alt="Dropdown Button"/>
|
||||
<img id="filter-dropdown-button-hover" src="/static/res/dropdown-hover.svg" alt="Dropdown Button"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="list-page-filters-flex">
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">Games</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div id="games-owned-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">Games Owned</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">General</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div id="from-games-owned-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">From My Games</p>
|
||||
</div>
|
||||
<div id="completed-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">Completed</p>
|
||||
</div>
|
||||
<div id="completed-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">Completed</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-filter-section page-subsection-wrapper">
|
||||
<div class="page-subheader">
|
||||
<p class="page-subheader-text">Platforms</p>
|
||||
<div class="page-subheader-separator"></div>
|
||||
</div>
|
||||
<div class="list-page-filter-chunk page-subsection-chunk">
|
||||
<div class="page-subsection-wrapper">
|
||||
<div id="games-owned-filter" class="list-page-filter">
|
||||
<div class="list-page-filter-checkbox"></div>
|
||||
<p class="list-page-filter-name">Games Owned</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-page-partitions">
|
||||
<div class="list-page-list-partition page-subsection-wrapper">
|
||||
<div class="page-subsection-chunk">
|
||||
<div class="list-page-list">
|
||||
<div class="list-page-header">
|
||||
<p class="list-page-entry-icon"></p>
|
||||
<p class="list-page-entry-text achievement-name">Name</p>
|
||||
<p class="list-page-entry-text achievement-description">Description</p>
|
||||
<p class="list-page-entry-text achievement-stages">Stages</p>
|
||||
</div>
|
||||
<template data-template="achievements-page-list: List<Basic>">
|
||||
<div class="list-page-entry">
|
||||
<img class="list-page-entry-icon" src="/static/res/dummy_achievement.png" alt="Achievement Thumbnail"></img>
|
||||
<div class="list-page-entry-text-section">
|
||||
<p class="list-page-entry-text achievement-name">${achievement-name}</p>
|
||||
<p class="list-page-entry-text achievement-description">${achievement-description}</p>
|
||||
<p class="list-page-entry-text achievement-stages">${stages}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/scripts/template.js"></script>
|
||||
<script src="/static/scripts/common.js"></script>
|
||||
<script src="/static/scripts/search.js"></script>
|
||||
<script src="/static/scripts/search_users.js"></script>
|
||||
</body>
|
||||
</html>
|
1
frontend/webpage/static/res/loading.svg
Normal file
1
frontend/webpage/static/res/loading.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><defs><style>.cls-1{fill:#eee;}</style></defs><path class="cls-1" d="M500,904C276.877,904,96,723.12305,96,500S276.877,96,500,96V0C223.8576,0,0,223.8576,0,500c0,276.14233,223.8576,500,500,500A498.43514,498.43514,0,0,0,853.55334,853.55334l-67.8822-67.8822A402.7356,402.7356,0,0,1,500,904Z"/></svg>
|
After Width: | Height: | Size: 392 B |
|
@ -25,7 +25,6 @@ const loadSession = async () => {
|
|||
|
||||
await fetch(`/api/auth/refresh`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@ -52,8 +51,10 @@ const commonTemplates = async () => {
|
|||
{ section: "right" }
|
||||
]);
|
||||
template.apply("navbar-section-left").values([
|
||||
{ item: "project", title: "Project" },
|
||||
{ item: "about", title: "About" }
|
||||
{ item: "achievements", title: "Achievements" },
|
||||
{ item: "users", title: "Users" },
|
||||
{ item: "games", title: "Games" },
|
||||
{ item: "import", title: "Import" }
|
||||
]);
|
||||
if (session) {
|
||||
template.apply("navbar-section-right").values([
|
||||
|
@ -62,34 +63,40 @@ const commonTemplates = async () => {
|
|||
]);
|
||||
} else {
|
||||
template.apply("navbar-section-right").values([
|
||||
{ item: "login", title: "Login" }
|
||||
{ item: "login", title: "Login" }
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
const loadLazyImages = () => {
|
||||
const imgs = document.querySelectorAll(".lazy-img");
|
||||
for (const img of imgs) {
|
||||
img.src = img.dataset.src;
|
||||
}
|
||||
}
|
||||
|
||||
const connectNavbar = () => {
|
||||
const navItems = document.querySelectorAll(".navbar-item");
|
||||
|
||||
if (!session || !session.admin) {
|
||||
document.querySelector("#navbar-item-import").remove();
|
||||
}
|
||||
|
||||
for (const item of navItems) {
|
||||
if (item.dataset.pageName === "logout") {
|
||||
item.addEventListener("click", (clickEvent) => {
|
||||
fetch(`/api/auth/logout`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ key: session.key })
|
||||
})
|
||||
.then(response => {
|
||||
session = undefined;
|
||||
window.location.href = "/login";
|
||||
});
|
||||
session = undefined;
|
||||
window.location.href = "/login";
|
||||
});
|
||||
} else if (item.dataset.pageName === "profile") {
|
||||
item.addEventListener("click", (clickEvent) => window.location.href = `/profile/${session.id}`);
|
||||
} else if (item.dataset.pageName === "project") {
|
||||
item.addEventListener("click", (clickEvent) => window.location.href = `/`);
|
||||
} else {
|
||||
item.addEventListener("click", (clickEvent) => window.location.href = `/${item.dataset.pageName}`);
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
const expandTemplates = async () => {
|
||||
await commonTemplates();
|
||||
}
|
||||
|
||||
const loadFilters = () => {
|
||||
const filtersButton = document.querySelector("#filter-dropdown-stack");
|
||||
const filters = document.querySelector("#list-page-filters-flex");
|
||||
|
||||
filtersButton.addEventListener("click", (clickEvent) => {
|
||||
filtersButton.classList.toggle("active");
|
||||
filters.classList.toggle("active");
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("load", async (loadEvent) => {
|
||||
loadRoot();
|
||||
loadSession();
|
||||
|
||||
await expandTemplates();
|
||||
await template.expand();
|
||||
|
||||
connectNavbar();
|
||||
loadFilters();
|
||||
});
|
|
@ -11,6 +11,7 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
password: document.querySelector("#password"),
|
||||
confirm: document.querySelector("#confirm" )
|
||||
};
|
||||
fields.email.focus();
|
||||
|
||||
const createUser = document.querySelector("#create-user-button");
|
||||
const login = document.querySelector("#login-button");
|
||||
|
@ -80,7 +81,6 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
freeze();
|
||||
fetch(`/api/auth/create_user`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@ -141,7 +141,6 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
freeze();
|
||||
fetch(`/api/auth/login`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
|
|
@ -2,14 +2,25 @@ let profileId = window.location.pathname.split('/').pop();
|
|||
let isReturn = false;
|
||||
let profileData = null;
|
||||
const loadProfile = () => {
|
||||
{
|
||||
const lists = document.querySelectorAll(".profile-list");
|
||||
const lists = document.querySelectorAll(".profile-list");
|
||||
const checkLists = () => {
|
||||
for (const list of lists) {
|
||||
if (list.querySelectorAll(".profile-entry").length === 0) {
|
||||
list.parentElement.removeChild(list);
|
||||
let found = false;
|
||||
const entries = list.querySelectorAll(".profile-entry");
|
||||
for (const entry of entries) {
|
||||
if (window.getComputedStyle(entry).getPropertyValue('display') !== 'none') {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
list.style.display = 'none';
|
||||
} else {
|
||||
list.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
checkLists();
|
||||
|
||||
{
|
||||
const validImageFile = (type) => {
|
||||
|
@ -32,7 +43,6 @@ const loadProfile = () => {
|
|||
if (usernameField.value !== '') {
|
||||
fetch(`/api/user/${profileId}/username`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@ -89,7 +99,6 @@ const loadProfile = () => {
|
|||
|
||||
fetch(`/api/user/${profileId}/image`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
body: data
|
||||
}).then(response => {
|
||||
if (upload.classList.contains("active")) {
|
||||
|
@ -141,6 +150,7 @@ const loadProfile = () => {
|
|||
for (const platform of platforms) {
|
||||
platform.classList.toggle("editing");
|
||||
}
|
||||
checkLists();
|
||||
};
|
||||
editPlatformsButton.addEventListener("click", togglePlatformEdit);
|
||||
savePlatformsButton.addEventListener("click", togglePlatformEdit);
|
||||
|
@ -156,7 +166,6 @@ const loadProfile = () => {
|
|||
steamButtons[1].addEventListener("click", (clickEvent) => {
|
||||
fetch(`/api/user/${profileId}/platforms/remove`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@ -213,11 +222,11 @@ const expandTemplates = async () => {
|
|||
template.apply("profile-platforms-list").promise(profileData.then(data =>
|
||||
data.platforms.map(platform => ({
|
||||
platform_id: platform.id,
|
||||
img: `<img class="profile-entry-icon" src="/api/platform/image/${platform.id}" alt="Steam Logo" />`,
|
||||
img: `<img class="profile-entry-icon" src="/api/platform/${platform.id}/image" alt="Steam Logo" />`,
|
||||
name: platform.name,
|
||||
connected: platform.connected ? "connected" : "",
|
||||
add:
|
||||
(platform.id === 0 ? `<img id="add-steam" class="platform-add" src="https://community.cloudflare.steamstatic.com/public/images/signinthroughsteam/sits_01.png" alt="Add" />` :
|
||||
(platform.id === 0 ? `<img id="add-steam" class="platform-add" src="https://steamcdn-a.akamaihd.net/steamcommunity/public/images/steamworks_docs/english/sits_small.png" alt="Add" />` :
|
||||
(platform.id === 1 ? `<p class="platform-unsupported">Coming soon...</p>` :
|
||||
(platform.id === 2 ? `<p class="platform-unsupported">Coming soon...</p>` :
|
||||
"")))
|
||||
|
@ -228,6 +237,7 @@ const expandTemplates = async () => {
|
|||
window.addEventListener("load", async (loadEvent) => {
|
||||
await loadCommon();
|
||||
|
||||
var importing = document.querySelector("#importing");
|
||||
if (!/\d+/.test(profileId)) {
|
||||
isReturn = true;
|
||||
const platform = profileId;
|
||||
|
@ -238,6 +248,9 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
delete session.lastProfile;
|
||||
}
|
||||
|
||||
const importingText = importing.querySelector("#importing-text");
|
||||
importingText.textContent = `Importing from ${platform}...`;
|
||||
importing.style.display = `flex`;
|
||||
if (platform === 'steam') {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
|
||||
|
@ -246,9 +259,8 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
} else {
|
||||
// Regex courtesy of https://github.com/liamcurry/passport-steam/blob/master/lib/passport-steam/strategy.js
|
||||
var steamId = /^https?:\/\/steamcommunity\.com\/openid\/id\/(\d+)$/.exec(query.get('openid.claimed_id'))[1];
|
||||
await fetch("/api/user/platforms/add", {
|
||||
await fetch(`/api/user/${profileId}/platforms/add`, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
@ -266,13 +278,15 @@ window.addEventListener("load", async (loadEvent) => {
|
|||
} else {
|
||||
// Handle error
|
||||
}
|
||||
importing.remove();
|
||||
|
||||
profileData = fetch(`/api/user/${profileId}`, { method: 'GET', mode: 'cors' })
|
||||
profileData = fetch(`/api/user/${profileId}`, { method: 'GET' })
|
||||
.then(response => response.json());
|
||||
|
||||
await expandTemplates();
|
||||
await template.expand();
|
||||
|
||||
loadLazyImages();
|
||||
connectNavbar();
|
||||
loadProfile();
|
||||
});
|
26
frontend/webpage/static/scripts/search.js
Normal file
26
frontend/webpage/static/scripts/search.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const expandTemplates = async () => {
|
||||
await commonTemplates();
|
||||
}
|
||||
|
||||
const loadFilters = () => {
|
||||
const filtersButton = document.querySelector("#filter-dropdown-stack");
|
||||
const filtersSection = document.querySelector("#list-page-filters-flex");
|
||||
|
||||
filtersButton.addEventListener("click", (clickEvent) => {
|
||||
filtersButton.classList.toggle("active");
|
||||
filtersSection.classList.toggle("active");
|
||||
});
|
||||
|
||||
const filterCheckboxes = document.querySelectorAll(".list-page-filter-checkbox");
|
||||
for (const checkbox of filterCheckboxes) {
|
||||
checkbox.parentElement.addEventListener("click", (clickEvent) => {
|
||||
checkbox.parentElement.classList.toggle("selected");
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const loadCommonSearch = async () => {
|
||||
await loadCommon();
|
||||
|
||||
await expandTemplates();
|
||||
};
|
108
frontend/webpage/static/scripts/search_achievements.js
Normal file
108
frontend/webpage/static/scripts/search_achievements.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
let templateList = null;
|
||||
let templateText = null;
|
||||
const saveTemplate = () => {
|
||||
const templateElement = document.querySelector("#achievement-list-template");
|
||||
templateList = templateElement.parentElement;
|
||||
templateText = templateElement.outerHTML;
|
||||
templateElement.remove();
|
||||
};
|
||||
|
||||
const loadAchievementSearch = () => {
|
||||
const loading = document.querySelector("#loading-results");
|
||||
|
||||
|
||||
const searchButton = document.querySelector("#achievement-search-button");
|
||||
const searchField = document.querySelector("#achievement-search-field" );
|
||||
|
||||
const completed = document.querySelector("#completed-filter");
|
||||
const minCompletion = document.querySelector("#min-completion-filter");
|
||||
const maxCompletion = document.querySelector("#max-completion-filter");
|
||||
const minDifficulty = document.querySelector("#min-difficulty-filter");
|
||||
const maxDifficulty = document.querySelector("#max-difficulty-filter");
|
||||
const minQuality = document.querySelector("#min-quality-filter" );
|
||||
const maxQuality = document.querySelector("#max-quality-filter" );
|
||||
|
||||
let canSearch = true;
|
||||
const loadList = async () => {
|
||||
if (canSearch) {
|
||||
canSearch = false;
|
||||
|
||||
const body = {
|
||||
searchTerm: searchField.value,
|
||||
userId: completed.classList.contains('active') ? session.id : null,
|
||||
completed: completed.classList.contains('active'),
|
||||
minCompletion: minCompletion.value === '' ? null : Number(minCompletion.value),
|
||||
maxCompletion: maxCompletion.value === '' ? null : Number(maxCompletion.value),
|
||||
minDifficulty: minDifficulty.value === '' ? null : Number(minDifficulty.value),
|
||||
maxDifficulty: maxDifficulty.value === '' ? null : Number(maxDifficulty.value),
|
||||
minQuality: minQuality.value === '' ? null : Number(minQuality.value ),
|
||||
maxQuality: maxQuality.value === '' ? null : Number(maxQuality.value ),
|
||||
};
|
||||
console.log(body);
|
||||
let successful = true;
|
||||
if (Number.isNaN(body.minCompletion)) { successful = false; minCompletion.style.backgroundColor = 'var(--error)'; } else { minCompletion.style.backgroundColor = 'var(--foreground)'; }
|
||||
if (Number.isNaN(body.maxCompletion)) { successful = false; maxCompletion.style.backgroundColor = 'var(--error)'; } else { maxCompletion.style.backgroundColor = 'var(--foreground)'; }
|
||||
if (Number.isNaN(body.minDifficulty)) { successful = false; minDifficulty.style.backgroundColor = 'var(--error)'; } else { minDifficulty.style.backgroundColor = 'var(--foreground)'; }
|
||||
if (Number.isNaN(body.maxDifficulty)) { successful = false; maxDifficulty.style.backgroundColor = 'var(--error)'; } else { maxDifficulty.style.backgroundColor = 'var(--foreground)'; }
|
||||
if (Number.isNaN(body.minQuality )) { successful = false; minQuality.style.backgroundColor = 'var(--error)'; } else { minQuality.style.backgroundColor = 'var(--foreground)'; }
|
||||
if (Number.isNaN(body.maxQuality )) { successful = false; maxQuality.style.backgroundColor = 'var(--error)'; } else { maxQuality.style.backgroundColor = 'var(--foreground)'; }
|
||||
|
||||
if (!successful) {
|
||||
canSearch = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (const entry of templateList.querySelectorAll(".list-page-entry")) {
|
||||
entry.remove();
|
||||
}
|
||||
templateList.innerHTML += templateText;
|
||||
loading.style.display = 'block';
|
||||
|
||||
const data = fetch("/api/achievements", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(response => response.json())
|
||||
|
||||
template.clear();
|
||||
template.apply('achievements-page-list').promise(data.then(data => data.map(item => ({
|
||||
achievement_id: item.ID,
|
||||
achievement_name: item.name,
|
||||
game_name: item.game,
|
||||
completion: item.completion == null ? 'N/A' : item.completion + '%',
|
||||
difficulty: item.difficulty == null ? 'N/A' : item.difficulty + ' / 10',
|
||||
quality: item.quality == null ? 'N/A' : item.quality + ' / 10'
|
||||
}))));
|
||||
await template.expand();
|
||||
data.then(data => {
|
||||
loading.style.display = 'none';
|
||||
canSearch = true;
|
||||
loadLazyImages();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
searchButton.addEventListener("click", loadList);
|
||||
searchField.addEventListener("keydown", (keyEvent) => {
|
||||
if (keyEvent.key === 'Enter') {
|
||||
loadList();
|
||||
}
|
||||
});
|
||||
|
||||
loadList();
|
||||
};
|
||||
|
||||
window.addEventListener("load", async (loadEvent) => {
|
||||
await loadCommonSearch();
|
||||
|
||||
saveTemplate();
|
||||
await template.expand();
|
||||
|
||||
connectNavbar();
|
||||
loadFilters();
|
||||
|
||||
await loadAchievementSearch();
|
||||
});
|
|
@ -136,6 +136,10 @@ var template = template || {};
|
|||
}
|
||||
};
|
||||
|
||||
template.clear = () => {
|
||||
templateEntryMap.clear();
|
||||
}
|
||||
|
||||
const parseType = (type) => {
|
||||
let result = type.match(/^\s*(\w+)\s*(?:<(.*)>)?\s*$/);
|
||||
let id = result[1];
|
||||
|
|
|
@ -70,6 +70,15 @@ html, body {
|
|||
background-color: var(--accent-value3);
|
||||
}
|
||||
|
||||
@keyframes load {
|
||||
from { transform: rotateZ(0deg ); }
|
||||
to { transform: rotateZ(360deg); }
|
||||
}
|
||||
|
||||
.ap-loading {
|
||||
animation: 1.5s cubic-bezier(0.4, 0.15, 0.6, 0.85) 0s infinite running load;
|
||||
}
|
||||
|
||||
.ap-button {
|
||||
color: var(--foreground);
|
||||
background-color: var(--accent-value2);
|
||||
|
@ -226,201 +235,3 @@ html, body {
|
|||
|
||||
background-color: var(--accent-value3);
|
||||
}
|
||||
|
||||
.list-page-search {
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-page-search > label,
|
||||
.list-page-search > input {
|
||||
box-sizing: border-box;
|
||||
padding: 12px 20px;
|
||||
|
||||
color: var(--foreground);
|
||||
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.list-page-search > label {
|
||||
background-color: var(--accent-value2);
|
||||
}
|
||||
|
||||
.list-page-search > label:hover {
|
||||
background-color: var(--accent-value3);
|
||||
}
|
||||
|
||||
.list-page-search > label:active {
|
||||
background-color: var(--accent-value1);
|
||||
|
||||
transition-property: background-color;
|
||||
transition-duration: 0.15s;
|
||||
}
|
||||
|
||||
.list-page-search > input {
|
||||
background-color: var(--distinction);
|
||||
|
||||
border: 0;
|
||||
|
||||
flex-grow: 1;
|
||||
|
||||
outline: none;
|
||||
|
||||
transition-property: background-color, color;
|
||||
transition-duration: 0.075s;
|
||||
}
|
||||
|
||||
.list-page-search > input:focus {
|
||||
background-color: var(--foreground);
|
||||
|
||||
color: var(--background);
|
||||
}
|
||||
|
||||
.list-page-partitions {
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.list-page-filter-partition {
|
||||
width: 20%;
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.list-page-filter-chunk {
|
||||
background-color: var(--distinction);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.list-page-filter {
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-page-filter-checkbox {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
|
||||
background-color: var(--foreground);
|
||||
|
||||
border: 3px solid var(--foreground);
|
||||
border-radius: 8px;
|
||||
|
||||
transition-property: background-color, border-color;
|
||||
transition-duration: 0.15s;
|
||||
}
|
||||
|
||||
.list-page-filter:hover > .list-page-filter-checkbox {
|
||||
background-color: var(--foreground);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter.selected > .list-page-filter-checkbox {
|
||||
background-color: var(--selected-accent1);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter.selected:hover > .list-page-filter-checkbox {
|
||||
background-color: var(--selected-accent0);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter-name {
|
||||
margin: 0;
|
||||
padding: 16px;
|
||||
|
||||
color: var(--foreground);
|
||||
|
||||
font-size: 24px;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.list-page-list-partition {
|
||||
box-sizing: border-box;
|
||||
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.list-page-list {
|
||||
border-radius: 8px;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.list-page-header {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
background-color: var(--accent-value2);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: var(--foreground);
|
||||
font-size: 24px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-page-entry {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
background-color: var(--distinction);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: var(--foreground);
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.list-page-entry-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.list-page-entry-text {
|
||||
box-sizing: border-box;
|
||||
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
border-top: 1px solid var(--background);
|
||||
}
|
||||
|
||||
.list-page-header > .list-page-entry-text {
|
||||
border: 0;
|
||||
}
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
#index-page {
|
||||
max-width: 1600px;
|
||||
}
|
||||
|
||||
#list-page-search-filters {
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
#list-page-search-dropdown {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#search-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#list-page-search-pair {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#filter-dropdown-wrapper {
|
||||
box-sizing: border-box;
|
||||
height: 84px;
|
||||
width: 84px;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack.active {
|
||||
transform: rotateZ(-90deg);
|
||||
}
|
||||
|
||||
#filter-dropdown-button {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: block;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack:hover > #filter-dropdown-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#filter-dropdown-button-hover {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack:hover > #filter-dropdown-button-hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#list-page-filters-flex {
|
||||
display: none;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#list-page-filters-flex.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.list-page-filter-section {
|
||||
box-sizing: border-box;
|
||||
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#list-page-filters-background {
|
||||
background-color: var(--distinction);
|
||||
}
|
||||
|
||||
.list-page-entry-text.achievement-name {
|
||||
flex-grow: 3;
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.list-page-entry-text.achievement-description {
|
||||
flex-grow: 6;
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.list-page-entry-text.achievement-stages {
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
--form-spacing: 48px;
|
||||
|
||||
--element-spacing: 12px;
|
||||
|
||||
--error: #F95959;
|
||||
}
|
||||
|
||||
#login-page {
|
||||
|
|
|
@ -2,6 +2,26 @@
|
|||
max-width: 1600px;
|
||||
}
|
||||
|
||||
#importing {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
#importing-text {
|
||||
margin: 0;
|
||||
height: 96px;
|
||||
font-size: 64px;
|
||||
line-height: 96px;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
#importing-loading {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.profile-list {
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
@ -150,7 +170,7 @@
|
|||
border-radius: 8px;
|
||||
object-fit: contain;
|
||||
|
||||
background-color: var(--background);
|
||||
background-color: var(--background-dark);
|
||||
|
||||
position: absolute;
|
||||
}
|
||||
|
@ -178,7 +198,7 @@
|
|||
|
||||
border-radius: 8px;
|
||||
|
||||
background-color: var(--background);
|
||||
background-color: var(--background-dark);
|
||||
opacity: 0.8;
|
||||
|
||||
display: block;
|
||||
|
|
330
frontend/webpage/static/styles/search.css
Normal file
330
frontend/webpage/static/styles/search.css
Normal file
|
@ -0,0 +1,330 @@
|
|||
#list-page-search-filters {
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
#list-page-search-dropdown {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#search-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#list-page-search-pair {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#filter-dropdown-wrapper {
|
||||
box-sizing: border-box;
|
||||
height: 84px;
|
||||
width: 84px;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack.active {
|
||||
transform: rotateZ(-90deg);
|
||||
}
|
||||
|
||||
#filter-dropdown-button {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: block;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack:hover > #filter-dropdown-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#filter-dropdown-button-hover {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
#filter-dropdown-stack:hover > #filter-dropdown-button-hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#list-page-filters-flex {
|
||||
display: none;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#list-page-filters-flex.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.list-page-filter-section {
|
||||
box-sizing: border-box;
|
||||
|
||||
flex-basis: max-content;
|
||||
flex-grow: 1;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list-page-filter-partition {
|
||||
width: 20%;
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.list-page-filter-chunk {
|
||||
background-color: var(--distinction);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.list-page-filter {
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-page-filter-checkbox {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
|
||||
background-color: var(--foreground);
|
||||
|
||||
border: 3px solid var(--foreground);
|
||||
border-radius: 8px;
|
||||
|
||||
transition-property: background-color, border-color;
|
||||
transition-duration: 0.15s;
|
||||
}
|
||||
|
||||
.list-page-filter:hover > .list-page-filter-checkbox {
|
||||
background-color: var(--foreground);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter.selected > .list-page-filter-checkbox {
|
||||
background-color: var(--selected-accent1);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter.selected:hover > .list-page-filter-checkbox {
|
||||
background-color: var(--selected-accent0);
|
||||
border-color: var(--selected-accent1);
|
||||
}
|
||||
|
||||
.list-page-filter-name,
|
||||
.list-page-filter-label {
|
||||
margin: 0;
|
||||
padding: 16px;
|
||||
|
||||
color: var(--foreground);
|
||||
|
||||
font-size: 24px;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.list-page-filter-label {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.list-page-filter-param {
|
||||
padding: 4px;
|
||||
width: 25%;
|
||||
|
||||
font-size: 24px;
|
||||
color: var(--background);
|
||||
background-color: var(--foreground);
|
||||
|
||||
border-radius: 8px;
|
||||
|
||||
border: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#list-page-filters-background {
|
||||
background-color: var(--distinction);
|
||||
}
|
||||
|
||||
.list-page-entry-text {
|
||||
flex-basis: 0;
|
||||
}
|
||||
|
||||
.page.search {
|
||||
max-width: 1720px;
|
||||
}
|
||||
|
||||
.list-page-search {
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.list-page-search > label,
|
||||
.list-page-search > input {
|
||||
box-sizing: border-box;
|
||||
padding: 12px 20px;
|
||||
|
||||
color: var(--foreground);
|
||||
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.list-page-search > label {
|
||||
background-color: var(--accent-value2);
|
||||
}
|
||||
|
||||
.list-page-search > label:hover {
|
||||
background-color: var(--accent-value3);
|
||||
}
|
||||
|
||||
.list-page-search > label:active {
|
||||
background-color: var(--accent-value1);
|
||||
|
||||
transition-property: background-color;
|
||||
transition-duration: 0.15s;
|
||||
}
|
||||
|
||||
.list-page-search > input {
|
||||
background-color: var(--distinction);
|
||||
|
||||
border: 0;
|
||||
|
||||
flex-grow: 1;
|
||||
|
||||
outline: none;
|
||||
|
||||
transition-property: background-color, color;
|
||||
transition-duration: 0.075s;
|
||||
}
|
||||
|
||||
.list-page-search > input:focus {
|
||||
background-color: var(--foreground);
|
||||
|
||||
color: var(--background);
|
||||
}
|
||||
|
||||
.list-page-partitions {
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
.list-page-list-partition {
|
||||
box-sizing: border-box;
|
||||
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.list-page-list {
|
||||
border-radius: 8px;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.list-page-header {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
background-color: var(--accent-value2);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: var(--foreground);
|
||||
font-size: 24px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-page-entry {
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
background-color: var(--distinction);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: var(--foreground);
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.list-page-entry-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.list-page-entry-text {
|
||||
box-sizing: border-box;
|
||||
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.list-page-entry > .list-page-entry-text {
|
||||
border-top: 1px solid var(--background);
|
||||
border-left: 1px solid var(--background);
|
||||
}
|
||||
|
||||
.list-page-header > .list-page-entry-text {
|
||||
border-left: 1px solid var(--accent-value0);
|
||||
}
|
||||
|
||||
#loading-results {
|
||||
margin: 16px 0;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
object-fit: contain;
|
||||
|
||||
display: none;
|
||||
}
|
5
frontend/webpage/static/styles/search_achievements.css
Normal file
5
frontend/webpage/static/styles/search_achievements.css
Normal file
|
@ -0,0 +1,5 @@
|
|||
.list-page-entry-text.achievement-game-name { flex-grow: 1.75; }
|
||||
.list-page-entry-text.achievement-name { flex-grow: 2; }
|
||||
.list-page-entry-text.achievement-completion { flex-grow: 1; }
|
||||
.list-page-entry-text.achievement-quality { flex-grow: 1; }
|
||||
.list-page-entry-text.achievement-difficulty { flex-grow: 1; }
|
|
@ -18,4 +18,6 @@
|
|||
|
||||
--selected-accent0: #2266CC;
|
||||
--selected-accent1: #3388FF;
|
||||
|
||||
--error: #F95959;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue