forked from MapComplete/MapComplete
		
	Merge develop
This commit is contained in:
		
						commit
						55ebaaa256
					
				
					 17 changed files with 640 additions and 645 deletions
				
			
		| 
						 | 
					@ -430,10 +430,10 @@
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "favourite_icon",
 | 
					      "condition": "_favourite=yes",
 | 
				
			||||||
      "description": "Only for rendering",
 | 
					      "description": "Only for rendering",
 | 
				
			||||||
      "icon": "circle:white;heart:red",
 | 
					      "icon": "circle:white;heart:red",
 | 
				
			||||||
      "condition": "_favourite=yes",
 | 
					      "id": "favourite_icon",
 | 
				
			||||||
      "metacondition": "__showTimeSensitiveIcons!=no"
 | 
					      "metacondition": "__showTimeSensitiveIcons!=no"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,8 +217,8 @@
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "debug",
 | 
					      "id": "debug",
 | 
				
			||||||
      "render": "{all_tags()}",
 | 
					      "metacondition": "__featureSwitchIsDebugging=true",
 | 
				
			||||||
      "metacondition": "__featureSwitchIsDebugging=true"
 | 
					      "render": "{all_tags()}"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "filter": [
 | 
					  "filter": [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,9 +114,9 @@
 | 
				
			||||||
  "lineRendering": [],
 | 
					  "lineRendering": [],
 | 
				
			||||||
  "tagRenderings": [
 | 
					  "tagRenderings": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					      "classes": "p-0",
 | 
				
			||||||
      "id": "conversation",
 | 
					      "id": "conversation",
 | 
				
			||||||
      "render": "{visualize_note_comments()}",
 | 
					      "render": "{visualize_note_comments()}"
 | 
				
			||||||
      "classes": "p-0"
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "add_image",
 | 
					      "id": "add_image",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,16 +66,16 @@
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "tagRenderings": [
 | 
					  "tagRenderings": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "country_name",
 | 
					      "condition": "level=country",
 | 
				
			||||||
      "description": "The name of the country",
 | 
					      "description": "The name of the country",
 | 
				
			||||||
      "render": "{nameEn} {emojiFlag}",
 | 
					      "id": "country_name",
 | 
				
			||||||
      "condition": "level=country"
 | 
					      "render": "{nameEn} {emojiFlag}"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "community_links",
 | 
					      "condition": "_community_links~*",
 | 
				
			||||||
      "description": "Community Links (Discord, meetups, Slack groups, IRC channels, mailing lists etc...)",
 | 
					      "description": "Community Links (Discord, meetups, Slack groups, IRC channels, mailing lists etc...)",
 | 
				
			||||||
      "render": "{_community_links}",
 | 
					      "id": "community_links",
 | 
				
			||||||
      "condition": "_community_links~*"
 | 
					      "render": "{_community_links}"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "filter": [
 | 
					  "filter": [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
		 Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3.1 MiB  | 
| 
						 | 
					@ -6,6 +6,7 @@ import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig"
 | 
				
			||||||
import LayerConfig from "../src/Models/ThemeConfig/LayerConfig"
 | 
					import LayerConfig from "../src/Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
import { Utils } from "../src/Utils"
 | 
					import { Utils } from "../src/Utils"
 | 
				
			||||||
import { Lists } from "../src/Utils/Lists"
 | 
					import { Lists } from "../src/Utils/Lists"
 | 
				
			||||||
 | 
					import { Strings } from "../src/Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Generates all the files in "Docs/TagInfo". These are picked up by the taginfo project, showing a link to the mapcomplete theme if the key is used
 | 
					 * Generates all the files in "Docs/TagInfo". These are picked up by the taginfo project, showing a link to the mapcomplete theme if the key is used
 | 
				
			||||||
| 
						 | 
					@ -107,8 +108,8 @@ function generateLayerUsage(layer: LayerConfig): TagInfoPrototype[] {
 | 
				
			||||||
                layerName,
 | 
					                layerName,
 | 
				
			||||||
                shownText: descr,
 | 
					                shownText: descr,
 | 
				
			||||||
                layer,
 | 
					                layer,
 | 
				
			||||||
                icon: !Utils.isEmoji(tr.renderIcon) ? tr.renderIcon : undefined,
 | 
					                icon: !Strings.isEmoji(tr.renderIcon) ? tr.renderIcon : undefined,
 | 
				
			||||||
                emoji: Utils.isEmoji(tr.renderIcon) ? tr.renderIcon : undefined,
 | 
					                emoji: Strings.isEmoji(tr.renderIcon) ? tr.renderIcon : undefined,
 | 
				
			||||||
                trid: tr.id,
 | 
					                trid: tr.id,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -123,8 +124,8 @@ function generateLayerUsage(layer: LayerConfig): TagInfoPrototype[] {
 | 
				
			||||||
                    shownText: `${mapping.if.asHumanString()} is displayed as "${
 | 
					                    shownText: `${mapping.if.asHumanString()} is displayed as "${
 | 
				
			||||||
                        mapping.then.txt
 | 
					                        mapping.then.txt
 | 
				
			||||||
                    }"`,
 | 
					                    }"`,
 | 
				
			||||||
                    icon: !Utils.isEmoji(mapping.icon) ? mapping.icon : undefined,
 | 
					                    icon: !Strings.isEmoji(mapping.icon) ? mapping.icon : undefined,
 | 
				
			||||||
                    emoji: Utils.isEmoji(mapping.icon) ? mapping.icon : undefined,
 | 
					                    emoji: Strings.isEmoji(mapping.icon) ? mapping.icon : undefined,
 | 
				
			||||||
                    trid: tr.id,
 | 
					                    trid: tr.id,
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ export class ChangesetHandler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        extraMetaTags = [...extraMetaTags, ...this.defaultChangesetTags()]
 | 
					        extraMetaTags = [...extraMetaTags, ...this.defaultChangesetTags()]
 | 
				
			||||||
        extraMetaTags = ChangesetHandler.removeDuplicateMetaTags(extraMetaTags)
 | 
					        extraMetaTags = ChangesetHandler.removeDuplicateMetaTags(extraMetaTags)
 | 
				
			||||||
        if (this.userDetails.data.csCount == 0) {
 | 
					        if (this.userDetails.data?.csCount == 0) {
 | 
				
			||||||
            // The user became a contributor!
 | 
					            // The user became a contributor!
 | 
				
			||||||
            this.userDetails.data.csCount = 1
 | 
					            this.userDetails.data.csCount = 1
 | 
				
			||||||
            this.userDetails.ping()
 | 
					            this.userDetails.ping()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
import LayerState from "../State/LayerState"
 | 
					import LayerState from "../State/LayerState"
 | 
				
			||||||
import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
 | 
					import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
 | 
				
			||||||
import { Lists } from "../../Utils/Lists"
 | 
					import { Lists } from "../../Utils/Lists"
 | 
				
			||||||
 | 
					import { Strings } from "../../Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type FilterSearchResult = {
 | 
					export type FilterSearchResult = {
 | 
				
			||||||
    option: FilterConfigOption
 | 
					    option: FilterConfigOption
 | 
				
			||||||
| 
						 | 
					@ -30,7 +31,7 @@ export default class FilterSearch {
 | 
				
			||||||
        const queries = query
 | 
					        const queries = query
 | 
				
			||||||
            .split(" ")
 | 
					            .split(" ")
 | 
				
			||||||
            .map((query) => {
 | 
					            .map((query) => {
 | 
				
			||||||
                if (!Utils.isEmoji(query)) {
 | 
					                if (!Strings.isEmoji(query)) {
 | 
				
			||||||
                    return Utils.simplifyStringForSearch(query)
 | 
					                    return Utils.simplifyStringForSearch(query)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return query
 | 
					                return query
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,9 +107,10 @@ export class GeoLocationState {
 | 
				
			||||||
            this.requestPermission()
 | 
					            this.requestPermission()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const hasLocation: Store<boolean> = this.currentGPSLocation.map(l => l !== undefined)
 | 
				
			||||||
        this.gpsStateExplanation = this.gpsAvailable.map(
 | 
					        this.gpsStateExplanation = this.gpsAvailable.map(
 | 
				
			||||||
            (available) => {
 | 
					            (available) => {
 | 
				
			||||||
                if (this.currentGPSLocation.data !== undefined) {
 | 
					                if (hasLocation.data) {
 | 
				
			||||||
                    if (!this.allowMoving.data) {
 | 
					                    if (!this.allowMoving.data) {
 | 
				
			||||||
                        return Translations.t.general.visualFeedback.islocked
 | 
					                        return Translations.t.general.visualFeedback.islocked
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -131,7 +132,7 @@ export class GeoLocationState {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return Translations.t.general.waitingForLocation
 | 
					                return Translations.t.general.waitingForLocation
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            [this.allowMoving, this.permission, this.currentGPSLocation]
 | 
					            [this.allowMoving, this.permission, hasLocation]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ import { FlatTag, OptimizedTag, TagsFilterClosed } from "../../../Logic/Tags/Tag
 | 
				
			||||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
 | 
					import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
 | 
				
			||||||
import { Translation } from "../../../UI/i18n/Translation"
 | 
					import { Translation } from "../../../UI/i18n/Translation"
 | 
				
			||||||
import { Lists } from "../../../Utils/Lists"
 | 
					import { Lists } from "../../../Utils/Lists"
 | 
				
			||||||
 | 
					import { Strings } from "../../../Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class PruneFilters extends DesugaringStep<LayerConfigJson> {
 | 
					export class PruneFilters extends DesugaringStep<LayerConfigJson> {
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
| 
						 | 
					@ -158,7 +159,7 @@ export class ExpandFilter extends DesugaringStep<LayerConfigJson> {
 | 
				
			||||||
        const options = qtr.mappings.map((mapping) => {
 | 
					        const options = qtr.mappings.map((mapping) => {
 | 
				
			||||||
            let icon: string = mapping.icon?.["path"] ?? mapping.icon
 | 
					            let icon: string = mapping.icon?.["path"] ?? mapping.icon
 | 
				
			||||||
            let emoji: string = undefined
 | 
					            let emoji: string = undefined
 | 
				
			||||||
            if (Utils.isEmoji(icon)) {
 | 
					            if (Strings.isEmoji(icon)) {
 | 
				
			||||||
                emoji = icon
 | 
					                emoji = icon
 | 
				
			||||||
                icon = undefined
 | 
					                icon = undefined
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import { PrevalidateLayer } from "./PrevalidateLayer"
 | 
				
			||||||
import { AvailableRasterLayers } from "../../RasterLayers"
 | 
					import { AvailableRasterLayers } from "../../RasterLayers"
 | 
				
			||||||
import { eliCategory } from "../../RasterLayerProperties"
 | 
					import { eliCategory } from "../../RasterLayerProperties"
 | 
				
			||||||
import licenses from "../../../assets/generated/license_info.json"
 | 
					import licenses from "../../../assets/generated/license_info.json"
 | 
				
			||||||
 | 
					import { Strings } from "../../../Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
 | 
					export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
 | 
				
			||||||
    private readonly _languages: string[]
 | 
					    private readonly _languages: string[]
 | 
				
			||||||
| 
						 | 
					@ -105,7 +106,7 @@ export class DoesImageExist extends DesugaringStep<string> {
 | 
				
			||||||
            return image
 | 
					            return image
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Utils.isEmoji(image)) {
 | 
					        if (Strings.isEmoji(image)) {
 | 
				
			||||||
            return image
 | 
					            return image
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,11 @@
 | 
				
			||||||
<script lang="ts">/**
 | 
					<script lang="ts">/**
 | 
				
			||||||
 * Show a compass. The compass outline rotates with the map, the compass needle points to the actual north
 | 
					 * Show a compass. The compass outline rotates with the map, the compass needle points to the actual north
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
import { UIEventSource } from "../../Logic/UIEventSource"
 | 
					import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
import { Orientation } from "../../Sensors/Orientation"
 | 
					import { Orientation } from "../../Sensors/Orientation"
 | 
				
			||||||
import Compass_back from "../../assets/svg/Compass_back.svelte"
 | 
					import Compass_back from "../../assets/svg/Compass_back.svelte"
 | 
				
			||||||
import Compass_needle from "../../assets/svg/Compass_needle.svelte"
 | 
					import Compass_needle from "../../assets/svg/Compass_needle.svelte"
 | 
				
			||||||
import North_arrow from "../../assets/svg/North_arrow.svelte"
 | 
					import North_arrow from "../../assets/svg/North_arrow.svelte"
 | 
				
			||||||
import { Store } from "../../Logic/UIEventSource"
 | 
					 | 
				
			||||||
import { Translation } from "../i18n/Translation"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let mapProperties: { rotation: UIEventSource<number>, allowRotating: Store<boolean> }
 | 
					export let mapProperties: { rotation: UIEventSource<number>, allowRotating: Store<boolean> }
 | 
				
			||||||
let orientation = Orientation.singleton.alpha
 | 
					let orientation = Orientation.singleton.alpha
 | 
				
			||||||
| 
						 | 
					@ -24,11 +22,6 @@ function clicked(e: Event) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    mapProperties.rotation.set(0)
 | 
					    mapProperties.rotation.set(0)
 | 
				
			||||||
    explanation.set(new Translation({ "*": "North is now up" }))
 | 
					 | 
				
			||||||
    showPopover = true
 | 
					 | 
				
			||||||
    Utils.waitFor(5000).then(() => {
 | 
					 | 
				
			||||||
      showPopover = false
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import { Validator } from "../Validator"
 | 
				
			||||||
import { Translation } from "../../i18n/Translation"
 | 
					import { Translation } from "../../i18n/Translation"
 | 
				
			||||||
import licenses from "../../../assets/generated/license_info.json"
 | 
					import licenses from "../../../assets/generated/license_info.json"
 | 
				
			||||||
import { Utils } from "../../../Utils"
 | 
					import { Utils } from "../../../Utils"
 | 
				
			||||||
 | 
					import { Strings } from "../../../Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class IconValidator extends Validator {
 | 
					export default class IconValidator extends Validator {
 | 
				
			||||||
    private static allLicenses = new Set(licenses.map((l) => l.path))
 | 
					    private static allLicenses = new Set(licenses.map((l) => l.path))
 | 
				
			||||||
| 
						 | 
					@ -16,7 +17,7 @@ export default class IconValidator extends Validator {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getFeedback(s: string, getCountry, sloppy?: boolean): Translation | undefined {
 | 
					    getFeedback(s: string, getCountry, sloppy?: boolean): Translation | undefined {
 | 
				
			||||||
        if (Utils.isEmoji(s)) {
 | 
					        if (Strings.isEmoji(s)) {
 | 
				
			||||||
            return undefined
 | 
					            return undefined
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        s = this.reformat(s)
 | 
					        s = this.reformat(s)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,7 @@
 | 
				
			||||||
  import LockClosed from "@babeard/svelte-heroicons/solid/LockClosed"
 | 
					  import LockClosed from "@babeard/svelte-heroicons/solid/LockClosed"
 | 
				
			||||||
  import Key from "@babeard/svelte-heroicons/solid/Key"
 | 
					  import Key from "@babeard/svelte-heroicons/solid/Key"
 | 
				
			||||||
  import Snap from "../../assets/svg/Snap.svelte"
 | 
					  import Snap from "../../assets/svg/Snap.svelte"
 | 
				
			||||||
 | 
					  import { Strings } from "../../Utils/Strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Renders a single icon.
 | 
					   * Renders a single icon.
 | 
				
			||||||
| 
						 | 
					@ -163,7 +164,7 @@
 | 
				
			||||||
    <UserCircleIcon class={clss} {color} />
 | 
					    <UserCircleIcon class={clss} {color} />
 | 
				
			||||||
  {:else if icon === "wifi"}
 | 
					  {:else if icon === "wifi"}
 | 
				
			||||||
    <WifiIcon class={"m-0 " + clss} {color} />
 | 
					    <WifiIcon class={"m-0 " + clss} {color} />
 | 
				
			||||||
  {:else if Utils.isEmoji(icon)}<span
 | 
					  {:else if Strings.isEmoji(icon)}<span
 | 
				
			||||||
      style={`font-size: ${emojiHeight}; line-height: ${emojiHeight}`}
 | 
					      style={`font-size: ${emojiHeight}; line-height: ${emojiHeight}`}
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      {icon}
 | 
					      {icon}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ export class DeleteFlowState {
 | 
				
			||||||
                return false
 | 
					                return false
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
                ud.csCount >=
 | 
					                ud?.csCount >=
 | 
				
			||||||
                Math.min(
 | 
					                Math.min(
 | 
				
			||||||
                    Constants.userJourney.deletePointsOfOthersUnlock,
 | 
					                    Constants.userJourney.deletePointsOfOthersUnlock,
 | 
				
			||||||
                    this._allowDeletionAtChangesetCount
 | 
					                    this._allowDeletionAtChangesetCount
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								src/Utils.ts
									
										
									
									
									
								
							| 
						 | 
					@ -1784,17 +1784,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
				
			||||||
        return href
 | 
					        return href
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Returns 'true' if the given string contains at least one and only emoji characters
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Utils.isEmoji("⛰\uFE0F") // => true
 | 
					 | 
				
			||||||
     * Utils.isEmoji("🇧🇪") // => true
 | 
					 | 
				
			||||||
     * Utils.isEmoji("🍕") // => true
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static isEmoji(string: string) {
 | 
					 | 
				
			||||||
        return  Strings.isEmoji(string)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static sum(list: number[]): number {
 | 
					    public static sum(list: number[]): number {
 | 
				
			||||||
        let total = 0
 | 
					        let total = 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue