forked from MapComplete/MapComplete
Refactoring: fix #2190, refactor noteCommentElement into svelte
This commit is contained in:
parent
565f1041fc
commit
1a3bb7bb27
3 changed files with 232 additions and 243 deletions
103
src/UI/Popup/Notes/NoteCommentElement.svelte
Normal file
103
src/UI/Popup/Notes/NoteCommentElement.svelte
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<script lang="ts">
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||
import Translations from "../../i18n/Translations"
|
||||
import Note from "../../../assets/svg/Note.svelte"
|
||||
import Resolved from "../../../assets/svg/Resolved.svelte"
|
||||
import Speech_bubble from "../../../assets/svg/Speech_bubble.svelte"
|
||||
import { ImmutableStore, Stores } from "../../../Logic/UIEventSource"
|
||||
import { Utils } from "../../../Utils"
|
||||
import Img from "../../Base/Img"
|
||||
import { SlideShow } from "../../Image/SlideShow"
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte"
|
||||
import Tr from "../../Base/Tr.svelte"
|
||||
|
||||
export let comment: {
|
||||
date: string
|
||||
uid: number
|
||||
user: string
|
||||
user_url: string
|
||||
action: "closed" | "opened" | "reopened" | "commented"
|
||||
text: string
|
||||
html: string
|
||||
highlighted: boolean
|
||||
}
|
||||
export let state: SpecialVisualizationState = undefined
|
||||
|
||||
const t = Translations.t.notes
|
||||
|
||||
// Info about the user who made the comment
|
||||
let userinfo = Stores.FromPromise(
|
||||
Utils.downloadJsonCached<{ user: { img: { href: string } } }>(
|
||||
"https://api.openstreetmap.org/api/0.6/user/" + comment.uid,
|
||||
24 * 60 * 60 * 1000,
|
||||
),
|
||||
)
|
||||
|
||||
const htmlElement = document.createElement("div")
|
||||
htmlElement.innerHTML = Utils.purify(comment.html)
|
||||
let images: string[] = Array.from(htmlElement.getElementsByTagName("a"))
|
||||
.map((link) => link.href)
|
||||
.filter((link) => {
|
||||
link = link.toLowerCase()
|
||||
const lastDotIndex = link.lastIndexOf(".")
|
||||
const extension = link.substring(lastDotIndex + 1, link.length)
|
||||
return Utils.imageExtensions.has(extension)
|
||||
})
|
||||
.filter((link) => !link.startsWith("https://wiki.openstreetmap.org/wiki/File:"))
|
||||
|
||||
|
||||
let imgStore = new ImmutableStore(
|
||||
images.map((i) =>
|
||||
new Img(i).SetClass("w-full block cursor-pointer")
|
||||
.onClick(() =>
|
||||
state?.previewedImage?.setData(
|
||||
<any>{
|
||||
url_hd: i,
|
||||
url: i,
|
||||
}),
|
||||
)))
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col py-2 my-2 border-gray-500 border-b" class:border-interactive={comment.highlighted}>
|
||||
|
||||
<div class="flex">
|
||||
|
||||
<!-- Action icon, e.g. 'created', 'commented', 'closed' -->
|
||||
{#if comment.action === "opened" || comment.action === "reopened"}
|
||||
<Note class="shrink-0 mr-4 w-6" />
|
||||
{:else if comment.action === "closed"}
|
||||
<Resolved class="shrink-0 mr-4 w-6" />
|
||||
{:else}
|
||||
<Speech_bubble class="shrink-0 mr-4 w-6" />
|
||||
{/if}
|
||||
<div class="flex flex-col gap-y-2">
|
||||
{@html comment.html}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if images.length > 0}
|
||||
<ToSvelte
|
||||
construct={() => new SlideShow(imgStore) .SetClass("mb-1").SetStyle("min-width: 50px; background: grey;")} />
|
||||
{/if}
|
||||
|
||||
|
||||
<div class="flex justify-end items-center subtle pt-4 pb-2">
|
||||
<!-- commenter info -->
|
||||
|
||||
{#if $userinfo?.user?.img?.href}
|
||||
<img alt="avatar" aria-hidden="true" src={$userinfo?.user?.img?.href} class="rounded-full w-8 h-8 mr-4" />
|
||||
{/if}
|
||||
|
||||
<span class="mr-2">
|
||||
{#if comment.user === undefined}
|
||||
<Tr t={t.anonymous} />
|
||||
{:else}
|
||||
<a href={comment.user_url} target="_blank">{comment.user}</a>
|
||||
{/if}
|
||||
{comment.date}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,117 +1,7 @@
|
|||
import Combine from "../../Base/Combine"
|
||||
import BaseUIElement from "../../BaseUIElement"
|
||||
import Link from "../../Base/Link"
|
||||
import { FixedUiElement } from "../../Base/FixedUiElement"
|
||||
import Translations from "../../i18n/Translations"
|
||||
import { Utils } from "../../../Utils"
|
||||
import Img from "../../Base/Img"
|
||||
import { SlideShow } from "../../Image/SlideShow"
|
||||
import { Store, Stores, UIEventSource } from "../../../Logic/UIEventSource"
|
||||
import { VariableUiElement } from "../../Base/VariableUIElement"
|
||||
import { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||
import SvelteUIElement from "../../Base/SvelteUIElement"
|
||||
import Note from "../../../assets/svg/Note.svelte"
|
||||
import Resolved from "../../../assets/svg/Resolved.svelte"
|
||||
import Speech_bubble from "../../../assets/svg/Speech_bubble.svelte"
|
||||
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
|
||||
|
||||
export default class NoteCommentElement extends Combine {
|
||||
constructor(
|
||||
comment: {
|
||||
date: string
|
||||
uid: number
|
||||
user: string
|
||||
user_url: string
|
||||
action: "closed" | "opened" | "reopened" | "commented"
|
||||
text: string
|
||||
html: string
|
||||
highlighted: boolean
|
||||
},
|
||||
state?: SpecialVisualizationState,
|
||||
index?: number,
|
||||
totalNumberOfComments?: number
|
||||
) {
|
||||
const t = Translations.t.notes
|
||||
export default class NoteCommentElement {
|
||||
|
||||
let actionIcon: BaseUIElement
|
||||
if (comment.action === "opened" || comment.action === "reopened") {
|
||||
actionIcon = new SvelteUIElement(Note)
|
||||
} else if (comment.action === "closed") {
|
||||
actionIcon = new SvelteUIElement(Resolved)
|
||||
} else {
|
||||
actionIcon = new SvelteUIElement(Speech_bubble)
|
||||
}
|
||||
|
||||
let user: BaseUIElement
|
||||
if (comment.user === undefined) {
|
||||
user = t.anonymous
|
||||
} else {
|
||||
user = new Link(comment.user, comment.user_url ?? "", true)
|
||||
}
|
||||
|
||||
const userinfo = Stores.FromPromise(
|
||||
Utils.downloadJsonCached<{ user: { img: { href: string } } }>(
|
||||
"https://api.openstreetmap.org/api/0.6/user/" + comment.uid,
|
||||
24 * 60 * 60 * 1000
|
||||
)
|
||||
)
|
||||
const userImg = new VariableUiElement(
|
||||
userinfo.map((userinfo) => {
|
||||
const href = userinfo?.user?.img?.href
|
||||
if (href !== undefined) {
|
||||
return new Img(href).SetClass("rounded-full w-8 h-8 mr-4")
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
)
|
||||
|
||||
const htmlElement = document.createElement("div")
|
||||
htmlElement.innerHTML = Utils.purify(comment.html)
|
||||
const images = Array.from(htmlElement.getElementsByTagName("a"))
|
||||
.map((link) => link.href)
|
||||
.filter((link) => {
|
||||
link = link.toLowerCase()
|
||||
const lastDotIndex = link.lastIndexOf(".")
|
||||
const extension = link.substring(lastDotIndex + 1, link.length)
|
||||
return Utils.imageExtensions.has(extension)
|
||||
})
|
||||
.filter((link) => !link.startsWith("https://wiki.openstreetmap.org/wiki/File:"))
|
||||
let imagesEl: BaseUIElement = undefined
|
||||
if (images.length > 0) {
|
||||
const imageEls = images.map((i) =>
|
||||
new Img(i)
|
||||
.SetClass("w-full block cursor-pointer")
|
||||
.onClick(() =>
|
||||
state?.previewedImage?.setData(<any>{
|
||||
url_hd: i,
|
||||
url: i,
|
||||
})
|
||||
)
|
||||
.SetStyle("min-width: 50px; background: grey;")
|
||||
)
|
||||
imagesEl = new SlideShow(new UIEventSource<BaseUIElement[]>(imageEls)).SetClass("mb-1")
|
||||
}
|
||||
|
||||
super([
|
||||
new Combine([
|
||||
actionIcon.SetClass("mr-4 w-6").SetStyle("flex-shrink: 0"),
|
||||
new FixedUiElement(comment.html).SetClass("flex flex-col").SetStyle("margin: 0"),
|
||||
]).SetClass("flex"),
|
||||
imagesEl,
|
||||
new Combine([userImg, user.SetClass("mr-2"), comment.date]).SetClass(
|
||||
"flex justify-end items-center subtle"
|
||||
),
|
||||
])
|
||||
this.SetClass("flex flex-col pb-2 mb-2 border-gray-500 border-b")
|
||||
if (comment.highlighted) {
|
||||
this.SetClass("focus")
|
||||
if (index + 2 === totalNumberOfComments) {
|
||||
console.log("Scrolling into view")
|
||||
requestAnimationFrame(() => {
|
||||
this.ScrollIntoView()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the comment to the _visualisation_ of the given note; doesn't _actually_ upload
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue