UX: add warning for too long reviews, see #1775

This commit is contained in:
Pieter Vander Vennet 2024-02-12 15:53:37 +01:00
parent f0152ce856
commit fa9aca0685
3 changed files with 77 additions and 50 deletions

View file

@ -676,6 +676,7 @@
"saving_review": "Saving…", "saving_review": "Saving…",
"title": "{count} reviews", "title": "{count} reviews",
"title_singular": "One review", "title_singular": "One review",
"too_long": "At most {max} characters are allowed. Your review has {amount} characters.",
"tos": "If you create a review, you agree to <a href='https://mangrove.reviews/terms' target='_blank'>the TOS and privacy policy of Mangrove.reviews</a>", "tos": "If you create a review, you agree to <a href='https://mangrove.reviews/terms' target='_blank'>the TOS and privacy policy of Mangrove.reviews</a>",
"write_a_comment": "Leave a review…" "write_a_comment": "Leave a review…"
}, },

View file

@ -52,6 +52,10 @@ export class MangroveIdentity {
* Tracks all reviews of a given feature, allows to create a new review * Tracks all reviews of a given feature, allows to create a new review
*/ */
export default class FeatureReviews { export default class FeatureReviews {
/**
* See https://gitlab.com/open-reviews/mangrove/-/blob/master/servers/reviewer/src/review.rs#L269 and https://github.com/pietervdvn/MapComplete/issues/1775
*/
public static readonly REVIEW_OPINION_MAX_LENGTH = 1000
private static readonly _featureReviewsCache: Record<string, FeatureReviews> = {} private static readonly _featureReviewsCache: Record<string, FeatureReviews> = {}
public readonly subjectUri: Store<string> public readonly subjectUri: Store<string>
public readonly average: Store<number | null> public readonly average: Store<number | null>
@ -172,6 +176,9 @@ export default class FeatureReviews {
* The given review is uploaded to mangrove.reviews and added to the list of known reviews * The given review is uploaded to mangrove.reviews and added to the list of known reviews
*/ */
public async createReview(review: Omit<Review, "sub">): Promise<void> { public async createReview(review: Omit<Review, "sub">): Promise<void> {
if(review.opinion.length > FeatureReviews .REVIEW_OPINION_MAX_LENGTH){
throw "Opinion too long, should be at most "+FeatureReviews.REVIEW_OPINION_MAX_LENGTH+" characters long"
}
const r: Review = { const r: Review = {
sub: this.subjectUri.data, sub: this.subjectUri.data,
...review, ...review,

View file

@ -3,7 +3,7 @@
import StarsBar from "./StarsBar.svelte" import StarsBar from "./StarsBar.svelte"
import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte" import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte"
import type { SpecialVisualizationState } from "../SpecialVisualization" import type { SpecialVisualizationState } from "../SpecialVisualization"
import { UIEventSource } from "../../Logic/UIEventSource" import { Store, UIEventSource } from "../../Logic/UIEventSource"
import type { Feature } from "geojson" import type { Feature } from "geojson"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
@ -14,6 +14,7 @@
import { Review } from "mangrove-reviews-typescript" import { Review } from "mangrove-reviews-typescript"
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
import { placeholder } from "../../Utils/placeholder" import { placeholder } from "../../Utils/placeholder"
import { ExclamationTriangle } from "@babeard/svelte-heroicons/solid/ExclamationTriangle"
export let state: SpecialVisualizationState export let state: SpecialVisualizationState
export let tags: UIEventSource<Record<string, string>> export let tags: UIEventSource<Record<string, string>>
@ -36,7 +37,18 @@
const connection = state.osmConnection const connection = state.osmConnection
const hasError: Store<undefined | "too_long"> = opinion.mapD(op => {
const tooLong = op.length > FeatureReviews.REVIEW_OPINION_MAX_LENGTH
if (tooLong) {
return "too_long"
}
return undefined
})
async function save() { async function save() {
if (hasError.data) {
return
}
_state = "saving" _state = "saving"
let nickname = undefined let nickname = undefined
if (connection.isLoggedIn.data) { if (connection.isLoggedIn.data) {
@ -95,6 +107,12 @@
class="mb-1 w-full" class="mb-1 w-full"
use:placeholder={t.reviewPlaceholder} use:placeholder={t.reviewPlaceholder}
/> />
{#if $hasError === "too_long"}
<div class="alert flex items-center px-2">
<ExclamationTriangle class="w-12 h-12"/>
<Tr t={t.too_long.Subs({max: FeatureReviews.REVIEW_OPINION_MAX_LENGTH, amount: $opinion?.length ?? 0})}> </Tr>
</div>
{/if}
</label> </label>
<Checkbox selected={isAffiliated}> <Checkbox selected={isAffiliated}>
@ -108,7 +126,8 @@
<Tr t={t.reviewing_as.Subs({ nickname: state.osmConnection.userDetails.data.name })} /> <Tr t={t.reviewing_as.Subs({ nickname: state.osmConnection.userDetails.data.name })} />
<Tr slot="else" t={t.reviewing_as_anonymous} /> <Tr slot="else" t={t.reviewing_as_anonymous} />
</If> </If>
<button class="primary" on:click={save}> <button class="primary" class:disabled={$hasError !== undefined}
on:click={save}>
<Tr t={t.save} /> <Tr t={t.save} />
</button> </button>
</div> </div>