Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from mapachurro/term-link
Browse files Browse the repository at this point in the history
Term link
  • Loading branch information
mapachurro authored May 29, 2024
2 parents 1aa5ac9 + 01caa84 commit 6408578
Show file tree
Hide file tree
Showing 70 changed files with 37,897 additions and 764 deletions.
4 changes: 1 addition & 3 deletions data/export-definitions.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const exportDefinitions = {
"0x API": {
"term": "0x API",
"phonetic": "",
"partOfSpeech": "",
"term": "0x API",,
"definition": (
<>
The 0x API is the liquidity and data endpoint for DeFi. It lets you access aggregated liquidity from tens of on-chain and off-chain decentralized exchange networks, across multiple blockchains. It comes with many parameters to customize your requests for your application and your users:\n\nAPI References
Expand Down
1 change: 1 addition & 0 deletions i18n/locales/src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions i18n/locales/src/i18n/locales/es/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
22 changes: 22 additions & 0 deletions i18next-scanner.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const path = require('path');

module.exports = {
input: ['src/**/*.{js,jsx}'], // Specify the input files to scan
output: 'src/i18n/locales/', // Specify the output directory for the translation files
options: {
debug: true, // Enable debugging
removeUnusedKeys: false, // Remove unused translation keys
func: {
list: ['i18next.t', 'i18n.t'], // List of functions to scan for translation keys
extensions: ['.js', '.jsx'] // File extensions to scan
},
lngs: ['en', 'es', 'ar', 'de', 'fr', 'id', 'it', 'ja', 'ko', 'nl', 'pt-br', 'ru', 'th', 'tl', 'tr', 'uk', 'vi', 'zh-cn'], // List of languages to generate translation files for
ns: ['translation'], // Namespace to use for translation keys
defaultLng: 'en', // Default language
resource: {
loadPath: 'src/i18n/locales/{{lng}}/{{ns}}.json', // Path to load existing translation files
savePath: 'src/i18n/locales/{{lng}}/{{ns}}.json', // Path to save updated translation files
jsonIndent: 2 // Indentation for the JSON files
}
}
};
12 changes: 0 additions & 12 deletions index.jsx

This file was deleted.

1,204 changes: 1,016 additions & 188 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
{
"name": "education-dao-glossary",
"version": "0.9",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@vitejs/plugin-react-swc": "^3.6.0",
"i18next": "^23.10.0",
"lunr": "^2.3.9",
"lunr-languages": "^1.14.0",
"react-i18next": "^14.1.0",
"react-router-dom": "^6.23.1",
"vite-plugin-svgr": "^4.2.0",
"vite-tsconfig-paths": "^4.3.1",
"web-vitals": "^3.0.4"
"vite-tsconfig-paths": "^4.3.1"
},
"scripts": {
"start": "vite",
"build": "tsc && vite build",
"serve": "vite preview",
"test": "vitest",
"test:coverage": "vitest run --coverage --watch=false"
"test:coverage": "vitest run --coverage --watch=false",
"extract": "i18next-scanner --config i18next-scanner.config.js"
},
"eslintConfig": {
"extends": [
Expand Down Expand Up @@ -45,11 +50,12 @@
"@svgr/webpack": "^8.1.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.3.1",
"i18next-scanner": "^4.4.0",
"jsdom": "^24.0.0",
"nth-check": "^2.1.1",
"postcss": "^8.4.31",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"serve": "^14.2.0",
"vite": "^5.1.6",
"vitest": "^1.3.1"
Expand Down
Binary file added public/education-dao-circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 48 additions & 35 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,57 @@
import terms from "./terms";
import Term from "./termStruct";
import { useState, useEffect } from "react";
import { urlToPath } from "./Link";
import { Breadcrumbs } from "./Breadcrumbs";

const DEFAULT = "permissionless distribution";
import React, { useState } from 'react';
import { Routes, Route, useNavigate } from 'react-router-dom';
import Search from './components/Search';
import index from './searchIndex';
import terms from './terms.json';
import EntryPage from './EntryPage';
import Navbar from './components/Navbar'; // Import the Navbar

function App() {
const [currentPath, setCurrentPath] = useState(urlToPath());
useEffect(() => {
const onLocationChange = () => {
setCurrentPath(urlToPath());
};
window.addEventListener("navigate", onLocationChange);
window.addEventListener("popstate", onLocationChange);
const [searchResults, setSearchResults] = useState([]);
const navigate = useNavigate();

return () => {
window.removeEventListener("navigate", onLocationChange);
window.removeEventListener("popstate", onLocationChange);
};
}, []);
const handleSearch = (query) => {
console.log('Searching for:', query);
const results = index.search(query);
console.log('Search results:', results);
const formattedResults = results.map((result) => ({
term: result.ref,
}));
setSearchResults(formattedResults);
console.log('Updated searchResults:', formattedResults);
};

let word = currentPath.length > 0 ? currentPath.at(-1) : DEFAULT;
if (!(word in terms) || currentPath.length === 0) {
word = DEFAULT;
window.location.pathname = `/${DEFAULT}`;
}
const term = terms[word];
const allTerms = Object.keys(terms["0"]["terms"]);

return (
<>
<Breadcrumbs segments={currentPath} />

<Term
word={word}
definition={term.definition}
phonetic={term.phonetic}
partOfSpeech={term.partOfSpeech}
/>
</>
<div>
<Navbar /> {/* Add the Navbar */}
<div>
<h2>Search the Education DAO Glossary:</h2>
</div>
<Search onSearch={handleSearch} />
<Routes>
<Route
path="/"
element={
<ul>
{searchResults.map((result) => (
<li
key={result.term}
onClick={() => navigate(`/term/${encodeURIComponent(result.term)}`)}
style={{
cursor: allTerms.includes(result.term) ? 'pointer' : 'default',
}}
>
{result.term}
</li>
))}
</ul>
}
/>
<Route path="/term/:termKey" element={<EntryPage />} />
</Routes>
</div>
);
}

Expand Down
47 changes: 28 additions & 19 deletions src/Breadcrumbs.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import { Link } from "./Link";
import "./Breadcrumbs.css";
import { Fragment } from "react";

export function Breadcrumbs({ segments }) {
const homeLink = (
<Link here="/" key="home">
Home
</Link>
);

let path = "";
const result = [
<p className="split" key={`/`}>
/
</p>,
];
const result = [homeLink];

for (let i = 0; i < segments.length; i++) {
const v = segments[i];
if (i === segments.length - 1) {
result.push(<Fragment key={"last"}>{v}</Fragment>);
} else {
path += v;
result.push(
<Link here={path} key={path}>
{v}
</Link>
);
path += v;
const isLast = i === segments.length - 1;

// Render regular text instead of a link for the current page
const breadcrumb = isLast ? (
<span key={path}>{v}</span>
) : (
<Link here={path} key={path}>
{v}
</Link>
);

result.push(breadcrumb);

// Add a "/" separator after each segment except for the last one
if (!isLast) {
result.push(
<p className="split" key={`${path}/`}>
<span className="split" key={`${path}/`}>
/
</p>
</span>
);
path += "/";
}
path += "/";
}
console.log(result);

return <div className="Breadcrumbs">{result}</div>;
}
34 changes: 34 additions & 0 deletions src/EntryPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import terms from './terms.json';
import linkedDefinitions from './linked-definitions.jsx';

function EntryPage() {
const { termKey } = useParams();
const [termContent, setTermContent] = useState(null);

useEffect(() => {
const termData = terms.find(term => term.terms[termKey]);
if (termData) {
setTermContent(termData.terms[termKey]);
} else {
console.error(`Term "${termKey}" not found`);
}
}, [termKey]);

if (!termContent) {
return <div>Loading...</div>;
}

const linkedDefinition = linkedDefinitions[termKey]?.definition || termContent.definition;

return (
<div>
<h1>{termContent.term}</h1>
<p>{linkedDefinition}</p>
{/* Render other content based on term data */}
</div>
);
}

export default EntryPage;
45 changes: 45 additions & 0 deletions src/Home.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Search from './components/Search';
import index from './searchIndex';
import terms from './terms';

function Home() {
const [searchResults, setSearchResults] = useState([]);
const navigate = useNavigate();

const handleSearch = (query) => {
console.log('Searching for:', query);
const results = index.search(query);
console.log('Search results:', results);
const formattedResults = results.map((result) => ({
term: result.ref,
}));
setSearchResults(formattedResults);
console.log('Updated searchResults:', formattedResults);
};

const allTerms = Object.keys(terms["0"]["terms"]);

return (
<div>
<h2>Search the Education DAO Glossary:</h2>
<Search onSearch={handleSearch} />
<ul>
{searchResults.map((result) => (
<li
key={result.term}
onClick={() => navigate(`/term/${result.term}`)}
style={{
cursor: allTerms.includes(result.term) ? 'pointer' : 'default',
}}
>
{result.term}
</li>
))}
</ul>
</div>
);
}

export default Home;
38 changes: 8 additions & 30 deletions src/Link.jsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,17 @@
import { useMemo } from "react";
import React from 'react';
import { useNavigate } from 'react-router-dom';

export function Link({ to, here, children }) {
if (to && here) {
throw new Error();
}
const loc = useMemo(() => {
let location;
if (here) {
location = `/${here}`;
} else {
location = urlToPath();
location.push(to);
location = `/${location.join("/")}`;
}
return location;
}, [to, here]);
export function Link({ to, children }) {
const navigate = useNavigate();

const preventReload = (event) => {
const handleClick = (event) => {
event.preventDefault();
console.log(loc);
window.history.pushState({}, "", loc);
const navigationEvent = new PopStateEvent("navigate");
window.dispatchEvent(navigationEvent);
navigate(to);
};

return (
<a href={loc} onClick={preventReload}>
<a href={to} onClick={handleClick}>
{children}
</a>
);
}

export function urlToPath() {
return window.location.pathname
.slice(1)
.split("/")
.filter((v) => v.length)
.map((v) => decodeURIComponent(v));
}
2 changes: 1 addition & 1 deletion src/Term.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.Definition {
.Term {
max-width: 35rem;
}
.declaration {
Expand Down
7 changes: 7 additions & 0 deletions src/components/Definition.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const Definition = ({ definition }) => {
return <div>{definition}</div>;
};

export default Definition;
Loading

0 comments on commit 6408578

Please sign in to comment.