Some refactoring, more work on the custom theme generator

This commit is contained in:
Pieter Vander Vennet 2020-08-17 17:23:15 +02:00
parent c4b5f180a6
commit 146552e62c
104 changed files with 382 additions and 1590 deletions

120
Logic/Web/Imgur.ts Normal file
View file

@ -0,0 +1,120 @@
import $ from "jquery"
import {LicenseInfo} from "./Wikimedia";
export class Imgur {
static uploadMultiple(
title: string, description: string, blobs: FileList,
handleSuccessfullUpload: ((imageURL: string) => void),
allDone: (() => void),
onFail: ((reason: string) => void),
offset:number) {
if(offset === undefined){
throw "Offset undefined - not uploading to prevent to much uploads!"
}
if (blobs.length == offset) {
allDone();
return;
}
const blob = blobs.item(offset);
const self = this;
this.uploadImage(title, description, blob,
(imageUrl) => {
handleSuccessfullUpload(imageUrl);
self.uploadMultiple(
title, description, blobs,
handleSuccessfullUpload,
allDone,
onFail,
offset + 1);
},
onFail
);
}
static getDescriptionOfImage(url: string,
handleDescription: ((license: LicenseInfo) => void)) {
const hash = url.substr("https://i.imgur.com/".length).split(".jpg")[0];
const apiUrl = 'https://api.imgur.com/3/image/'+hash;
const apiKey = '7070e7167f0a25a';
var settings = {
async: true,
crossDomain: true,
processData: false,
contentType: false,
type: 'GET',
url: apiUrl,
headers: {
Authorization: 'Client-ID ' + apiKey,
Accept: 'application/json',
},
};
$.ajax(settings).done(function (response) {
const descr : string= response.data.description;
const data : any = {};
for (const tag of descr.split("\n")) {
const kv = tag.split(":");
const k = kv[0];
const v = kv[1].replace("\r", "");
data[k] = v;
}
const licenseInfo = new LicenseInfo();
licenseInfo.licenseShortName = data.license;
licenseInfo.artist = data.author;
handleDescription(licenseInfo);
}).fail((reason) => {
console.log("Getting metadata from to IMGUR failed", reason)
});
}
static uploadImage(title: string, description: string, blob,
handleSuccessfullUpload: ((imageURL: string) => void),
onFail: (reason:string) => void) {
const apiUrl = 'https://api.imgur.com/3/image';
const apiKey = '7070e7167f0a25a';
var settings = {
async: true,
crossDomain: true,
processData: false,
contentType: false,
type: 'POST',
url: apiUrl,
headers: {
Authorization: 'Client-ID ' + apiKey,
Accept: 'application/json',
},
mimeType: 'multipart/form-data',
};
var formData = new FormData();
formData.append('image', blob);
formData.append("title", title);
formData.append("description", description)
// @ts-ignore
settings.data = formData;
// Response contains stringified JSON
// Image URL available at response.data.link
$.ajax(settings).done(function (response) {
response = JSON.parse(response);
handleSuccessfullUpload(response.data.link);
}).fail((reason) => {
console.log("Uploading to IMGUR failed", reason);
onFail(reason);
});
}
}

View file

@ -0,0 +1,21 @@
import {UIEventSource} from "../UIEventSource";
export class LocalStorageSource {
static Get(key: string, defaultValue: string = undefined): UIEventSource<string> {
try {
const saved = localStorage.getItem(key);
const source = new UIEventSource<string>(saved ?? defaultValue);
source.addCallback((data) => {
localStorage.setItem(key, data);
});
return source;
} catch (e) {
return new UIEventSource<string>(defaultValue);
}
}
}

View file

@ -0,0 +1,72 @@
/**
* Wraps the query parameters into UIEventSources
*/
import {UIEventSource} from "../UIEventSource";
export class QueryParameters {
private static order: string [] = ["layout","test","z","lat","lon"];
private static knownSources = {};
private static initialized = false;
private static defaults = {}
private static addOrder(key){
if(this.order.indexOf(key) < 0){
this.order.push(key)
}
}
private static init() {
if(this.initialized){
return;
}
this.initialized = true;
if (window?.location?.search) {
const params = window.location.search.substr(1).split("&");
for (const param of params) {
const kv = param.split("=");
const key = kv[0];
QueryParameters.addOrder(key)
const v = kv[1];
const source = new UIEventSource<string>(v);
source.addCallback(() => QueryParameters.Serialize())
QueryParameters.knownSources[key] = source;
}
}
}
private static Serialize() {
const parts = []
for (const key of QueryParameters.order) {
if (QueryParameters.knownSources[key] === undefined || QueryParameters.knownSources[key].data === undefined) {
continue;
}
if (QueryParameters.knownSources[key].data == QueryParameters.defaults[key]) {
continue;
}
parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(QueryParameters.knownSources[key].data))
}
history.replaceState(null, "", "?" + parts.join("&"));
}
public static GetQueryParameter(key: string, deflt: string): UIEventSource<string> {
if(!this.initialized){
this.init();
}
if (deflt !== undefined) {
QueryParameters.defaults[key] = deflt;
}
if (QueryParameters.knownSources[key] !== undefined) {
return QueryParameters.knownSources[key];
}
QueryParameters.addOrder(key);
const source = new UIEventSource<string>(deflt);
QueryParameters.knownSources[key] = source;
source.addCallback(() => QueryParameters.Serialize())
return source;
}
}

