diff --git a/UI/Reviews/ReviewElement.ts b/UI/Reviews/ReviewElement.ts index 6eef928..9f123a2 100644 --- a/UI/Reviews/ReviewElement.ts +++ b/UI/Reviews/ReviewElement.ts @@ -12,7 +12,7 @@ import SingleReview from "./SingleReview"; export default class ReviewElement extends UIElement { private readonly _reviews: UIEventSource; private readonly _subject: string; - private _middleElement: UIElement; + private readonly _middleElement: UIElement; constructor(subject: string, reviews: UIEventSource, middleElement: UIElement) { super(reviews); @@ -34,7 +34,7 @@ export default class ReviewElement extends UIElement { const avg = (revs.map(review => review.rating).reduce((a, b) => a + b, 0) / revs.length); elements.push( new Combine([ - SingleReview.GenStars(avg).SetClass("stars flex"), + SingleReview.GenStars(avg), ``, revs.length === 1 ? Translations.t.reviews.title_singular : Translations.t.reviews.title @@ -43,7 +43,7 @@ export default class ReviewElement extends UIElement { "" ]) - .SetClass("review-title")); + .SetClass("font-2xl flex justify-between items-center pl-2 pr-2")); elements.push(this._middleElement); @@ -56,7 +56,7 @@ export default class ReviewElement extends UIElement { .SetClass("review-attribution")) - return new Combine(elements).SetClass("review").Render(); + return new Combine(elements).SetClass("block").Render(); } } \ No newline at end of file diff --git a/UI/Reviews/ReviewForm.ts b/UI/Reviews/ReviewForm.ts index 29a6af9..29cc968 100644 --- a/UI/Reviews/ReviewForm.ts +++ b/UI/Reviews/ReviewForm.ts @@ -56,7 +56,7 @@ export default class ReviewForm extends InputElement { onSave(this._value.data, () => { self._saveButton = Translations.t.reviews.saved.SetClass("thanks"); }); - }) + }).SetClass("break-normal") this._isAffiliated = new CheckBoxes([t.i_am_affiliated]) diff --git a/UI/Reviews/SingleReview.ts b/UI/Reviews/SingleReview.ts index 4457363..9a9edd8 100644 --- a/UI/Reviews/SingleReview.ts +++ b/UI/Reviews/SingleReview.ts @@ -22,9 +22,9 @@ export default class SingleReview extends UIElement{ } const scoreTen = Math.round(rating / 10); return new Combine([ - "".repeat(Math.floor(scoreTen / 2)), - scoreTen % 2 == 1 ? "" : "" - ]) + "".repeat(Math.floor(scoreTen / 2)), + scoreTen % 2 == 1 ? "" : "" + ]).SetClass("flex w-max") } InnerRender(): string { const d = this._review.date; @@ -32,26 +32,24 @@ export default class SingleReview extends UIElement{ const el= new Combine( [ new Combine([ - SingleReview.GenStars(review.rating) - .SetClass("review-rating"), - new FixedUiElement(review.comment).SetClass("review-comment") - ]).SetClass("review-stars-comment"), - + SingleReview.GenStars(review.rating) + ]), + new FixedUiElement(review.comment), new Combine([ new Combine([ - new FixedUiElement(review.author).SetClass("review-author"), + new Combine(["",review.author,""]), review.affiliated ? Translations.t.reviews.affiliated_reviewer_warning : "", ]).SetStyle("margin-right: 0.5em"), new FixedUiElement(`${d.getFullYear()}-${Utils.TwoDigits(d.getMonth() + 1)}-${Utils.TwoDigits(d.getDate())} ${Utils.TwoDigits(d.getHours())}:${Utils.TwoDigits(d.getMinutes())}`) - .SetClass("review-date") - ]).SetClass("review-author-date") + .SetClass("subtle-lighter") + ]).SetClass("flex mb-4 justify-end") ] ); - el.SetClass("review-element"); - if(review.made_by_user){ - el.SetClass("review-by-current-user") + el.SetClass("block p-2 m-1 rounded-xl subtle-background review-element"); + if(review.made_by_user.data){ + el.SetClass("border-attention-catch") } return el.Render(); } diff --git a/UI/SpecialVisualizations.ts b/UI/SpecialVisualizations.ts index 5653f73..72772e1 100644 --- a/UI/SpecialVisualizations.ts +++ b/UI/SpecialVisualizations.ts @@ -22,7 +22,7 @@ export default class SpecialVisualizations { public static specialVisualizations: { funcName: string, - constr: ((state: State,tagSource: UIEventSource, argument: string[]) => UIElement), + constr: ((state: State, tagSource: UIEventSource, argument: string[]) => UIElement), docs: string, example?: string, args: { name: string, defaultValue?: string, doc: string }[] @@ -32,7 +32,7 @@ export default class SpecialVisualizations { funcName: "all_tags", docs: "Prints all key-value pairs of the object - used for debugging", args: [], - constr: ((state: State,tags: UIEventSource) => { + constr: ((state: State, tags: UIEventSource) => { return new VariableUiElement(tags.map(tags => { const parts = []; for (const key in tags) { @@ -56,10 +56,10 @@ export default class SpecialVisualizations { defaultValue: "true", doc: "Also include images given via 'Wikidata', 'wikimedia_commons' and 'mapillary" }], - constr: (state: State,tags, args) => { + constr: (state: State, tags, args) => { const imagePrefix = args[0]; const loadSpecial = args[1].toLowerCase() === "true"; - const searcher : UIEventSource<{ key: string, url: string }[]> = new ImageSearcher(tags, imagePrefix, loadSpecial); + const searcher: UIEventSource<{ key: string, url: string }[]> = new ImageSearcher(tags, imagePrefix, loadSpecial); return new ImageCarousel(searcher, tags); } @@ -73,25 +73,28 @@ export default class SpecialVisualizations { doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)", defaultValue: "image" }], - constr: (state: State,tags, args) => { + constr: (state: State, tags, args) => { return new ImageUploadFlow(tags, args[0]) } }, { funcName: "reviews", - docs: "Adds an overview of the mangrove-reviews of this object. IMPORTANT: the _name_ of the object should be defined for this to work!", + docs: "Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten", + example: "{reviews()} for a vanilla review, {reviews(name, play_forest)} to review a play forest. If a name is known, the name will be used as identifier, otherwise 'play_forest' is used", args: [{ - name: "subject", - doc: "The identifier used for this value; by default the name of the reviewed object" + name: "subjectKey", + defaultValue: "name", + doc: "The key to use to determine the subject. If specified, the subject will be tags[subjectKey]" + }, { + name: "fallback", + doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value" }], - constr: (state: State,tags, args) => { + constr: (state: State, tags, args) => { const tgs = tags.data; - let subject = tgs.name ?? ""; - if (args[0] !== undefined && args[0] !== "") { - subject = args[0]; - } - if (subject === "") { + const key = args[0] ?? "name" + let subject = tgs[key] ?? args[1]; + if (subject === undefined || subject === "") { return Translations.t.reviews.name_required; } const mangrove = MangroveReviews.Get(Number(tgs._lon), Number(tgs._lat), @@ -111,7 +114,7 @@ export default class SpecialVisualizations { defaultValue: "opening_hours", doc: "The tagkey from which the table is constructed." }], - constr: (state: State,tagSource: UIEventSource, args) => { + constr: (state: State, tagSource: UIEventSource, args) => { let keyname = args[0]; if (keyname === undefined || keyname === "") { keyname = keyname ?? "opening_hours" @@ -132,7 +135,7 @@ export default class SpecialVisualizations { }, { name: "path", doc: "The path (or shorthand) that should be returned" }], - constr: (state: State,tagSource: UIEventSource, args) => { + constr: (state: State, tagSource: UIEventSource, args) => { const url = args[0]; const shorthands = args[1]; const neededValue = args[2]; @@ -147,10 +150,10 @@ export default class SpecialVisualizations { args: [ { name: "url", - doc: "The url to share (defualt: current URL)", + doc: "The url to share (default: current URL)", } ], - constr: (state: State,tagSource: UIEventSource, args) => { + constr: (state: State, tagSource: UIEventSource, args) => { if (window.navigator.share) { const title = state.layoutToUse.data.title.txt; let name = tagSource.data.name; @@ -204,7 +207,9 @@ export default class SpecialVisualizations { return new Combine([ + "

Special tag renderings

", "In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.", + "General usage is {func_name()} or {func_name(arg, someotherarg)}. Note that you do not need to use quotes around your arguments, the comma is enough to seperate them. This also implies you cannot use a comma in your args", ...helpTexts ] diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index 01b0687..a31aa4c 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -18,19 +18,19 @@ export default class Translations { } - static T(t: string | any): Translation { + static T(t: string | any, context = undefined): Translation { if(t === undefined){ return undefined; } if(typeof t === "string"){ - return new Translation({"*":t}); + return new Translation({"*":t}, context); } if(t.render !== undefined){ const msg = "Creating a translation, but this object contains a 'render'-field. Use the translation directly" console.error(msg, t); throw msg } - return new Translation(t); + return new Translation(t, context); } private static wtcache = {} diff --git a/css/ReviewElement.css b/css/ReviewElement.css index d480def..de9c58e 100644 --- a/css/ReviewElement.css +++ b/css/ReviewElement.css @@ -1,70 +1,3 @@ -.review { - display: block; - margin-top: 1em; -} - -.review-title { - font-size: x-large; - display: flex; - justify-content: space-between; - align-items: center; - padding-left: 1em; - padding-right: 1em; -} - -.review-title img { - max-width: 1.5em; - height: 1.5em; -} - - -.review-rating img { - max-width: 1em; - height: 1em; -} - -.review-by-current-user { - border: 5px solid var(--catch-detail-color); -} - -.review-rating { - display: flex; - flex-direction: row; - width: 5em; - margin-right: 0.5em; - flex-shrink: 0; -} - -.review-date { - color: var(--subtle-detail-color-light-contrast); -} - -.review-stars-comment { - display: flex; - margin-bottom: 0.5em; -} - - - -.review-author { - font-weight: bold; -} - -.review-author-date { - display: flex; - margin-bottom: 0.5em; - justify-content: flex-end; -} - - -.review-element { - padding: 1em; - margin: 0.5em; - display: block; - border-radius: 1em; - background-color: var(--subtle-detail-color); - color: var(--subtle-detail-color-contrast); -} .review-attribution { display: flex; diff --git a/index.css b/index.css index 756fda0..440512f 100644 --- a/index.css +++ b/index.css @@ -19,7 +19,7 @@ .z-above-controls{ z-index: 10001 } - + } .btn { @@ -110,7 +110,15 @@ a { .subtle-background { background: var(--subtle-detail-color); + color: var(--subtle-detail-color-contrast); } + +.subtle-lighter { + color: var(--subtle-detail-color-light-contrast); +} + +.border-attention-catch{ border: 5px solid var(--catch-detail-color);} + .slick-prev:before, .slick-next:before { /*Slideshow workaround*/ color:black !important;