Add Wikipedia page box
This commit is contained in:
parent
df34239256
commit
9df263c362
12 changed files with 3605 additions and 3457 deletions
|
@ -62,9 +62,29 @@ export class UIEventSource<T> {
|
|||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a promise into a UIVentsource, sets the UIEVentSource when the result is calculated.
|
||||
* If the promise fails, the value will stay undefined
|
||||
* @param promise
|
||||
* @constructor
|
||||
*/
|
||||
public static FromPromise<T>(promise : Promise<T>): UIEventSource<T>{
|
||||
const src = new UIEventSource<T>(undefined)
|
||||
promise?.then(d => src.setData(d))
|
||||
promise?.catch(err => console.warn("Promise failed:", err))
|
||||
return src
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a promise into a UIVentsource, sets the UIEVentSource when the result is calculated.
|
||||
* If the promise fails, the value will stay undefined
|
||||
* @param promise
|
||||
* @constructor
|
||||
*/
|
||||
public static FromPromiseWithErr<T>(promise : Promise<T>): UIEventSource<{success: T} | {error: any}>{
|
||||
const src = new UIEventSource<{success: T}|{error: any}>(undefined)
|
||||
promise?.then(d => src.setData({success:d}))
|
||||
promise?.catch(err => src.setData({error: err}))
|
||||
return src
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Some usefull utility functions around the wikipedia API
|
||||
*/
|
||||
import {Utils} from "../../Utils";
|
||||
import WikipediaBox from "../../UI/WikipediaBox";
|
||||
|
||||
export default class Wikipedia {
|
||||
|
||||
/**
|
||||
* When getting a wikipedia page data result, some elements (e.g. navigation, infoboxes, ...) should be removed if 'removeInfoBoxes' is set.
|
||||
* We do this based on the classes. This set contains a blacklist of the classes to remove
|
||||
* @private
|
||||
*/
|
||||
private static readonly classesToRemove = [
|
||||
"shortdescription",
|
||||
"sidebar",
|
||||
"infobox",
|
||||
"mw-editsection",
|
||||
"hatnote" // Often redirects
|
||||
]
|
||||
|
||||
public static async GetArticle(options: {
|
||||
pageName: string,
|
||||
language?: "en" | string,
|
||||
section?: number,
|
||||
}): Promise<string> {
|
||||
|
||||
let section = ""
|
||||
if (options.section !== undefined) {
|
||||
section = "§ion=" + options.section
|
||||
}
|
||||
const url = `https://${options.language ?? "en"}.wikipedia.org/w/api.php?action=parse${section}&format=json&origin=*&prop=text&page=` + options.pageName
|
||||
const response = await Utils.downloadJson(url)
|
||||
const html = response["parse"]["text"]["*"];
|
||||
|
||||
const div = document.createElement("div")
|
||||
div.innerHTML = html
|
||||
const content = Array.from(div.children)[0]
|
||||
|
||||
for (const forbiddenClass of Wikipedia.classesToRemove) {
|
||||
const toRemove = content.getElementsByClassName(forbiddenClass)
|
||||
for (const toRemoveElement of Array.from(toRemove)) {
|
||||
toRemoveElement.parentElement?.removeChild(toRemoveElement)
|
||||
}
|
||||
}
|
||||
return content.innerHTML;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,17 @@
|
|||
import {FixedUiElement} from "./FixedUiElement";
|
||||
import {Translation} from "../i18n/Translation";
|
||||
import Combine from "./Combine";
|
||||
import Svg from "../../Svg";
|
||||
import Translations from "../i18n/Translations";
|
||||
|
||||
export default class Loading extends FixedUiElement {
|
||||
constructor() {
|
||||
super("Loading..."); // TODO to be improved
|
||||
export default class Loading extends Combine {
|
||||
constructor(msg?: Translation | string) {
|
||||
const t = Translations.T(msg ) ?? Translations.t.general.loading.Clone();
|
||||
t.SetClass("pl-2")
|
||||
super([
|
||||
Svg.loading_svg().SetClass("animate-spin").SetStyle("width: 1.5rem; height: 1.5rem; margin-bottom: 4px;"),
|
||||
t
|
||||
])
|
||||
this.SetClass("flex m-1")
|
||||
}
|
||||
}
|
53
UI/WikipediaBox.ts
Normal file
53
UI/WikipediaBox.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import {UIEventSource} from "../Logic/UIEventSource";
|
||||
import {VariableUiElement} from "./Base/VariableUIElement";
|
||||
import Wikipedia from "../Logic/Web/Wikipedia";
|
||||
import Loading from "./Base/Loading";
|
||||
import {FixedUiElement} from "./Base/FixedUiElement";
|
||||
import Combine from "./Base/Combine";
|
||||
import BaseUIElement from "./BaseUIElement";
|
||||
import Title from "./Base/Title";
|
||||
import Translations from "./i18n/Translations";
|
||||
import Svg from "../Svg";
|
||||
|
||||
export default class WikipediaBox extends Combine{
|
||||
|
||||
constructor(options: {
|
||||
pagename: string,
|
||||
language: string
|
||||
}) {
|
||||
|
||||
const htmlContent = UIEventSource.FromPromiseWithErr(Wikipedia.GetArticle({
|
||||
pageName: options.pagename,
|
||||
language: options.language,
|
||||
removeInfoBoxes: true
|
||||
}))
|
||||
|
||||
const contents : UIEventSource<string | BaseUIElement> = htmlContent.map(htmlContent => {
|
||||
if(htmlContent === undefined){
|
||||
// Still loading
|
||||
return new Loading("Loading wikipedia page").SetClass("p-4")
|
||||
}
|
||||
if(htmlContent["success"] !== undefined){
|
||||
return new FixedUiElement(htmlContent["success"]).SetClass("wikipedia-article")
|
||||
}
|
||||
if(htmlContent["error"]){
|
||||
return new FixedUiElement(htmlContent["error"]).SetClass("alert p-4")
|
||||
}
|
||||
|
||||
return undefined
|
||||
|
||||
})
|
||||
|
||||
const scrollable = new Combine([new VariableUiElement(contents).SetClass("block pl-6 pt-2")])
|
||||
.SetClass("block overflow-auto normal-background rounded-lg")
|
||||
super([
|
||||
new Combine([Svg.wikipedia_svg().SetStyle("width: 1.5rem").SetClass("mr-3"),
|
||||
new Title(Translations.t.general.wikipedia.wikipediaboxTitle, 2)]).SetClass("flex"),
|
||||
scrollable])
|
||||
|
||||
this
|
||||
.SetClass("block rounded-xl subtle-background m-1 p-2 flex flex-col")
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -3,16 +3,12 @@
|
|||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
viewBox="0 0 25 25"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="loading.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
id="svg6">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
|
@ -20,44 +16,23 @@
|
|||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10"/>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1003"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="13.906433"
|
||||
inkscape:cx="14.114788"
|
||||
inkscape:cy="9.6469257"
|
||||
inkscape:window-x="1024"
|
||||
inkscape:window-y="1080"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6"/>
|
||||
id="defs10" />
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
cx="12.529661"
|
||||
cy="12.529661"
|
||||
r="10.441384"
|
||||
id="circle2"
|
||||
stroke-width="4"
|
||||
stroke="currentColor"
|
||||
style="stroke:#000000;stroke-opacity:0.33976835"/>
|
||||
style="stroke:#000000;stroke-width:4.17655373;stroke-opacity:0.33976835" />
|
||||
<path
|
||||
style="fill:currentColor;stroke-width:1.04413843"
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
id="path4"/>
|
||||
d="M 4.1765537,12.529661 A 8.3531073,8.3531073 0 0 1 12.529661,4.1765537 V 0 C 5.6101557,0 0,5.6101557 0,12.529661 Z m 2.0882768,5.524536 A 8.3134301,8.3134301 0 0 1 4.1765537,12.529661 H 0 c 0,3.176269 1.1850971,6.081062 3.1324153,8.288371 z"
|
||||
id="path4" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -812,6 +812,10 @@ video {
|
|||
margin: 0px;
|
||||
}
|
||||
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.m-2 {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
@ -820,8 +824,8 @@ video {
|
|||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
.m-6 {
|
||||
margin: 1.5rem;
|
||||
}
|
||||
|
||||
.my-2 {
|
||||
|
@ -844,18 +848,14 @@ video {
|
|||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.-ml-1 {
|
||||
margin-left: -0.25rem;
|
||||
}
|
||||
|
||||
.mr-3 {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.ml-3 {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mb-2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
@ -892,10 +892,6 @@ video {
|
|||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
@ -916,10 +912,18 @@ video {
|
|||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.mr-3 {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.box-border {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -968,10 +972,6 @@ video {
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.h-24 {
|
||||
height: 6rem;
|
||||
}
|
||||
|
@ -988,6 +988,10 @@ video {
|
|||
height: 3rem;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.h-screen {
|
||||
height: 100vh;
|
||||
}
|
||||
|
@ -1032,10 +1036,6 @@ video {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.w-5 {
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.w-10 {
|
||||
width: 2.5rem;
|
||||
}
|
||||
|
@ -1394,6 +1394,18 @@ video {
|
|||
padding: 0px;
|
||||
}
|
||||
|
||||
.pl-6 {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.pt-2 {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.pl-2 {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.pt-3 {
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
|
@ -1422,10 +1434,6 @@ video {
|
|||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.pl-2 {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.pl-5 {
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
|
@ -1787,6 +1795,7 @@ svg, img {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
display: unset;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
.mapcontrol svg path {
|
||||
|
@ -1876,6 +1885,11 @@ li::marker {
|
|||
color: var(--subtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
.normal-background {
|
||||
background: var(--background-color);
|
||||
color: var(--foreground-color)
|
||||
}
|
||||
|
||||
.subtle-lighter {
|
||||
color: var(--subtle-detail-color-light-contrast);
|
||||
}
|
||||
|
|
32
css/wikipedia.css
Normal file
32
css/wikipedia.css
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* This stylesheet reimplements a few classes from wikipedia to show their articles prettily */
|
||||
|
||||
.wikipedia-article {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.wikipedia-article .tright {
|
||||
float: right;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.wikipedia-article .thumb {
|
||||
background: var(--subtle-detail-color);
|
||||
margin: 1rem;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid var(--subtle-detail-color-light-contrast);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.wikipedia-article a {
|
||||
color: #0645ad;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.wikipedia-article a:hover a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.wikipedia-article p {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
|
@ -92,6 +92,7 @@ svg, img {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
display: unset;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
.mapcontrol svg path {
|
||||
|
@ -179,6 +180,11 @@ li::marker {
|
|||
color: var(--subtle-detail-color-contrast);
|
||||
}
|
||||
|
||||
.normal-background {
|
||||
background: var(--background-color);
|
||||
color: var(--foreground-color)
|
||||
}
|
||||
|
||||
.subtle-lighter {
|
||||
color: var(--subtle-detail-color-light-contrast);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
"readMessages": "You have unread messages. Read these before deleting a point - someone might have feedback"
|
||||
},
|
||||
"general": {
|
||||
"loading": "Loading...",
|
||||
"pdf": {
|
||||
"generatedWith": "Generated with MapComplete.osm.be",
|
||||
"attr": "Map data © OpenStreetMap Contributors, reusable under ODbL",
|
||||
|
@ -215,6 +216,9 @@
|
|||
},
|
||||
"histogram": {
|
||||
"error_loading": "Could not load the histogram"
|
||||
},
|
||||
"wikipedia": {
|
||||
"wikipediaboxTitle": "Wikipedia"
|
||||
}
|
||||
},
|
||||
"favourite": {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
<link href="./css/mobile.css" rel="stylesheet"/>
|
||||
<link href="./css/openinghourstable.css" rel="stylesheet"/>
|
||||
<link href="./css/tagrendering.css" rel="stylesheet"/>
|
||||
<link href="./css/index-tailwind-output.css" rel="stylesheet"/>
|
||||
<link href="./css/wikipedia.css" rel="stylesheet"/>
|
||||
<link href="css/ReviewElement.css" rel="stylesheet"/>
|
||||
<link href="vendor/MarkerCluster.css" rel="stylesheet"/>
|
||||
<link href="vendor/MarkerCluster.Default.css" rel="stylesheet"/>
|
||||
|
|
33
test.ts
33
test.ts
|
@ -1,31 +1,14 @@
|
|||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
||||
import TagRenderingQuestion from "./UI/Popup/TagRenderingQuestion";
|
||||
import {UIEventSource} from "./Logic/UIEventSource";
|
||||
import {VariableUiElement} from "./UI/Base/VariableUIElement";
|
||||
import Wikipedia from "./Logic/Web/Wikipedia";
|
||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||
import WikipediaBox from "./UI/WikipediaBox";
|
||||
import Loading from "./UI/Base/Loading";
|
||||
|
||||
const theme = AllKnownLayouts.allKnownLayouts.get("charging_stations")
|
||||
|
||||
const tagRendering = theme.layers[0].tagRenderings.filter(tr => tr.id === "Available_charging_stations (generated)")[0]
|
||||
const tag = new UIEventSource({
|
||||
id: "node/42",
|
||||
amenity:"charging_station",
|
||||
bicycle:"yes",
|
||||
car:"no",
|
||||
"motorcar":"no",
|
||||
"hgv":"no",
|
||||
bus:"no"
|
||||
new WikipediaBox({
|
||||
pagename: "Poertoren",
|
||||
language: "nl"
|
||||
})
|
||||
window.tags = tag
|
||||
|
||||
//const q =
|
||||
new VariableUiElement(tag.map(_ => new TagRenderingQuestion(tag, tagRendering) ))
|
||||
.SetStyle("width: 100px")
|
||||
.SetStyle("max-height: 20rem;")
|
||||
.AttachTo("maindiv")
|
||||
|
||||
|
||||
window.setTimeout(_ => {
|
||||
tag.data.bicycle="no"
|
||||
tag.data.car = "yes"
|
||||
tag.ping()
|
||||
console.log("Pinged")
|
||||
}, 2500)
|
Loading…
Reference in a new issue