135
Logic/Web/Wikimedia.ts Normal file
View file

@ -0,0 +1,135 @@
import * as $ from "jquery"
/**
* This module provides endpoints for wikipedia/wikimedia and others
*/
export class Wikimedia {
static ImageNameToUrl(filename: string, width: number = 500, height: number = 200): string {
filename = encodeURIComponent(filename);
return "https://commons.wikimedia.org/wiki/Special:FilePath/" + filename + "?width=" + width + "&height=" + height;
}
private static knownLicenses = {};
static LicenseData(filename: string, handle: ((LicenseInfo) => void)): void {
if (filename in this.knownLicenses) {
return this.knownLicenses[filename];
}
if (filename === "") {
return;
}
const url = "https://en.wikipedia.org/w/" +
"api.php?action=query&prop=imageinfo&iiprop=extmetadata&" +
"titles=" + filename +
"&format=json&origin=*";
$.getJSON(url, function (data, status) {
const licenseInfo = new LicenseInfo();
const license = data.query.pages[-1].imageinfo[0].extmetadata;
licenseInfo.artist = license.Artist?.value;
licenseInfo.license = license.License?.value;
licenseInfo.copyrighted = license.Copyrighted?.value;
licenseInfo.attributionRequired = license.AttributionRequired?.value;
licenseInfo.usageTerms = license.UsageTerms?.value;
licenseInfo.licenseShortName = license.LicenseShortName?.value;
licenseInfo.credit = license.Credit?.value;
licenseInfo.description = license.ImageDescription?.value;
Wikimedia.knownLicenses[filename] = licenseInfo;
handle(licenseInfo);
});
}
static GetCategoryFiles(categoryName: string, handleCategory: ((ImagesInCategory) => void),
alreadyLoaded = 0, continueParameter: { k: string, param: string } = undefined) {
if (categoryName === undefined || categoryName === null || categoryName === "") {
return;
}
// @ts-ignore
if (!categoryName.startsWith("Category:")) {
categoryName = "Category:" + categoryName;
}
let url = "https://commons.wikimedia.org/w/api.php?" +
"action=query&list=categorymembers&format=json&" +
"&origin=*" +
"&cmtitle=" + encodeURIComponent(categoryName);
if (continueParameter !== undefined) {
url = url + "&" + continueParameter.k + "=" + continueParameter.param;
}
$.getJSON(url, (response) => {
let imageOverview = new ImagesInCategory();
let members = response.query?.categorymembers;
if (members === undefined) {
members = [];
}
for (const member of members) {
imageOverview.images.push(member.title);
}
if (response.continue === undefined || alreadyLoaded > 30) {
handleCategory(imageOverview);
} else {
console.log("Recursive load for ", categoryName)
this.GetCategoryFiles(categoryName, (recursiveImages) => {
for (const image of imageOverview.images) {
recursiveImages.images.push(image);
}
handleCategory(recursiveImages);
},
alreadyLoaded + 10, {k: "cmcontinue", param: response.continue.cmcontinue})
}
});
}
static GetWikiData(id: number, handleWikidata: ((Wikidata) => void)) {
const url = "https://www.wikidata.org/wiki/Special:EntityData/Q" + id + ".json";
$.getJSON(url, (response) => {
const entity = response.entities["Q" + id];
const commons = entity.sitelinks.commonswiki;
const wd = new Wikidata();
wd.commonsWiki = commons?.title;
// P18 is the claim 'depicted in this image'
const image = entity.claims.P18?.[0]?.mainsnak?.datavalue?.value;
if (image) {
wd.image = "File:" + image;
}
handleWikidata(wd);
});
}
}
export class Wikidata {
commonsWiki: string;
image: string;
}
export class ImagesInCategory {
// Filenames of relevant images
images: string[] = [];
}
export class LicenseInfo {
artist: string = "";
license: string = "";
licenseShortName: string = "";
usageTerms: string = "";
attributionRequired: boolean = false;
copyrighted: boolean = false;
credit: string = "";
description: string = "";
}