Added SteamAPI and achievement searching
This commit is contained in:
parent
b229ff9a15
commit
627cc810ed
61 changed files with 2781 additions and 903 deletions
|
@ -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];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue