diff --git a/config/enjin-platform-ui.php b/config/enjin-platform-ui.php index 4fc3368..14970d6 100644 --- a/config/enjin-platform-ui.php +++ b/config/enjin-platform-ui.php @@ -16,6 +16,7 @@ 'settings', 'login', 'register', + 'marketplace', 'forgot-password', 'reset-password', ], diff --git a/package-lock.json b/package-lock.json index bd8530e..0bb66ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "easymde": "^2.18.0", "eslint-plugin-import": "^2.27.5", "eventemitter3": "^5.0.0", + "lodash": "^4.17.21", "marked": "^12.0.1", "pinia": "^2.1.4", "pinia-plugin-persistedstate": "^3.1.0", diff --git a/package.json b/package.json index 1518f0c..70a3fb4 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "easymde": "^2.18.0", "eslint-plugin-import": "^2.27.5", "eventemitter3": "^5.0.0", + "lodash": "^4.17.21", "marked": "^12.0.1", "pinia": "^2.1.4", "pinia-plugin-persistedstate": "^3.1.0", diff --git a/resources/js/components/FormSelect.vue b/resources/js/components/FormSelect.vue index 8b24ef3..b06f81a 100644 --- a/resources/js/components/FormSelect.vue +++ b/resources/js/components/FormSelect.vue @@ -19,6 +19,7 @@ > @@ -99,10 +100,10 @@ import { useAppStore } from '~/store'; const props = withDefaults( defineProps<{ + modelValue: string | number | undefined; label?: string; description?: string; options: string[]; - modelValue: string | number; name: string; required?: boolean; tooltip?: string; diff --git a/resources/js/components/batch/forms/BatchMintForm.vue b/resources/js/components/batch/forms/BatchMintForm.vue index 4922cce..948f2fd 100644 --- a/resources/js/components/batch/forms/BatchMintForm.vue +++ b/resources/js/components/batch/forms/BatchMintForm.vue @@ -260,7 +260,7 @@ const mintTypes = [ }, ]; const formRef: Ref = ref(); -const account = ref(publicKeyToAddress(props.modelValue.account ?? '') ?? ''); +const account = ref(publicKeyToAddress(props.modelValue.account!)!); const createTokenId: Ref = ref( parseFormatedTokenId(props.modelValue.createParams?.tokenId ?? null) ?? { tokenId: '', @@ -277,7 +277,7 @@ const initialSupply = ref(props.modelValue.createParams?.initialSupply ?? 1); const capAmount = ref(props.modelValue.createParams?.cap?.amount ?? undefined); const mintAmount = ref(props.modelValue.mintParams?.amount ?? 1); const isCurrency = ref(props.modelValue.createParams?.behavior?.isCurrency ?? false); -const beneficiaryAddress = ref(props.modelValue.createParams?.behavior?.hasRoyalty?.beneficiary ?? ''); +const beneficiaryAddress = ref(props.modelValue.createParams?.behavior?.hasRoyalty?.beneficiary!); const beneficiaryPercentage = ref(props.modelValue.createParams?.behavior?.hasRoyalty?.percentage ?? 0); const listingForbidden = ref(props.modelValue.createParams?.listingForbidden ?? false); diff --git a/resources/js/components/batch/forms/BatchTransferForm.vue b/resources/js/components/batch/forms/BatchTransferForm.vue index 3d7c98e..e5e27b9 100644 --- a/resources/js/components/batch/forms/BatchTransferForm.vue +++ b/resources/js/components/batch/forms/BatchTransferForm.vue @@ -149,7 +149,7 @@ const transferTypes = [ }, ]; const formRef = ref(); -const account = ref(publicKeyToAddress(props.modelValue.account ?? '') ?? ''); +const account = ref(publicKeyToAddress(props.modelValue.account!)!); const simpleTokenId = ref( parseFormatedTokenId(props.modelValue.simpleParams?.tokenId ?? null) ?? { tokenId: '', @@ -166,7 +166,7 @@ const simpleAmount = ref(props.modelValue.simpleParams?.amount ?? 1); const operatorAmount = ref(props.modelValue.operatorParams?.amount ?? 1); const simpleKeepAlive = ref(props.modelValue.simpleParams?.keepAlive ?? false); const operatorKeepAlive = ref(props.modelValue.operatorParams?.keepAlive ?? false); -const operatorSource = ref(props.modelValue.operatorParams?.source ?? ''); +const operatorSource = ref(props.modelValue.operatorParams?.source!); const validForm = computed(() => formRef.value.getMeta().valid); diff --git a/resources/js/components/fueltank/DispatchRuleForm.vue b/resources/js/components/fueltank/DispatchRuleForm.vue index de558b1..2a79fc4 100644 --- a/resources/js/components/fueltank/DispatchRuleForm.vue +++ b/resources/js/components/fueltank/DispatchRuleForm.vue @@ -22,6 +22,10 @@ class="ml-1 w-4 h-4 cursor-pointer text-light-content dark:text-dark-content" /> +  * + +
+

At least one rule is required

@@ -288,13 +291,13 @@ import { ref, computed, watch, Ref } from 'vue'; import { Form } from 'vee-validate'; import * as yup from 'yup'; import FormInput from '~/components/FormInput.vue'; -import { currencySymbolByNetwork, formatData, formatPriceToENJ, formatToken, parseFormatedTokenId } from '~/util'; +import { currencySymbolByNetwork, formatData, formatPriceToENJ, parseFormatedTokenId } from '~/util'; import { TokenIdSelectType, TransactionMethods, DispatchRules } from '~/types/types.enums'; import TokenIdInput from '~/components/TokenIdInput.vue'; import FormList from '../FormList.vue'; import { formatWhitelistedCallers, formatWhitelistedCollections } from '~/util'; import { DispatchRulesValuesInterface } from '~/types/types.interface'; -import { numberNotRequiredSchema, stringNotRequiredSchema } from '~/util/schemas'; +import { addressNotRequiredSchema, numberNotRequiredSchema, stringNotRequiredSchema } from '~/util/schemas'; import { useAppStore } from '~/store'; import FormSelect from '../FormSelect.vue'; import { PlusIcon } from '@heroicons/vue/20/solid'; @@ -310,6 +313,8 @@ const props = withDefaults( modelValue: DispatchRulesValuesInterface; isModal?: boolean; ruleId?: number; + required?: boolean; + error?: boolean; }>(), { isModal: false, @@ -318,7 +323,7 @@ const props = withDefaults( const formRef = ref(); const whitelistedCallers = ref(formatWhitelistedCallers(props.modelValue.whitelistedCallers) ?? [{ caller: '' }]); -const collectionId = ref(props.modelValue.requireToken?.collectionId ?? ''); +const collectionId = ref(props.modelValue.requireToken?.collectionId!); const tokenId = ref( parseFormatedTokenId(props.modelValue.requireToken?.tokenId ?? null) ?? { tokenId: '', @@ -349,12 +354,16 @@ const currencySymbol = computed(() => currencySymbolByNetwork(useAppStore().conf const validation = yup.object({ whitelistedCallers: yup.array().of( yup.object({ - caller: yup.string(), + caller: addressNotRequiredSchema, }) ), collectionId: stringNotRequiredSchema, tokenId: stringNotRequiredSchema, - whitelistedCollections: stringNotRequiredSchema, + whitelistedCollections: yup.array().of( + yup.object({ + collection: numberNotRequiredSchema, + }) + ), maxFuelBurnPerTransaction: numberNotRequiredSchema.typeError('Max Fuel Burn Per Transaction must be a number'), userFuelAmount: numberNotRequiredSchema.typeError('User Fuel Amount must be a number'), userFuelresetPeriod: numberNotRequiredSchema.typeError('User Fuel Reset Period must be a number'), @@ -405,27 +414,59 @@ const checkSelectedDispatchRule = (rule: DispatchRules) => { const removeSelectedDispatch = (rule: DispatchRules) => { const index = selectedDispatchRules.value.indexOf(rule); if (index > -1) { + clearSelectedDispatchRule(rule); selectedDispatchRules.value.splice(index, 1); } }; +const clearSelectedDispatchRule = (rule: DispatchRules) => { + switch (rule) { + case DispatchRules.WhitelistedCallers: + whitelistedCallers.value = [{ caller: '' }]; + break; + case DispatchRules.RequireToken: + collectionId.value = ''; + tokenId.value = { tokenId: '', tokenType: TokenIdSelectType.Integer }; + break; + case DispatchRules.WhitelistedCollections: + whitelistedCollections.value = [{ collection: '' }]; + break; + case DispatchRules.MaxFuelBurnPerTransaction: + maxFuelBurnPerTransaction.value = null; + break; + case DispatchRules.PermittedExtrinsic: + permittedExtrinsics.value = []; + break; + case DispatchRules.UserFuelBudget: + userFuelAmount.value = null; + userFuelresetPeriod.value = null; + break; + case DispatchRules.TankFuelBudget: + tankFuelAmount.value = null; + tankFuelresetPeriod.value = null; + break; + } +}; + const hasChanged = computed(() => formatData({ - whitelistedCallers: whitelistedCallers.value.map((item: any) => item.caller), - requireToken: { + whitelistedCallers: whitelistedCallers.value.map((item: any) => item.caller).filter((item: string) => item), + requireToken: formatData({ collectionId: collectionId.value, - tokenId: formatToken(tokenId.value), - }, - whitelistedCollections: whitelistedCollections.value.map((item: any) => item.collection), + tokenId: tokenId.value.tokenId, + }), + whitelistedCollections: whitelistedCollections.value + .map((item: any) => item.collection) + .filter((item: number) => item), maxFuelBurnPerTransaction: maxFuelBurnPerTransaction.value, - userFuelBudget: { + userFuelBudget: formatData({ amount: formatPriceToENJ(userFuelAmount.value), resetPeriod: userFuelresetPeriod.value, - }, - tankFuelBudget: { + }), + tankFuelBudget: formatData({ amount: formatPriceToENJ(tankFuelAmount.value), resetPeriod: tankFuelresetPeriod.value, - }, + }), permittedExtrinsics: permittedExtrinsics.value, }) ); diff --git a/resources/js/components/slideovers/beam/ClaimBeamSlideover.vue b/resources/js/components/slideovers/beam/ClaimBeamSlideover.vue index 40985a3..2596619 100644 --- a/resources/js/components/slideovers/beam/ClaimBeamSlideover.vue +++ b/resources/js/components/slideovers/beam/ClaimBeamSlideover.vue @@ -56,7 +56,7 @@ const props = withDefaults( const qrCodeRef = ref(); const copyLink = () => { - navigator.clipboard.writeText(props.item?.qr.payload ?? ''); + navigator.clipboard.writeText(props.item?.qr.payload!); snackbar.info({ title: 'Link copied to clipboard!' }); }; diff --git a/resources/js/components/slideovers/beam/UpdateBeamSlideover.vue b/resources/js/components/slideovers/beam/UpdateBeamSlideover.vue index e9f6ed2..791e97b 100644 --- a/resources/js/components/slideovers/beam/UpdateBeamSlideover.vue +++ b/resources/js/components/slideovers/beam/UpdateBeamSlideover.vue @@ -138,11 +138,11 @@ const checkChanges = () => { description: description.value !== props.item?.description ? description.value : null, image: image.value !== props.item?.image ? image.value : null, start: - new Date(start.value).toString() !== new Date(props.item?.start ?? '').toString() + new Date(start.value).toString() !== new Date(props.item?.start!).toString() ? new Date(start.value).toString() : null, end: - new Date(end.value).toString() !== new Date(props.item?.end ?? '').toString() + new Date(end.value).toString() !== new Date(props.item?.end!).toString() ? new Date(end.value).toString() : null, flags: diff --git a/resources/js/components/slideovers/common/DetailsTransactionSlideover.vue b/resources/js/components/slideovers/common/DetailsTransactionSlideover.vue index 9232624..65b4f62 100644 --- a/resources/js/components/slideovers/common/DetailsTransactionSlideover.vue +++ b/resources/js/components/slideovers/common/DetailsTransactionSlideover.vue @@ -277,7 +277,7 @@ const getTransaction = async () => { } isLoading.value = true; - const res = await TransactionApi.getTransaction(props.item?.id ?? ''); + const res = await TransactionApi.getTransaction(props.item?.id!); transaction.value = DTOTransactionFactory.forTransaction(res); if (transaction.value.state === TransactionState.FINALIZED) { emit('update', transaction.value); diff --git a/resources/js/components/slideovers/common/FreezeSlideover.vue b/resources/js/components/slideovers/common/FreezeSlideover.vue index ab94cbd..345ea99 100644 --- a/resources/js/components/slideovers/common/FreezeSlideover.vue +++ b/resources/js/components/slideovers/common/FreezeSlideover.vue @@ -130,7 +130,7 @@ const collectionId = ref(props.item?.collectionId); const freezeType = ref(props.item?.freezeType ?? FreezeType.COLLECTION); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionAccount = ref(''); const freezeState = ref(FreezeStateType.TEMPORARY); diff --git a/resources/js/components/slideovers/common/ThawSlideover.vue b/resources/js/components/slideovers/common/ThawSlideover.vue index 656b6d7..b28438a 100644 --- a/resources/js/components/slideovers/common/ThawSlideover.vue +++ b/resources/js/components/slideovers/common/ThawSlideover.vue @@ -120,7 +120,7 @@ const collectionId = ref(props.item?.collectionId); const freezeType = ref(props.item?.freezeType ?? FreezeType.COLLECTION); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionAccount = ref(''); const tokenAccount = ref(''); diff --git a/resources/js/components/slideovers/fueltank/AccountsFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/AccountsFuelTankSlideover.vue index 059cc59..f3bc063 100644 --- a/resources/js/components/slideovers/fueltank/AccountsFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/AccountsFuelTankSlideover.vue @@ -212,7 +212,7 @@ const accounts: Ref<{ items: [], cursor: null, }); -const tankId = ref(props.item?.tankId ?? ''); +const tankId = ref(props.item?.tankId!); const idempotencyKey = ref(''); const formRef = ref(); const paginatorRef = ref(); @@ -321,7 +321,7 @@ const closeSlide = () => { const getAccounts = async () => { try { - const res = await FuelTankApi.getAccounts(addressToPublicKey(tankId.value) ?? ''); + const res = await FuelTankApi.getAccounts(addressToPublicKey(tankId.value)!); accounts.value = DTOFactory.forAccounts(res); } catch (e) { // Do nothing diff --git a/resources/js/components/slideovers/fueltank/ConsumptionFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/ConsumptionFuelTankSlideover.vue index 70a0847..f1d21bd 100644 --- a/resources/js/components/slideovers/fueltank/ConsumptionFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/ConsumptionFuelTankSlideover.vue @@ -126,7 +126,7 @@ const setConsumption = async () => { isLoading.value = true; const res = await FuelTankApi.setConsumption( formatData({ - tankId: addressToPublicKey(tankId.value ?? ''), + tankId: addressToPublicKey(tankId.value!), ruleSetId: ruleSetId.value, userId: userId.value, totalConsumed: totalConsumed.value, diff --git a/resources/js/components/slideovers/fueltank/DispatchFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/DispatchFuelTankSlideover.vue index e2058b5..2d07367 100644 --- a/resources/js/components/slideovers/fueltank/DispatchFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/DispatchFuelTankSlideover.vue @@ -25,6 +25,7 @@ name="ruleSetId" label="Rule Set ID" description="The rule set index." + type="number" required /> { isLoading.value = true; const res = await FuelTankApi.dispatch( formatData({ - tankId: addressToPublicKey(tankId.value ?? ''), + tankId: addressToPublicKey(tankId.value!), ruleSetId: ruleSetId.value, dispatch: { call: call.value, diff --git a/resources/js/components/slideovers/fueltank/FreezeFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/FreezeFuelTankSlideover.vue index 6f6ddc9..52ad10e 100644 --- a/resources/js/components/slideovers/fueltank/FreezeFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/FreezeFuelTankSlideover.vue @@ -110,7 +110,7 @@ const freezeFuelTank = async () => { isLoading.value = true; const res = await FuelTankApi.scheduleMutateFreezeState( formatData({ - tankId: addressToPublicKey(tankId.value ?? ''), + tankId: addressToPublicKey(tankId.value!), isFrozen: isFrozen.value, ruleSetId: ruleSetId.value, idempotencyKey: idempotencyKey.value, diff --git a/resources/js/components/slideovers/fueltank/MutateFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/MutateFuelTankSlideover.vue index f323537..68c9133 100644 --- a/resources/js/components/slideovers/fueltank/MutateFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/MutateFuelTankSlideover.vue @@ -202,7 +202,7 @@ const mutateFuelTank = async () => { isLoading.value = true; const res = await FuelTankApi.mutateFuelTank( formatData({ - tankId: addressToPublicKey(tankId.value ?? ''), + tankId: addressToPublicKey(tankId.value!), mutation: { providesDeposit: providesDeposit.value, reservesExistentialDeposit: reservesExistentialDeposit.value, diff --git a/resources/js/components/slideovers/fueltank/RuleSetsFuelTankSlideover.vue b/resources/js/components/slideovers/fueltank/RuleSetsFuelTankSlideover.vue index ae6d612..259d0ec 100644 --- a/resources/js/components/slideovers/fueltank/RuleSetsFuelTankSlideover.vue +++ b/resources/js/components/slideovers/fueltank/RuleSetsFuelTankSlideover.vue @@ -41,6 +41,7 @@ name="ruleSetId" label="Rule Set ID" description="The rule set index." + type="number" required /> = ref({}); const userId = ref(''); const rule = ref(''); +const dispatchRuleError = ref(false); const ruleOptions = Object.values(RuleType); @@ -168,6 +177,10 @@ const formAction = () => { }; const insertRule = async () => { + if (isEmpty(dispatchRule.value)) { + dispatchRuleError.value = true; + return; + } await formRef.value?.validate(); if (!formRef.value?.getMeta().valid) return; @@ -178,7 +191,7 @@ const insertRule = async () => { isLoading.value = true; const res = await FuelTankApi.insertRuleSet( formatData({ - tankId: addressToPublicKey(tankId.value ?? ''), + tankId: addressToPublicKey(tankId.value!), ruleSetId: ruleSetId.value, dispatchRules: dispatchRule.value, idempotencyKey: idempotencyKey.value, diff --git a/resources/js/components/slideovers/token/ApproveTokenSlideover.vue b/resources/js/components/slideovers/token/ApproveTokenSlideover.vue index 40076e1..029ec1c 100644 --- a/resources/js/components/slideovers/token/ApproveTokenSlideover.vue +++ b/resources/js/components/slideovers/token/ApproveTokenSlideover.vue @@ -123,7 +123,7 @@ const props = withDefaults( const isLoading = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionId = ref(props.item?.collectionId); const operator = ref(''); diff --git a/resources/js/components/slideovers/token/AttributesTokenSlideover.vue b/resources/js/components/slideovers/token/AttributesTokenSlideover.vue index 0433390..0925253 100644 --- a/resources/js/components/slideovers/token/AttributesTokenSlideover.vue +++ b/resources/js/components/slideovers/token/AttributesTokenSlideover.vue @@ -141,7 +141,7 @@ const idempotencyKey = ref(''); const skipValidation = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const formRef = ref(); diff --git a/resources/js/components/slideovers/token/BurnTokenSlideover.vue b/resources/js/components/slideovers/token/BurnTokenSlideover.vue index 1bd3911..cc86d8d 100644 --- a/resources/js/components/slideovers/token/BurnTokenSlideover.vue +++ b/resources/js/components/slideovers/token/BurnTokenSlideover.vue @@ -113,7 +113,7 @@ const props = withDefaults( const isLoading = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionId = ref(props.item?.collectionId); const amount = ref(); diff --git a/resources/js/components/slideovers/token/MintTokenSlideover.vue b/resources/js/components/slideovers/token/MintTokenSlideover.vue index fd29625..8e312cc 100644 --- a/resources/js/components/slideovers/token/MintTokenSlideover.vue +++ b/resources/js/components/slideovers/token/MintTokenSlideover.vue @@ -114,13 +114,13 @@ const props = withDefaults( const isLoading = ref(false); const collectionId = ref(props.item?.collectionId); -const recipient = ref(publicKeyToAddress(props.item?.owner ?? '')); +const recipient = ref(publicKeyToAddress(props.item?.owner!)); const amount = ref(); const idempotencyKey = ref(''); const skipValidation = ref(false); const tokenId: Ref = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const formRef = ref(); diff --git a/resources/js/components/slideovers/token/MutateTokenSlideover.vue b/resources/js/components/slideovers/token/MutateTokenSlideover.vue index de8fab6..d4af574 100644 --- a/resources/js/components/slideovers/token/MutateTokenSlideover.vue +++ b/resources/js/components/slideovers/token/MutateTokenSlideover.vue @@ -132,7 +132,7 @@ const props = withDefaults( const isLoading = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionId = ref(props.item?.collectionId); const beneficiaryAddress = ref(Royalty.getRoyaltyBeneficiary(props.item)); diff --git a/resources/js/components/slideovers/token/TransferTokenSlideover.vue b/resources/js/components/slideovers/token/TransferTokenSlideover.vue index 45d0244..5d15a2c 100644 --- a/resources/js/components/slideovers/token/TransferTokenSlideover.vue +++ b/resources/js/components/slideovers/token/TransferTokenSlideover.vue @@ -139,7 +139,7 @@ const props = withDefaults( const isLoading = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionId = ref(props.item?.collectionId); const recipient = ref(''); diff --git a/resources/js/components/slideovers/token/UnapproveTokenSlideover.vue b/resources/js/components/slideovers/token/UnapproveTokenSlideover.vue index a18a4e0..04558e5 100644 --- a/resources/js/components/slideovers/token/UnapproveTokenSlideover.vue +++ b/resources/js/components/slideovers/token/UnapproveTokenSlideover.vue @@ -101,7 +101,7 @@ const props = withDefaults( const isLoading = ref(false); const tokenId = ref({ tokenType: TokenIdSelectType.Integer, - tokenId: props.item?.tokenId ?? '', + tokenId: props.item?.tokenId!, }); const collectionId = ref(props.item?.collectionId); const operator = ref(''); diff --git a/resources/js/store/index.ts b/resources/js/store/index.ts index 17433e3..8617181 100644 --- a/resources/js/store/index.ts +++ b/resources/js/store/index.ts @@ -253,7 +253,7 @@ export const useAppStore = defineStore('app', { if (this.navigations.find((nav) => nav.name === 'Marketplace')) return; this.navigations = [ ...this.navigations, - { name: 'Marketplace', to: { name: 'platform.marketplace' }, pos: 5 }, + { name: 'Marketplace', to: { name: 'platform.marketplace.bids' }, pos: 5 }, ].sort((a, b) => a.pos - b.pos); }, setAdvancedMode(advanced: boolean) {