Add wikipedia box
This commit is contained in:
parent
1edf829cad
commit
8b4442c8cc
20 changed files with 401 additions and 149 deletions
|
@ -3,6 +3,7 @@ import ImageProvider, {ProvidedImage} from "./ImageProvider";
|
|||
import BaseUIElement from "../../UI/BaseUIElement";
|
||||
import Svg from "../../Svg";
|
||||
import {WikimediaImageProvider} from "./WikimediaImageProvider";
|
||||
import Wikidata from "../Web/Wikidata";
|
||||
|
||||
export class WikidataImageProvider extends ImageProvider {
|
||||
|
||||
|
@ -22,31 +23,18 @@ export class WikidataImageProvider extends ImageProvider {
|
|||
}
|
||||
|
||||
public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
|
||||
const wikidataUrl = "https://www.wikidata.org/wiki/"
|
||||
if (value.startsWith(wikidataUrl)) {
|
||||
value = value.substring(wikidataUrl.length)
|
||||
}
|
||||
if(value.startsWith("http")){
|
||||
// Probably some random link in the image field - we skip it
|
||||
return undefined
|
||||
}
|
||||
if (!value.startsWith("Q")) {
|
||||
value = "Q" + value
|
||||
}
|
||||
const url = "https://www.wikidata.org/wiki/Special:EntityData/" + value + ".json";
|
||||
const response = await Utils.downloadJson(url)
|
||||
const entity = response.entities[value];
|
||||
const commons = entity.sitelinks.commonswiki;
|
||||
const entity = await Wikidata.LoadWikidataEntry(value)
|
||||
|
||||
const allImages : Promise<ProvidedImage>[] = []
|
||||
// P18 is the claim 'depicted in this image'
|
||||
const image = entity.claims.P18?.[0]?.mainsnak?.datavalue?.value;
|
||||
const allImages = []
|
||||
if (image !== undefined) {
|
||||
// We found a 'File://'
|
||||
const promises = await WikimediaImageProvider.singleton.ExtractUrls(key, image)
|
||||
for (const img of Array.from(entity.claims.get("P18") ?? [])) {
|
||||
const promises = await WikimediaImageProvider.singleton.ExtractUrls(undefined, img)
|
||||
allImages.push(...promises)
|
||||
}
|
||||
|
||||
const commons =entity.wikisites.get("commons")
|
||||
if (commons !== undefined) {
|
||||
const promises = await WikimediaImageProvider.singleton.ExtractUrls(commons, image)
|
||||
const promises = await WikimediaImageProvider.singleton.ExtractUrls(undefined , commons)
|
||||
allImages.push(...promises)
|
||||
}
|
||||
return allImages
|
||||
|
|
|
@ -44,7 +44,6 @@ export class WikimediaImageProvider extends ImageProvider {
|
|||
if (continueParameter !== undefined) {
|
||||
url = `${url}&cmcontinue=${continueParameter}`;
|
||||
}
|
||||
console.debug("Loading a wikimedia category: ", url)
|
||||
const response = await Utils.downloadJson(url)
|
||||
const members = response.query?.categorymembers ?? [];
|
||||
const imageOverview: string[] = members.map(member => member.title);
|
||||
|
@ -135,8 +134,7 @@ export class WikimediaImageProvider extends ImageProvider {
|
|||
}
|
||||
|
||||
public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> {
|
||||
|
||||
if(key !== this.commons_key && !value.startsWith(WikimediaImageProvider.commonsPrefix)){
|
||||
if(key !== undefined && key !== this.commons_key && !value.startsWith(WikimediaImageProvider.commonsPrefix)){
|
||||
return []
|
||||
}
|
||||
|
||||
|
|
89
Logic/Web/Wikidata.ts
Normal file
89
Logic/Web/Wikidata.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import {Utils} from "../../Utils";
|
||||
|
||||
|
||||
export interface WikidataResponse {
|
||||
|
||||
id: string,
|
||||
labels: Map<string, string>,
|
||||
descriptions: Map<string, string>,
|
||||
claims: Map<string, Set<string>>,
|
||||
wikisites: Map<string, string>
|
||||
commons: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility functions around wikidata
|
||||
*/
|
||||
export default class Wikidata {
|
||||
|
||||
private static ParseResponse(entity: any): WikidataResponse {
|
||||
const labels = new Map<string, string>()
|
||||
for (const labelName in entity.labels) {
|
||||
// The labelname is the language code
|
||||
labels.set(labelName, entity.labels[labelName].value)
|
||||
}
|
||||
|
||||
const descr = new Map<string, string>()
|
||||
for (const labelName in entity.descriptions) {
|
||||
// The labelname is the language code
|
||||
descr.set(labelName, entity.descriptions[labelName].value)
|
||||
}
|
||||
|
||||
const sitelinks = new Map<string, string>();
|
||||
for (const labelName in entity.sitelinks) {
|
||||
// labelName is `${language}wiki`
|
||||
const language = labelName.substring(0, labelName.length - 4)
|
||||
const title = entity.sitelinks[labelName].title
|
||||
sitelinks.set(language, title)
|
||||
}
|
||||
|
||||
const commons = sitelinks.get("commons")
|
||||
sitelinks.delete("commons")
|
||||
|
||||
const claims = new Map<string, Set<string>>();
|
||||
for (const claimId of entity.claims) {
|
||||
|
||||
const claimsList: any[] = entity.claims[claimId]
|
||||
const values = new Set<string>()
|
||||
for (const claim of claimsList) {
|
||||
const value = claim.mainsnak.datavalue.value;
|
||||
values.add(value)
|
||||
}
|
||||
claims.set(claimId, values);
|
||||
}
|
||||
|
||||
return {
|
||||
claims: claims,
|
||||
descriptions: descr,
|
||||
id: entity.id,
|
||||
labels: labels,
|
||||
wikisites: sitelinks,
|
||||
commons: commons
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a wikidata page
|
||||
* @returns the entity of the given value
|
||||
*/
|
||||
public static async LoadWikidataEntry(value: string | number): Promise<WikidataResponse> {
|
||||
const wikidataUrl = "https://www.wikidata.org/wiki/"
|
||||
if (typeof value === "number") {
|
||||
value = "Q" + value
|
||||
}
|
||||
if (value.startsWith(wikidataUrl)) {
|
||||
value = value.substring(wikidataUrl.length)
|
||||
}
|
||||
if (value.startsWith("http")) {
|
||||
// Probably some random link in the image field - we skip it
|
||||
return undefined
|
||||
}
|
||||
if (!value.startsWith("Q")) {
|
||||
value = "Q" + value
|
||||
}
|
||||
const url = "https://www.wikidata.org/wiki/Special:EntityData/" + value + ".json";
|
||||
const response = await Utils.downloadJson(url)
|
||||
return Wikidata.ParseResponse(response.entities[value]);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
* Some usefull utility functions around the wikipedia API
|
||||
*/
|
||||
import {Utils} from "../../Utils";
|
||||
import WikipediaBox from "../../UI/WikipediaBox";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import Wikidata from "./Wikidata";
|
||||
|
||||
export default class Wikipedia {
|
||||
|
||||
|
@ -14,22 +15,36 @@ export default class Wikipedia {
|
|||
private static readonly classesToRemove = [
|
||||
"shortdescription",
|
||||
"sidebar",
|
||||
"infobox",
|
||||
"infobox","infobox_v2",
|
||||
"noprint",
|
||||
"ambox",
|
||||
"mw-editsection",
|
||||
"mw-selflink",
|
||||
"hatnote" // Often redirects
|
||||
]
|
||||
|
||||
public static async GetArticle(options: {
|
||||
private static readonly _cache = new Map<string, UIEventSource<{ success: string } | { error: any }>>()
|
||||
|
||||
public static GetArticle(options: {
|
||||
pageName: string,
|
||||
language?: "en" | string,
|
||||
section?: number,
|
||||
language?: "en" | string}): UIEventSource<{ success: string } | { error: any }>{
|
||||
const key = (options.language ?? "en")+":"+options.pageName
|
||||
const cached = Wikipedia._cache.get(key)
|
||||
if(cached !== undefined){
|
||||
return cached
|
||||
}
|
||||
const v = UIEventSource.FromPromiseWithErr(Wikipedia.GetArticleAsync(options))
|
||||
Wikipedia._cache.set(key, v)
|
||||
return v;
|
||||
}
|
||||
|
||||
public static async GetArticleAsync(options: {
|
||||
pageName: string,
|
||||
language?: "en" | string
|
||||
}): 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 language = options.language ?? "en"
|
||||
const url = `https://${language}.wikipedia.org/w/api.php?action=parse&format=json&origin=*&prop=text&page=` + options.pageName
|
||||
const response = await Utils.downloadJson(url)
|
||||
const html = response["parse"]["text"]["*"];
|
||||
|
||||
|
@ -43,7 +58,19 @@ export default class Wikipedia {
|
|||
toRemoveElement.parentElement?.removeChild(toRemoveElement)
|
||||
}
|
||||
}
|
||||
return content.innerHTML;
|
||||
|
||||
const links = Array.from(content.getElementsByTagName("a"))
|
||||
|
||||
console.log("Links are", links)
|
||||
// Rewrite relative links to absolute links + open them in a new tab
|
||||
links.filter(link => link.getAttribute("href")?.startsWith("/") ?? false).
|
||||
forEach(link => {
|
||||
link.target = '_blank'
|
||||
// note: link.getAttribute("href") gets the textual value, link.href is the rewritten version which'll contain the host for relative paths
|
||||
link.href = `https://${language}.wikipedia.org${link.getAttribute("href")}`;
|
||||
})
|
||||
|
||||
return content.innerHTML
|
||||
}
|
||||
|
||||
}
|
|
@ -9,9 +9,9 @@ export default class Loading extends Combine {
|
|||
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;"),
|
||||
Svg.loading_svg().SetClass("animate-spin").SetStyle("width: 1.5rem; height: 1.5rem;"),
|
||||
t
|
||||
])
|
||||
this.SetClass("flex m-1")
|
||||
this.SetClass("flex p-1")
|
||||
}
|
||||
}
|
|
@ -225,7 +225,6 @@ export default class ShowDataLayer {
|
|||
popup.setContent(`<div style='height: 65vh' id='${id}'>Popup for ${feature.properties.id} ${feature.geometry.type}</div>`)
|
||||
|
||||
leafletLayer.on("popupopen", () => {
|
||||
console.trace(`Opening the popup for ${feature.properties.id} ${feature.geometry.type}`)
|
||||
if (infobox === undefined) {
|
||||
const tags = State.state.allElements.getEventSourceById(feature.properties.id);
|
||||
infobox = new FeatureInfoBox(tags, layer);
|
||||
|
@ -239,7 +238,9 @@ export default class ShowDataLayer {
|
|||
}
|
||||
infobox.AttachTo(id)
|
||||
infobox.Activate();
|
||||
if (State.state?.selectedElement?.data?.properties?.id !== feature.properties.id) {
|
||||
State.state.selectedElement.setData(feature)
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSou
|
|||
import ShowDataMultiLayer from "./ShowDataLayer/ShowDataMultiLayer";
|
||||
import Minimap from "./Base/Minimap";
|
||||
import AllImageProviders from "../Logic/ImageProviders/AllImageProviders";
|
||||
import WikipediaBox from "./WikipediaBox";
|
||||
|
||||
export interface SpecialVisualization {
|
||||
funcName: string,
|
||||
|
@ -84,6 +85,20 @@ export default class SpecialVisualizations {
|
|||
return new ImageUploadFlow(tags, args[0])
|
||||
}
|
||||
},
|
||||
{
|
||||
funcName: "wikipedia",
|
||||
docs: "A box showing the corresponding wikipedia article - based on the wikidata tag",
|
||||
args: [
|
||||
{
|
||||
name: "keyToShowWikipediaFor",
|
||||
doc: "Use the wikidata entry from this key to show the wikipedia article for",
|
||||
defaultValue: "wikidata"
|
||||
}
|
||||
],
|
||||
example: "`{wikipedia()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the wikipedia page of whom the feature was named after. Also remember that these can be styled, e.g. `{wikipedia():max-height: 10rem}` to limit the height",
|
||||
constr: (_, tagsSource, args) =>
|
||||
new WikipediaBox( tagsSource.map(tags => tags[args[0]]))
|
||||
},
|
||||
{
|
||||
funcName: "minimap",
|
||||
docs: "A small map showing the selected feature. Note that no styling is applied, wrap this in a div",
|
||||
|
@ -156,7 +171,7 @@ export default class SpecialVisualizations {
|
|||
new ShowDataMultiLayer(
|
||||
{
|
||||
leafletMap: minimap["leafletMap"],
|
||||
enablePopups : false,
|
||||
enablePopups: false,
|
||||
zoomToFeatures: true,
|
||||
layers: State.state.filteredLayers,
|
||||
features: new StaticFeatureSource(featuresToShow, true)
|
||||
|
@ -411,8 +426,8 @@ There are also some technicalities in your theme to keep in mind:
|
|||
}
|
||||
return kv
|
||||
})
|
||||
const rewrittenTags : UIEventSource<Tag[]> = tagSource.map(tags => {
|
||||
const newTags : Tag [] = []
|
||||
const rewrittenTags: UIEventSource<Tag[]> = tagSource.map(tags => {
|
||||
const newTags: Tag [] = []
|
||||
for (const [key, value] of tgsSpec) {
|
||||
if (value.startsWith('$')) {
|
||||
const origKey = value.substring(1)
|
||||
|
@ -446,9 +461,9 @@ There are also some technicalities in your theme to keep in mind:
|
|||
[
|
||||
new Title(viz.funcName, 3),
|
||||
viz.docs,
|
||||
new Table(["name", "default", "description"],
|
||||
viz.args.length > 0 ? new Table(["name", "default", "description"],
|
||||
viz.args.map(arg => [arg.name, arg.defaultValue ?? "undefined", arg.doc])
|
||||
),
|
||||
) : undefined,
|
||||
new Title("Example usage", 4),
|
||||
new FixedUiElement(
|
||||
viz.example ?? "`{" + viz.funcName + "(" + viz.args.map(arg => arg.defaultValue).join(",") + ")}`"
|
||||
|
|
|
@ -8,46 +8,109 @@ import BaseUIElement from "./BaseUIElement";
|
|||
import Title from "./Base/Title";
|
||||
import Translations from "./i18n/Translations";
|
||||
import Svg from "../Svg";
|
||||
import Wikidata from "../Logic/Web/Wikidata";
|
||||
import Locale from "./i18n/Locale";
|
||||
|
||||
export default class WikipediaBox extends Combine{
|
||||
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")
|
||||
private static async ExtractWikiPages(wikidata): Promise<Map<string, string>> {
|
||||
return (await Wikidata.LoadWikidataEntry(wikidata)).wikisites
|
||||
}
|
||||
|
||||
return undefined
|
||||
|
||||
private static _cache = new Map()
|
||||
|
||||
constructor(wikidataId: string | UIEventSource<string>) {
|
||||
const wp = Translations.t.general.wikipedia;
|
||||
if(typeof wikidataId === "string"){
|
||||
wikidataId = new UIEventSource(wikidataId)
|
||||
}
|
||||
|
||||
const knownPages = new UIEventSource<{success:Map<string, string>}|{error:any}>(undefined)
|
||||
|
||||
wikidataId.addCallbackAndRunD(wikidataId => {
|
||||
WikipediaBox.ExtractWikiPages(wikidataId).then(pages => {
|
||||
knownPages.setData({success:pages})
|
||||
}).catch(err=> {
|
||||
knownPages.setData({error: err})
|
||||
})
|
||||
})
|
||||
|
||||
const scrollable = new Combine([new VariableUiElement(contents).SetClass("block pl-6 pt-2")])
|
||||
.SetClass("block overflow-auto normal-background rounded-lg")
|
||||
const cachedPages = new Map<string, BaseUIElement>()
|
||||
|
||||
const contents = new VariableUiElement(
|
||||
knownPages.map(pages => {
|
||||
|
||||
if (pages === undefined) {
|
||||
return new Loading(wp.loading.Clone())
|
||||
}
|
||||
if (pages["error"] !== undefined) {
|
||||
return wp.failed.Clone().SetClass("alert p-4")
|
||||
}
|
||||
const dict: Map<string, string> = pages["success"]
|
||||
|
||||
const preferredLanguage = [Locale.language.data, "en", Array.from(dict.keys())[0]]
|
||||
let language
|
||||
let pagetitle;
|
||||
let i = 0
|
||||
do {
|
||||
language = preferredLanguage[i]
|
||||
pagetitle = dict.get(language)
|
||||
i++;
|
||||
if(i >= preferredLanguage.length){
|
||||
return wp.noWikipediaPage.Clone()
|
||||
}
|
||||
} while (pagetitle === undefined)
|
||||
|
||||
if(cachedPages.has(language)){
|
||||
return cachedPages.get(language)
|
||||
}
|
||||
|
||||
const page = WikipediaBox.createContents(pagetitle, language);
|
||||
cachedPages.set(language, page)
|
||||
return page
|
||||
}, [Locale.language])
|
||||
).SetClass("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])
|
||||
new Combine([Svg.wikipedia_ui().SetStyle("width: 1.5rem").SetClass("mr-3"),
|
||||
new Title(Translations.t.general.wikipedia.wikipediaboxTitle.Clone(), 2)]).SetClass("flex"),
|
||||
contents])
|
||||
|
||||
this
|
||||
.SetClass("block rounded-xl subtle-background m-1 p-2 flex flex-col")
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual content in a scrollable way
|
||||
* @param pagename
|
||||
* @param language
|
||||
* @private
|
||||
*/
|
||||
private static createContents(pagename: string, language: string): BaseUIElement {
|
||||
const htmlContent = Wikipedia.GetArticle({
|
||||
pageName: pagename,
|
||||
language: language
|
||||
})
|
||||
const wp = Translations.t.general.wikipedia
|
||||
const contents: UIEventSource<string | BaseUIElement> = htmlContent.map(htmlContent => {
|
||||
if (htmlContent === undefined) {
|
||||
// Still loading
|
||||
return new Loading(wp.loading.Clone())
|
||||
}
|
||||
if (htmlContent["success"] !== undefined) {
|
||||
return new FixedUiElement(htmlContent["success"]).SetClass("wikipedia-article")
|
||||
}
|
||||
if (htmlContent["error"]) {
|
||||
return wp.failed.Clone().SetClass("alert p-4")
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
return new Combine([new VariableUiElement(contents).SetClass("block pl-6 pt-2")])
|
||||
.SetClass("block")
|
||||
}
|
||||
|
||||
}
|
|
@ -392,7 +392,8 @@
|
|||
}
|
||||
],
|
||||
"id": "Surface area"
|
||||
}
|
||||
},
|
||||
"wikipedia"
|
||||
],
|
||||
"wayHandling": 2,
|
||||
"icon": {
|
||||
|
|
|
@ -122,7 +122,8 @@
|
|||
},
|
||||
"id": "Payment methods"
|
||||
},
|
||||
"wheelchair-access"
|
||||
"wheelchair-access",
|
||||
"wikipedia"
|
||||
],
|
||||
"wayHandling": 1,
|
||||
"icon": {
|
||||
|
|
|
@ -5,12 +5,17 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 25 25"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
viewBox="0 0 24.022156 24.021992"
|
||||
version="1.1"
|
||||
id="svg6">
|
||||
id="svg9"
|
||||
sodipodi:docname="loading.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
width="24.022156"
|
||||
height="24.021992">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
id="metadata13">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
|
@ -21,18 +26,53 @@
|
|||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<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="1043"
|
||||
id="namedview11"
|
||||
showgrid="false"
|
||||
inkscape:zoom="19.666667"
|
||||
inkscape:cx="-1.7824593"
|
||||
inkscape:cy="7.7694192"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg9" />
|
||||
<defs
|
||||
id="defs10" />
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12.529661"
|
||||
cy="12.529661"
|
||||
r="10.441384"
|
||||
id="circle2"
|
||||
style="stroke:#000000;stroke-width:4.17655373;stroke-opacity:0.33976835" />
|
||||
id="defs4">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#000;}</style>
|
||||
</defs>
|
||||
<path
|
||||
style="fill:currentColor;stroke-width:1.04413843"
|
||||
class="opacity-75"
|
||||
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" />
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.26200151;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.26635515"
|
||||
id="path821"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="12.010992"
|
||||
sodipodi:cy="12.010992"
|
||||
sodipodi:rx="10.379992"
|
||||
sodipodi:ry="10.379992"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="6.2828013"
|
||||
sodipodi:open="true"
|
||||
d="M 22.390984,12.010992 A 10.379992,10.379992 0 0 1 12.011989,22.390984 10.379992,10.379992 0 0 1 1.6310007,12.012985 10.379992,10.379992 0 0 1 12.008003,1.6310009 10.379992,10.379992 0 0 1 22.390983,12.007006" />
|
||||
<path
|
||||
d="m 22.390984,12.010992 a 10.379992,10.379992 0 0 1 -3.26001,7.55315 10.379992,10.379992 0 0 1 -7.732307,2.808765"
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="1.6298215"
|
||||
sodipodi:start="0"
|
||||
sodipodi:ry="10.379992"
|
||||
sodipodi:rx="10.379992"
|
||||
sodipodi:cy="12.010992"
|
||||
sodipodi:cx="12.010992"
|
||||
sodipodi:type="arc"
|
||||
id="path838"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.26200151;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.8 KiB |
|
@ -2,6 +2,9 @@
|
|||
"images": {
|
||||
"render": "{image_carousel()}{image_upload()}"
|
||||
},
|
||||
"wikipedia": {
|
||||
"render": "{wikipedia():max-height:25rem}"
|
||||
},
|
||||
"reviews": {
|
||||
"render": "{reviews()}"
|
||||
},
|
||||
|
|
|
@ -812,10 +812,6 @@ video {
|
|||
margin: 0px;
|
||||
}
|
||||
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.m-2 {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
@ -824,8 +820,8 @@ video {
|
|||
margin: 0.75rem;
|
||||
}
|
||||
|
||||
.m-6 {
|
||||
margin: 1.5rem;
|
||||
.m-4 {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.my-2 {
|
||||
|
@ -852,8 +848,8 @@ video {
|
|||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
.mr-3 {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.mb-2 {
|
||||
|
@ -892,6 +888,10 @@ video {
|
|||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.ml-2 {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
@ -912,18 +912,10 @@ 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;
|
||||
}
|
||||
|
@ -1794,8 +1786,6 @@ svg, img {
|
|||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: unset;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
.mapcontrol svg path {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* This stylesheet reimplements a few classes from wikipedia to show their articles prettily */
|
||||
|
||||
.wikipedia-article {
|
||||
font-family: sans-serif;
|
||||
font-family: sans-serif !important;
|
||||
}
|
||||
|
||||
.wikipedia-article .tright {
|
||||
|
@ -9,6 +9,12 @@
|
|||
clear: right;
|
||||
}
|
||||
|
||||
.wikipedia-article svg, img {
|
||||
width: unset;
|
||||
height: unset;
|
||||
display: unset;
|
||||
}
|
||||
|
||||
.wikipedia-article .thumb {
|
||||
background: var(--subtle-detail-color);
|
||||
margin: 1rem;
|
||||
|
@ -17,15 +23,17 @@
|
|||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.wikipedia-article a {
|
||||
color: #0645ad;
|
||||
background: none;
|
||||
.wikipedia-article a:hover a:focus {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.wikipedia-article a:hover a:focus {
|
||||
text-decoration: underline;
|
||||
.wikipedia-article a {
|
||||
color: #0645ad !important;
|
||||
background: none !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.wikipedia-article p {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@ svg, img {
|
|||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: unset;
|
||||
vertical-align: unset;
|
||||
}
|
||||
|
||||
.mapcontrol svg path {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<link href="vendor/MarkerCluster.css" rel="stylesheet"/>
|
||||
<link href="vendor/MarkerCluster.Default.css" rel="stylesheet"/>
|
||||
<link href="./css/index-tailwind-output.css" rel="stylesheet" />
|
||||
<link href="./css/wikipedia.css" rel="stylesheet" />
|
||||
<meta content="website" property="og:type">
|
||||
|
||||
<!-- THEME-SPECIFIC -->
|
||||
|
|
|
@ -218,7 +218,10 @@
|
|||
"error_loading": "Could not load the histogram"
|
||||
},
|
||||
"wikipedia": {
|
||||
"wikipediaboxTitle": "Wikipedia"
|
||||
"wikipediaboxTitle": "Wikipedia",
|
||||
"failed":"Loading the wikipedia entry failed",
|
||||
"loading": "Loading Wikipedia...",
|
||||
"noWikipediaPage": "This wikidata item has no corresponding wikipedia page yet."
|
||||
}
|
||||
},
|
||||
"favourite": {
|
||||
|
|
|
@ -743,6 +743,22 @@
|
|||
"description": "On this map, publicly accessible drinking water spots are shown and can be easily added",
|
||||
"title": "Drinking Water"
|
||||
},
|
||||
"etymology": {
|
||||
"description": "On this map, you can see what an object is named after. The streets, buildings, ... come from OpenStreetMap which got linked with Wikidata. The information comes from Wpikipedia.",
|
||||
"layers": {
|
||||
"0": {
|
||||
"description": "All objects which have an etymology known",
|
||||
"name": "Has etymolgy",
|
||||
"tagRenderings": {
|
||||
"simple etymology": {
|
||||
"render": "Named after {name:etymology}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortDescription": "What is the origin of a toponym?",
|
||||
"title": "Open Etymology Map"
|
||||
},
|
||||
"facadegardens": {
|
||||
"description": "<a href='https://nl.wikipedia.org/wiki/Geveltuin' target=_blank>Facade gardens</a>, green facades and trees in the city not only bring peace and quiet, but also a more beautiful city, greater biodiversity, a cooling effect and better air quality. <br/> Klimaan VZW and Mechelen Klimaatneutraal want to map existing and new facade gardens as an example for people who want to build their own garden or for city walkers who love nature.<br/>More info about the project at <a href='https://klimaan.be/' target=_blank>klimaan.be</a>.",
|
||||
"layers": {
|
||||
|
|
|
@ -624,6 +624,22 @@
|
|||
"description": "Op deze kaart staan publiek toegankelijke drinkwaterpunten en kan je makkelijk een nieuw drinkwaterpunt toevoegen",
|
||||
"title": "Drinkwaterpunten"
|
||||
},
|
||||
"etymology": {
|
||||
"description": "Op deze kaart zie je waar een plaats naar is vernoemd. De straten, gebouwen, ... komen uit OpenStreetMap, waar een link naar Wikidata werd gelegd. De informatie komt uit wikipedia.",
|
||||
"layers": {
|
||||
"0": {
|
||||
"description": "Alle lagen met een gelinkt etymology",
|
||||
"name": "Heeft etymology info",
|
||||
"tagRenderings": {
|
||||
"simple etymology": {
|
||||
"render": "Vernoemd naar {name:etymology}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortDescription": "Wat is de oorsprong van een plaatsnaam?",
|
||||
"title": "Open Etymology-kaart"
|
||||
},
|
||||
"facadegardens": {
|
||||
"description": "Ontharde voortuintjes, groene gevels en bomen ín de stad brengen naast rust ook een mooiere stad, een grotere biodiversiteit, een verkoelend effect en een betere luchtkwaliteit. <br/> Klimaan VZW en 'Mechelen Klimaatneutraal' willen met het project Klim(t)aan je Gevel bestaande en nieuwe geveltuintjes in kaart brengen als voorbeeld voor mensen zelf een tuintje willen aanleggen of voor stadwandelaars die houden van de natuur. <br/>Meer info over het project op <a href='https://klimaan.be/' target=_blank>klimaan.be</a>.",
|
||||
"layers": {
|
||||
|
|
16
test.ts
16
test.ts
|
@ -1,14 +1,8 @@
|
|||
import Wikipedia from "./Logic/Web/Wikipedia";
|
||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||
import Wikidata from "./Logic/Web/Wikidata";
|
||||
import WikipediaBox from "./UI/WikipediaBox";
|
||||
import Loading from "./UI/Base/Loading";
|
||||
import Locale from "./UI/i18n/Locale";
|
||||
import LanguagePicker from "./UI/LanguagePicker";
|
||||
|
||||
|
||||
new WikipediaBox({
|
||||
pagename: "Poertoren",
|
||||
language: "nl"
|
||||
})
|
||||
.SetStyle("max-height: 20rem;")
|
||||
new WikipediaBox("Q177").SetStyle("max-height: 25rem")
|
||||
.AttachTo("maindiv")
|
||||
|
||||
|
||||
LanguagePicker.CreateLanguagePicker(["en","nl","fr","de"]).AttachTo("extradiv")
|
Loading…
Reference in a new issue