Skip to content

Commit

Permalink
Feat: allow to disable questions (and to enable them again), fix #256
Browse files Browse the repository at this point in the history
  • Loading branch information
pietervdvn committed Oct 8, 2024
1 parent f8ef32f commit 93ebdd8
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 76 deletions.
8 changes: 8 additions & 0 deletions assets/layers/usersettings/usersettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,14 @@
}
]
},
{
"id": "disabled-questions",
"render": {
"special": {
"type": "disabled_questions"
}
}
},
{
"id": "title-privacy-legal",
"render": {
Expand Down
10 changes: 10 additions & 0 deletions src/Logic/State/UserRelatedState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,4 +545,14 @@ export default class UserRelatedState {

return amendedPrefs
}


/**
* The disabled questions for this theme and layer
*/
public getThemeDisabled(themeId: string, layerId: string): UIEventSource<string[]> {
const flatSource = this.osmConnection.getPreference("disabled-questions-" + themeId + "-" + layerId, "[]")
return UIEventSource.asObject<string[]>(flatSource, [])
}

}
14 changes: 7 additions & 7 deletions src/UI/Base/DotMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
export let open = new UIEventSource(false)
export let dotsSize = `w-6 h-6`
export let dotsPosition = `top-0 right-0`
export let hideBackground= false
export let hideBackground: boolean = false
let menuPosition = ``
if(dotsPosition.indexOf("left-0") >= 0){
if (dotsPosition.indexOf("left-0") >= 0) {
menuPosition = "left-0"
}else{
} else {
menuPosition = `right-0`
}
if(dotsPosition.indexOf("top-0") > 0){
if (dotsPosition.indexOf("top-0") > 0) {
menuPosition += " bottom-0"
}else{
} else {
menuPosition += ` top-0`
}
Expand Down Expand Up @@ -49,7 +49,7 @@
}
:global(.dots-menu > path) {
fill: var(--interactive-background);
fill: var(--button-background-hover);
transition: fill 350ms linear;
cursor: pointer;
Expand All @@ -74,7 +74,7 @@
}
.transition-background {
transition: background-color 150ms linear;
transition: background-color 150ms linear;
}
.transition-background.collapsed {
Expand Down
23 changes: 23 additions & 0 deletions src/UI/Popup/DisabledQuestions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import DisabledQuestionsLayer from "./DisabledQuestionsLayer.svelte"
import { Stores } from "../../Logic/UIEventSource"
/**
* Shows _all_ disabled questions
*/
export let state
let layers = state.layout.layers.filter(l => l.isNormal())
let allDisabled = Stores.concat<string>(layers.map(l => state.userRelatedState.getThemeDisabled(state.layout.id, l.id))).map(l => [].concat(...l))
</script>

<h3>Disabled questions</h3>
{#if $allDisabled.length === 0}
To disable a question, click the three dots in the upper-right corner
{:else}
To enable a question again, click it
{#each layers as layer (layer.id)}
<DisabledQuestionsLayer {state} {layer} />
{/each}
{/if}
45 changes: 45 additions & 0 deletions src/UI/Popup/DisabledQuestionsLayer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts">/**
* Gives an overview of questions which are disabled for the given theme
*/
import UserRelatedState from "../../Logic/State/UserRelatedState"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import ThemeViewState from "../../Models/ThemeViewState"
import Tr from "../Base/Tr.svelte"
import { Translation } from "../i18n/Translation"
import { XMarkIcon } from "@babeard/svelte-heroicons/mini"
import ToSvelte from "../Base/ToSvelte.svelte"
export let layer: LayerConfig
export let state: ThemeViewState
let disabledQuestions = state.userRelatedState.getThemeDisabled(state.layout.id, layer.id)
function getQuestion(id: string): Translation {
return layer.tagRenderings.find(q => q.id === id).question.Subs({})
}
function enable(idToEnable: string) {
const newList = disabledQuestions.data.filter(id => id !== idToEnable)
disabledQuestions.set(newList)
}
</script>

{#if $disabledQuestions.length > 0}
<div class="low-interaction p-2">

<h4 class="flex my-2">
<div class="no-image-background block h-6 w-6">
<ToSvelte construct={() => layer.defaultIcon()} />
</div>
<Tr t={layer.name} />
</h4>
<div class="flex">
{#each $disabledQuestions as id}
<button class="badge button-unstyled" on:click={() => enable(id)}>
<Tr cls="ml-2" t={getQuestion(id)} />
<XMarkIcon class="w-4 h-4 mr-2" />
</button>
{/each}
</div>
</div>
{/if}
168 changes: 100 additions & 68 deletions src/UI/Popup/TagRendering/Questionbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,20 @@
}
return true
}
const baseQuestions = (layer?.tagRenderings ?? [])?.filter(
(tr) => allowed(tr.labels) && tr.question !== undefined
(tr) => allowed(tr.labels) && tr.question !== undefined,
)
/**
* Ids of skipped questions
*/
let skippedQuestions = new UIEventSource<Set<string>>(new Set<string>())
let layerDisabledForTheme = state.userRelatedState.getThemeDisabled(state.layout.id, layer.id)
layerDisabledForTheme.addCallbackAndRunD(disabled => {
skippedQuestions.set(new Set(disabled.concat(Array.from(skippedQuestions.data))))
})
let questionboxElem: HTMLDivElement
let questionsToAsk = tags.map(
(tags) => {
Expand All @@ -69,10 +78,10 @@
}
return questionsToAsk
},
[skippedQuestions]
[skippedQuestions],
)
let firstQuestion: UIEventSource<TagRenderingConfig> = new UIEventSource<TagRenderingConfig>(
undefined
undefined,
)
let allQuestionsToAsk: UIEventSource<TagRenderingConfig[]> = new UIEventSource<
TagRenderingConfig[]
Expand All @@ -95,6 +104,8 @@
let skipped: number = 0
let loginEnabled = state.featureSwitches.featureSwitchEnableLogin
let debug = state.featureSwitches.featureSwitchIsDebugging
function skip(question: { id: string }, didAnswer: boolean = false) {
skippedQuestions.data.add(question.id) // Must use ID, the config object might be a copy of the original
Expand All @@ -117,43 +128,84 @@
class="marker-questionbox-root"
class:hidden={$questionsToAsk.length === 0 && skipped === 0 && answered === 0}
>
{#if $showAllQuestionsAtOnce}
<div class="flex flex-col gap-y-1">
{#each $allQuestionsToAsk as question (question.id)}
<TagRenderingQuestionDynamic
config={question}
{tags}
{selectedElement}
{state}
{layer}
/>
{/each}
</div>
{:else if $firstQuestion !== undefined}
<TagRenderingQuestionDynamic
config={$firstQuestion}
{layer}
{selectedElement}
{state}
{tags}
on:saved={() => {
skip($firstQuestion, true)
}}
>
<button
class="secondary"
on:click={() => {
skip($firstQuestion)
}}
slot="cancel"
>
<Tr t={Translations.t.general.skip} />
</button>
</TagRenderingQuestionDynamic>
{/if}

{#if $allQuestionsToAsk.length === 0}
<div class="thanks">
<Tr t={Translations.t.general.questionBox.done} />
</div>
{/if}

<div class="mt-4 mb-8">

{#if skipped + answered > 0}
<div class="thanks">
<Tr t={Translations.t.general.questionBox.done} />
</div>
{#if answered === 0}
{#if skipped === 1}
<Tr t={Translations.t.general.questionBox.skippedOne} />
{:else}
<Tr t={Translations.t.general.questionBox.skippedMultiple.Subs({ skipped })} />
{/if}
{:else if answered === 1}
{#if skipped === 0}
<Tr t={Translations.t.general.questionBox.answeredOne} />
<div class="flex justify-center">
{#if answered === 0}
{#if skipped === 1}
<Tr t={Translations.t.general.questionBox.skippedOne} />
{:else}
<Tr t={Translations.t.general.questionBox.skippedMultiple.Subs({ skipped })} />
{/if}
{:else if answered === 1}
{#if skipped === 0}
<Tr t={Translations.t.general.questionBox.answeredOne} />
{:else if skipped === 1}
<Tr t={Translations.t.general.questionBox.answeredOneSkippedOne} />
{:else}
<Tr
t={Translations.t.general.questionBox.answeredOneSkippedMultiple.Subs({ skipped })}
/>
{/if}
{:else if skipped === 0}
<Tr t={Translations.t.general.questionBox.answeredMultiple.Subs({ answered })} />
{:else if skipped === 1}
<Tr t={Translations.t.general.questionBox.answeredOneSkippedOne} />
{:else}
<Tr
t={Translations.t.general.questionBox.answeredOneSkippedMultiple.Subs({ skipped })}
t={Translations.t.general.questionBox.answeredMultipleSkippedOne.Subs({ answered })}
/>
{/if}
{:else if skipped === 0}
<Tr t={Translations.t.general.questionBox.answeredMultiple.Subs({ answered })} />
{:else if skipped === 1}
<Tr
t={Translations.t.general.questionBox.answeredMultipleSkippedOne.Subs({ answered })}
/>
{:else}
<Tr
t={Translations.t.general.questionBox.answeredMultipleSkippedMultiple.Subs({
{:else}
<Tr
t={Translations.t.general.questionBox.answeredMultipleSkippedMultiple.Subs({
answered,
skipped,
})}
/>
{/if}
/>
{/if}
</div>

{#if skipped > 0}
{#if skipped + $skippedQuestions.size > 0}
<button
class="w-full"
on:click={() => {
Expand All @@ -163,45 +215,25 @@
>
<Tr t={Translations.t.general.questionBox.reactivate} />
</button>

{/if}
{/if}
{:else}
<div>
{#if $showAllQuestionsAtOnce}
<div class="flex flex-col gap-y-1">
{#each $allQuestionsToAsk as question (question.id)}
<TagRenderingQuestionDynamic
config={question}
{tags}
{selectedElement}
{state}
{layer}
/>
{/each}
</div>
{:else if $firstQuestion !== undefined}
<TagRenderingQuestionDynamic
config={$firstQuestion}
{layer}
{selectedElement}
{state}
{tags}
on:saved={() => {
skip($firstQuestion, true)

{#if $skippedQuestions.size - skipped > 0}
<button
class="w-full"
on:click={() => {
skippedQuestions.setData(new Set())
skipped = 0
}}
>
<button
class="secondary"
on:click={() => {
skip($firstQuestion)
}}
slot="cancel"
>
<Tr t={Translations.t.general.skip} />
</button>
</TagRenderingQuestionDynamic>
{/if}
</div>
{/if}
>
Show the disabled questions for this object
</button>

{/if}
{#if $debug}
Skipped questions are {Array.from($skippedQuestions).join(", ")}
{/if}
</div>
</div>
{/if}
Loading

0 comments on commit 93ebdd8

Please sign in to comment.