-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #98 from koddsson/update
Update
- Loading branch information
Showing
9 changed files
with
877 additions
and
1,525 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import config from '@koddsson/eslint-config'; | ||
|
||
export default [ | ||
...config | ||
]; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,25 +17,25 @@ | |
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/koddsson/web-dev.git" | ||
"url": "git+https://github.com/koddsson/geopedia.git" | ||
}, | ||
"keywords": [], | ||
"author": "Kristján Oddsson <[email protected]>", | ||
"license": "ISC", | ||
"bugs": { | ||
"url": "https://github.com/koddsson/web-dev/issues" | ||
"url": "https://github.com/koddsson/geopedia/issues" | ||
}, | ||
"prettier": "@github/prettier-config", | ||
"homepage": "https://github.com/koddsson/web-dev#readme", | ||
"prettier": "@koddsson/prettier-config", | ||
"homepage": "https://github.com/koddsson/geopedia#readme", | ||
"devDependencies": { | ||
"@github/prettier-config": "^0.0.6", | ||
"@koddsson/eslint-config": "^1.1.0", | ||
"@koddsson/prettier-config": "^2.0.0", | ||
"@open-wc/testing": "^4.0.0", | ||
"@web/dev-server": "^0.4.4", | ||
"@web/dev-server-esbuild": "^1.0.2", | ||
"@web/rollup-plugin-html": "^2.3.0", | ||
"@web/test-runner": "^0.18.1", | ||
"eslint": "^8.57.0", | ||
"eslint-plugin-github": "^4.10.2", | ||
"open-props": "^1.7.4", | ||
"postcss": "^8.4.38", | ||
"postcss-cli": "^11.0.0", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
interface DatabaseEntry { | ||
id: string; | ||
} | ||
|
||
type DatabaseEntryId = string; | ||
|
||
export class Database<T extends DatabaseEntry> { | ||
constructor(public key: string) {} | ||
|
||
save(datum: T) { | ||
const existingData = this.getAll(); | ||
existingData.push(datum); | ||
|
||
localStorage.setItem(this.key, JSON.stringify(existingData)); | ||
} | ||
|
||
remove(id: DatabaseEntryId) { | ||
const data = this.getAll().filter((item) => item.id !== id); | ||
|
||
localStorage.setItem(this.key, JSON.stringify(data)); | ||
} | ||
|
||
get(id: DatabaseEntryId): T | undefined { | ||
const all = this.getAll(); | ||
return all.find((item) => item.id === id); | ||
} | ||
|
||
getAll(): T[] { | ||
return JSON.parse(localStorage.getItem(this.key) || '[]'); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
function handleError(event: ErrorEvent | PromiseRejectionEvent) { | ||
const searchParams = new URLSearchParams(window.location.search) | ||
if (!searchParams.has('debug')) { | ||
return | ||
const searchParameters = new URLSearchParams(window.location.search); | ||
if (!searchParameters.has('debug')) { | ||
return; | ||
} | ||
|
||
if (event instanceof ErrorEvent) { | ||
alert(event.message) | ||
alert(event.message); | ||
} else if (event instanceof PromiseRejectionEvent) { | ||
alert(event.reason) | ||
alert(event.reason); | ||
} else { | ||
alert(JSON.stringify(event, null, 4)) | ||
alert(JSON.stringify(event, undefined, 4)); | ||
} | ||
} | ||
|
||
window.addEventListener("error", handleError) | ||
window.addEventListener('unhandledrejection', handleError) | ||
window.addEventListener('error', handleError); | ||
window.addEventListener('unhandledrejection', handleError); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,124 @@ | ||
import {Database} from './db' | ||
import {ready, html} from './utils' | ||
import { Database } from './database'; | ||
import { ready, html } from './utils'; | ||
|
||
interface Location { | ||
title: string | ||
pageid: number | ||
primary: string | ||
ns: number | ||
lat: number | ||
lon: number | ||
dist: number | ||
title: string; | ||
pageid: number; | ||
primary: string; | ||
ns: number; | ||
lat: number; | ||
lon: number; | ||
dist: number; | ||
} | ||
|
||
interface LocationEntry { | ||
id: string | ||
location: Location | ||
id: string; | ||
location: Location; | ||
} | ||
|
||
const db = new Database<LocationEntry>('locations') | ||
const database = new Database<LocationEntry>('locations'); | ||
|
||
function getCurrentPosition(): Promise<{coords: {latitude: number, longitude: number}}> { | ||
function getCurrentPosition(): Promise<{ | ||
coords: { latitude: number; longitude: number }; | ||
}> { | ||
return new Promise((resolve, reject) => { | ||
navigator.geolocation.getCurrentPosition(resolve, reject, { | ||
enableHighAccuracy: false, | ||
timeout: 5000, | ||
maximumAge: 60000, | ||
maximumAge: 60_000, | ||
}); | ||
}) | ||
}); | ||
} | ||
|
||
async function findPagesNear(latitude: number, longitude: number): Promise<Location[]> { | ||
const url = new URL('https://en.wikipedia.org/w/api.php') | ||
async function findPagesNear( | ||
latitude: number, | ||
longitude: number, | ||
): Promise<Location[]> { | ||
const url = new URL('https://en.wikipedia.org/w/api.php'); | ||
url.search = new URLSearchParams({ | ||
action: 'query', | ||
list: 'geosearch', | ||
origin: '*', | ||
gscoord: `${latitude}|${longitude}`, | ||
gsradius: '10000', | ||
gslimit: '1', | ||
format: 'json' | ||
}).toString() | ||
format: 'json', | ||
}).toString(); | ||
|
||
const headers = new Headers({Accept: 'application/json'}) | ||
const response = await fetch(url, {headers}) | ||
const json = await response.json() | ||
const headers = new Headers({ Accept: 'application/json' }); | ||
const response = await fetch(url, { headers }); | ||
const json = await response.json(); | ||
|
||
return json.query.geosearch | ||
return json.query.geosearch; | ||
} | ||
|
||
const pageTextCache = new Database<{id: string, extract: string}>('page-text-cache') | ||
const pageTextCache = new Database<{ id: string; extract: string }>( | ||
'page-text-cache', | ||
); | ||
|
||
async function getPageText(pageid: string) { | ||
const cacheHit = pageTextCache.get(pageid) | ||
const cacheHit = pageTextCache.get(pageid); | ||
if (cacheHit) { | ||
return cacheHit.extract | ||
return cacheHit.extract; | ||
} | ||
const url = new URL('https://en.wikipedia.org/w/api.php') | ||
const url = new URL('https://en.wikipedia.org/w/api.php'); | ||
url.search = new URLSearchParams({ | ||
action: 'query', | ||
prop: 'extracts', | ||
exintro: 'true', | ||
explaintext: 'true', | ||
pageids: pageid, | ||
origin: '*', | ||
format: 'json' | ||
}).toString() | ||
const headers = new Headers({Accept: 'application/json'}) | ||
const response = await fetch(url, {headers}) | ||
const json = await response.json() | ||
const extract = json.query.pages[pageid].extract | ||
pageTextCache.save({id: pageid, extract}) | ||
return extract | ||
format: 'json', | ||
}).toString(); | ||
|
||
const headers = new Headers({ Accept: 'application/json' }); | ||
const response = await fetch(url, { headers }); | ||
const json = await response.json(); | ||
const extract = json.query.pages[pageid].extract; | ||
pageTextCache.save({ id: pageid, extract }); | ||
return extract; | ||
} | ||
|
||
async function generatePlace() { | ||
const {coords: {latitude, longitude}} = await getCurrentPosition() | ||
const locations = await findPagesNear(latitude, longitude) | ||
const location = locations[0] | ||
const { | ||
coords: { latitude, longitude }, | ||
} = await getCurrentPosition(); | ||
const locations = await findPagesNear(latitude, longitude); | ||
const location = locations[0]; | ||
|
||
db.save({id: location.pageid.toString(), location}) | ||
database.save({ id: location.pageid.toString(), location }); | ||
|
||
renderLocation(location) | ||
renderLocation(location); | ||
} | ||
|
||
async function renderLocation(location: Location) { | ||
const text = await getPageText(location.pageid.toString()) | ||
const text = await getPageText(location.pageid.toString()); | ||
|
||
document.querySelector('#locations')?.prepend(...html`<article><h2>${location.title}</h2><div>${text}</div><div class="location-actions"><button data-remove-location="${location.pageid}">Remove</button><div></article>`) | ||
document | ||
.querySelector('#locations') | ||
?.prepend( | ||
...html`<article><h2>${location.title}</h2><div>${text}</div><div class="location-actions"><button data-remove-location="${location.pageid}">Remove</button><div></article>`, | ||
); | ||
} | ||
|
||
await ready() | ||
const entries = db.getAll().sort() | ||
for (const {location} of entries) { | ||
await renderLocation(location) | ||
await ready(); | ||
const entries = database.getAll().sort(); | ||
for (const { location } of entries) { | ||
await renderLocation(location); | ||
} | ||
|
||
document.querySelector('#find-nearest-place')?.addEventListener('click', () => { | ||
generatePlace() | ||
}) | ||
generatePlace(); | ||
}); | ||
|
||
document.addEventListener('click', function(event) { | ||
const target = event.target as HTMLElement | ||
document.addEventListener('click', function (event) { | ||
const target = event.target as HTMLElement; | ||
if (target.matches('button[data-remove-location]')) { | ||
const id = target.getAttribute('data-remove-location')! | ||
db.remove(id) | ||
target.closest('article')?.remove() | ||
const id = target.dataset.removeLocation!; | ||
database.remove(id); | ||
target.closest('article')?.remove(); | ||
} | ||
}) | ||
}); | ||
|
||
export {} | ||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,24 @@ | ||
export function ready(): Promise<void> { | ||
return new Promise(resolve => { | ||
if (document.readyState === 'interactive' || document.readyState === 'complete') { | ||
resolve() | ||
return new Promise((resolve) => { | ||
if ( | ||
document.readyState === 'interactive' || | ||
document.readyState === 'complete' | ||
) { | ||
resolve(); | ||
} else { | ||
document.addEventListener('DOMContentLoaded', () => resolve()) | ||
document.addEventListener('DOMContentLoaded', () => resolve()); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
const parser = new DOMParser() | ||
const parser = new DOMParser(); | ||
|
||
export function html(strings: TemplateStringsArray, ...values: unknown[]): HTMLCollection { | ||
return parser.parseFromString(String.raw({raw: strings}, ...values), 'text/html').body.children | ||
export function html( | ||
strings: TemplateStringsArray, | ||
...values: unknown[] | ||
): HTMLCollection { | ||
return parser.parseFromString( | ||
String.raw({ raw: strings }, ...values), | ||
'text/html', | ||
).body.children; | ||
} |