this is so cracked lol
This commit is contained in:
parent
b3dad219c6
commit
080215183f
|
@ -6,7 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite App</title>
|
<title>Vite App</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="overflow-y: hidden;">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
"@vueuse/core": "^8.7.5",
|
"@vueuse/core": "^8.7.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"handsontable": "^12.0.1",
|
"handsontable": "^12.0.1",
|
||||||
|
"loglevel": "^1.8.0",
|
||||||
|
"pinia": "^2.0.14",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"typescript-cookie": "^1.0.3",
|
"typescript-cookie": "^1.0.3",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
|
@ -173,6 +175,11 @@
|
||||||
"@vue/shared": "3.2.37"
|
"@vue/shared": "3.2.37"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vue/devtools-api": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA=="
|
||||||
|
},
|
||||||
"node_modules/@vue/reactivity": {
|
"node_modules/@vue/reactivity": {
|
||||||
"version": "3.2.37",
|
"version": "3.2.37",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
|
||||||
|
@ -882,6 +889,18 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/loglevel": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "tidelift",
|
||||||
|
"url": "https://tidelift.com/funding/github/npm/loglevel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
||||||
|
@ -963,6 +982,56 @@
|
||||||
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
|
||||||
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
|
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/pinia": {
|
||||||
|
"version": "2.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz",
|
||||||
|
"integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^6.1.4",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/posva"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.4.0",
|
||||||
|
"typescript": ">=4.4.4",
|
||||||
|
"vue": "^2.6.14 || ^3.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pinia/node_modules/vue-demi": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.14",
|
"version": "8.4.14",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
|
||||||
|
@ -1100,7 +1169,7 @@
|
||||||
"version": "4.7.4",
|
"version": "4.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
@ -1331,6 +1400,11 @@
|
||||||
"@vue/shared": "3.2.37"
|
"@vue/shared": "3.2.37"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@vue/devtools-api": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA=="
|
||||||
|
},
|
||||||
"@vue/reactivity": {
|
"@vue/reactivity": {
|
||||||
"version": "3.2.37",
|
"version": "3.2.37",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
|
||||||
|
@ -1740,6 +1814,11 @@
|
||||||
"has": "^1.0.3"
|
"has": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"loglevel": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA=="
|
||||||
|
},
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
||||||
|
@ -1800,6 +1879,23 @@
|
||||||
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
|
||||||
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
|
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
|
||||||
},
|
},
|
||||||
|
"pinia": {
|
||||||
|
"version": "2.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz",
|
||||||
|
"integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/devtools-api": "^6.1.4",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue-demi": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.14",
|
"version": "8.4.14",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
|
||||||
|
@ -1891,7 +1987,7 @@
|
||||||
"version": "4.7.4",
|
"version": "4.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"typescript-cookie": {
|
"typescript-cookie": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
"@vueuse/core": "^8.7.5",
|
"@vueuse/core": "^8.7.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"handsontable": "^12.0.1",
|
"handsontable": "^12.0.1",
|
||||||
|
"loglevel": "^1.8.0",
|
||||||
|
"pinia": "^2.0.14",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"typescript-cookie": "^1.0.3",
|
"typescript-cookie": "^1.0.3",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
|
|
58
src/App.vue
58
src/App.vue
|
@ -1,13 +1,25 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import CharacterInventory from "./components/CharacterInventory.vue"
|
import CharacterInventory from "./components/CharacterInventory.vue"
|
||||||
import Login from "./pages/login.vue"
|
import Login from "./pages/login.vue"
|
||||||
import SessionDisplay from "./components/SessionDisplay.vue";
|
import CharacterRoulette from "./components/CharacterRoulette.vue";
|
||||||
|
import Sidebar from "./components/Sidebar.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<SessionDisplay/>
|
<div class="parent">
|
||||||
<Login/>
|
<div class="splash"> </div>
|
||||||
<CharacterInventory/>
|
<div class="main">
|
||||||
|
<CharacterInventory />
|
||||||
|
</div>
|
||||||
|
<div class="sidebar">
|
||||||
|
<Sidebar/>
|
||||||
|
</div>
|
||||||
|
<div class="select">
|
||||||
|
<CharacterRoulette />
|
||||||
|
</div>
|
||||||
|
<div class="login">
|
||||||
|
<Login />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -18,6 +30,8 @@ import SessionDisplay from "./components/SessionDisplay.vue";
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handsontable td {
|
.handsontable td {
|
||||||
|
@ -27,7 +41,41 @@ import SessionDisplay from "./components/SessionDisplay.vue";
|
||||||
border-bottom: 1px white !important;
|
border-bottom: 1px white !important;
|
||||||
background-color: #F7F7F7 !important;
|
background-color: #F7F7F7 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handsontable tr {
|
.handsontable tr {
|
||||||
border-radius: 10px !important;
|
border-radius: 10px !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.parent {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 4fr 3fr;
|
||||||
|
grid-template-rows: 1fr repeat(2, 3fr) 1fr;
|
||||||
|
grid-column-gap: 0px;
|
||||||
|
grid-row-gap: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.splash {
|
||||||
|
grid-area: 1 / 1 / 2 / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
grid-area: 2 / 2 / 5 / 4;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
grid-area: 2 / 1 / 5 / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection {
|
||||||
|
grid-area: 1 / 2 / 2 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
grid-area: 1 / 3 / 2 / 4;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<input type="checkbox" id={{props.colname}} v-model="checked" />
|
||||||
|
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
const props = defineProps(["colname","label"])
|
||||||
|
const {columns} = useStoreRef()
|
||||||
|
const checked = ref(columns.value.has(props.colname))
|
||||||
|
watch(columns.value.dirty,()=>{
|
||||||
|
console.log("changed")
|
||||||
|
if(columns.value.has(props.colname)) {
|
||||||
|
checked.value = true
|
||||||
|
}else{
|
||||||
|
checked.value = false
|
||||||
|
}
|
||||||
|
},{deep:true})
|
||||||
|
|
||||||
|
watch(checked, ()=>{
|
||||||
|
if(checked.value === true) {
|
||||||
|
columns.value.add(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(checked.value === false) {
|
||||||
|
columns.value.delete(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineProps, ref, watch } from 'vue';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { ColumnName, Columns } from '../lib/columns';
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-on:click="selectCharacter()"
|
||||||
|
>{{name}} the <span v-html="job" /> ({{galders.toLocaleString()}}g)</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const session = storage.GetSession()
|
||||||
|
const api:LTOApi = new LTOApiv0(session)
|
||||||
|
|
||||||
|
const props = defineProps(['character'])
|
||||||
|
|
||||||
|
const name = ref("")
|
||||||
|
const job = ref("")
|
||||||
|
const galders = ref(0)
|
||||||
|
const {invs, activeTable} = useStoreRef()
|
||||||
|
|
||||||
|
name.value = invs.value.get(props.character)?.name!
|
||||||
|
job.value = invs.value.get(props.character)?.wallet?.job_img!
|
||||||
|
galders.value = invs.value.get(props.character)?.wallet?.galders!
|
||||||
|
|
||||||
|
const selectCharacter = () => {
|
||||||
|
activeTable.value = props.character
|
||||||
|
log.info("selected char", activeTable.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import log from 'loglevel';
|
||||||
|
import { defineComponent, computed, PropType, defineProps, defineEmits, ref} from 'vue';
|
||||||
|
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
|
||||||
|
import { LoginHelper, Session } from '../lib/session';
|
||||||
|
import { storage } from '../session_storage';
|
||||||
|
import { useStore, useStoreRef } from '../state/state';
|
||||||
|
</script>
|
|
@ -1,62 +1,51 @@
|
||||||
<template>
|
<template>
|
||||||
<input v-on:input="swapHotData" placeholder="separate by comma" value="Image, Name, Count, MoveCount, Move, MoveConfirm">
|
<HotTable
|
||||||
<hot-table
|
|
||||||
ref="hotTableComponent"
|
ref="hotTableComponent"
|
||||||
:settings="hotSettings"
|
:settings="DefaultSettings()"
|
||||||
></hot-table>
|
></HotTable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
|
import { ref } from 'vue';
|
||||||
import { HotTable, HotColumn} from '@handsontable/vue3';
|
import { HotTable, HotColumn } from '@handsontable/vue3';
|
||||||
import { registerAllModules } from 'handsontable/registry';
|
|
||||||
import { InventoryTable, TableRecipe } from '../lib/table';
|
|
||||||
import { Columns, ColumnByNames } from '../lib/columns';
|
|
||||||
import { TricksterItem, SampleData } from '../lib/trickster';
|
|
||||||
import Handsontable from 'handsontable';
|
|
||||||
|
|
||||||
|
const session = storage.GetSession()
|
||||||
|
const api:LTOApi = new LTOApiv0(session)
|
||||||
|
const {invs, activeTable, columns, tags} = useStoreRef()
|
||||||
|
const hotTableComponent = ref<any>(null)
|
||||||
|
|
||||||
|
const updateTable = () => {
|
||||||
|
if (invs.value.has(activeTable.value)) {
|
||||||
|
const chardat = invs.value.get(activeTable.value)
|
||||||
|
if (chardat) {
|
||||||
|
const it = new InventoryTable(chardat!, { columns: columns.value, tags: tags.value })
|
||||||
|
const hot = (hotTableComponent.value.hotInstance as Handsontable)
|
||||||
|
const build = it.BuildTable()
|
||||||
|
hot.updateSettings(build.settings)
|
||||||
|
hot.updateData(build.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// register Handsontable's modules
|
// register Handsontable's modules
|
||||||
registerAllModules();
|
registerAllModules();
|
||||||
|
|
||||||
const _defaultColumn = [
|
watch([columns.value.dirty,tags.value.dirty, activeTable], () => {
|
||||||
Columns.Image,
|
updateTable()
|
||||||
Columns.Name,
|
})
|
||||||
Columns.Count,
|
|
||||||
Columns.MoveCount,
|
|
||||||
Columns.Move,
|
|
||||||
]
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
data() {
|
|
||||||
let cols = _defaultColumn
|
|
||||||
const it = new InventoryTable(SampleData.aysheBoyfriend,
|
|
||||||
...cols
|
|
||||||
);
|
|
||||||
const dat = it.BuildTable()
|
|
||||||
return {
|
|
||||||
hotSettings: {
|
|
||||||
data: dat.data,
|
|
||||||
...dat.settings,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
swapHotData: function(event:any) {
|
|
||||||
let trm = event.target.value.split(",").map((x:any)=>x.trim())
|
|
||||||
let cols = ColumnByNames(...(trm as any)).filter(x=>x!=undefined)
|
|
||||||
if(cols.length < 2) {
|
|
||||||
cols = _defaultColumn
|
|
||||||
}
|
|
||||||
const it = new InventoryTable(SampleData.aysheBoyfriend,
|
|
||||||
...cols)
|
|
||||||
const hot = ((this.$refs!.hotTableComponent as any).hotInstance as Handsontable)
|
|
||||||
hot.updateSettings(it.BuildTable().settings)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
HotTable,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style src="handsontable/dist/handsontable.full.css"></style>
|
<script lang="ts">
|
||||||
|
import { defineComponent, computed, PropType, defineProps, defineEmits, watch} from 'vue';
|
||||||
|
import { registerAllModules } from 'handsontable/registry';
|
||||||
|
import { DefaultSettings, InventoryTable, TableRecipe } from '../lib/table';
|
||||||
|
import { Columns, ColumnByNames, ColumnInfo } from '../lib/columns';
|
||||||
|
import { TricksterItem, SampleData } from '../lib/trickster';
|
||||||
|
import Handsontable from 'handsontable';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { storage } from '../session_storage';
|
||||||
|
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style src="handsontable/dist/handsontable.full.css">
|
||||||
|
</style>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<template>
|
||||||
|
<div v-for="v in characters">
|
||||||
|
<CharacterCard :character="v" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import CharacterCard from './CharacterCard.vue';
|
||||||
|
|
||||||
|
const { accounts, invs } = useStoreRef()
|
||||||
|
|
||||||
|
const characters = ref([] as string[])
|
||||||
|
|
||||||
|
watch(invs, () => {
|
||||||
|
characters.value = [...new Set([...characters.value, ...invs.value.keys()])]
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
|
const session = storage.GetSession()
|
||||||
|
const api: LTOApi = new LTOApiv0(session)
|
||||||
|
api.GetAccounts().then(xs => {
|
||||||
|
xs.forEach(x => {
|
||||||
|
accounts.value.add(x)
|
||||||
|
api.GetCharacters(x).then(chars => {
|
||||||
|
chars.forEach(char => {
|
||||||
|
log.debug("new character", char)
|
||||||
|
invs.value.set(char.path, char)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, computed, PropType, defineProps, defineEmits, ref, watch } from 'vue';
|
||||||
|
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
|
||||||
|
import { LoginHelper, Session } from '../lib/session';
|
||||||
|
import { storage } from '../session_storage';
|
||||||
|
import { useStore, useStoreRef } from '../state/state';
|
||||||
|
import log from 'loglevel';
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<input type="checkbox" id={{props.colname}} v-model="checked" />
|
||||||
|
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
const props = defineProps(["colname","label"])
|
||||||
|
const {columns} = useStoreRef()
|
||||||
|
const checked = ref(columns.value.has(props.colname))
|
||||||
|
watch(columns.value.dirty,()=>{
|
||||||
|
console.log("changed")
|
||||||
|
if(columns.value.has(props.colname)) {
|
||||||
|
checked.value = true
|
||||||
|
}else{
|
||||||
|
checked.value = false
|
||||||
|
}
|
||||||
|
},{deep:true})
|
||||||
|
|
||||||
|
watch(checked, ()=>{
|
||||||
|
if(checked.value === true) {
|
||||||
|
columns.value.add(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(checked.value === false) {
|
||||||
|
columns.value.delete(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineProps, ref, watch } from 'vue';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { ColumnName, Columns } from '../lib/columns';
|
||||||
|
</script>
|
|
@ -0,0 +1,124 @@
|
||||||
|
<template>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="css-checkbox"
|
||||||
|
:id="'toggle-'+props.header"
|
||||||
|
v-model="show"
|
||||||
|
/>
|
||||||
|
<label :for="'toggle-'+props.header" class="css-label">
|
||||||
|
<span class="fa fa-plus">+</span>
|
||||||
|
<span class="fa fa-minus">-</span>
|
||||||
|
</label>
|
||||||
|
<label :for="'checkbox-'+props.header">{{props.header}}</label>
|
||||||
|
<input type="checkbox" :id="'checkbox-'+props.header" v-model="checked" />
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div
|
||||||
|
class="checkbox_parent"
|
||||||
|
:style="'grid-template-rows: repeat('+Math.ceil(props.columns.length/2+2)+', 1fr);'"
|
||||||
|
v-if="show"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in props.columns"
|
||||||
|
class="checkbox_child"
|
||||||
|
>
|
||||||
|
<ColumnCheckbox :colname="item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import ColumnCheckbox from './ColumnCheckbox.vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
header: string
|
||||||
|
columns: ColumnName[]
|
||||||
|
default?: boolean
|
||||||
|
}>()
|
||||||
|
const {columns} = useStoreRef()
|
||||||
|
const checked = ref(props.default)
|
||||||
|
const show = ref(true)
|
||||||
|
watch(show,()=>{
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(checked,()=>{
|
||||||
|
if(checked.value === true) {
|
||||||
|
props.columns.forEach(x=>columns.value.add(x))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(checked.value === false) {
|
||||||
|
props.columns.forEach(x=>columns.value.delete(x))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineProps, ref, watch } from 'vue';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { ColumnName } from '../lib/columns';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.checkbox_parent {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
grid-column-gap: 0px;
|
||||||
|
grid-row-gap: 0px;
|
||||||
|
}
|
||||||
|
.checkbox_child {
|
||||||
|
align-content: left;
|
||||||
|
justify-self: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.css-checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.fa {
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.fa-plus {
|
||||||
|
background-color: #E85764;
|
||||||
|
}
|
||||||
|
.fa-minus {
|
||||||
|
background-color: #3AC5C9;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.css-checkbox:checked + .css-label .fa-minus {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.css-checkbox:checked + .css-label .fa-plus {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<input type="checkbox" id={{props.colname}} v-model="checked" />
|
||||||
|
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
const props = defineProps(["colname","label"])
|
||||||
|
const {tags} = useStoreRef()
|
||||||
|
const checked = ref(tags.value.has(props.colname))
|
||||||
|
watch(tags.value.dirty,()=>{
|
||||||
|
console.log("changed")
|
||||||
|
if(tags.value.has(props.colname)) {
|
||||||
|
checked.value = true
|
||||||
|
}else{
|
||||||
|
checked.value = false
|
||||||
|
}
|
||||||
|
},{deep:true})
|
||||||
|
|
||||||
|
watch(checked, ()=>{
|
||||||
|
if(checked.value === true) {
|
||||||
|
tags.value.add(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(checked.value === false) {
|
||||||
|
tags.value.delete(props.colname)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineProps, ref, watch } from 'vue';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { ColumnName, Columns } from '../lib/columns';
|
||||||
|
</script>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="css-checkbox"
|
||||||
|
:id="'toggle-'+props.header"
|
||||||
|
v-model="show"
|
||||||
|
/>
|
||||||
|
<label :for="'toggle-'+props.header" class="css-label">
|
||||||
|
<span class="fa fa-plus">+</span>
|
||||||
|
<span class="fa fa-minus">-</span>
|
||||||
|
</label>
|
||||||
|
<label :for="'checkbox-'+props.header">{{props.header}}</label>
|
||||||
|
<input type="checkbox" :id="'checkbox-'+props.header" v-model="checked" />
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div
|
||||||
|
class="checkbox_parent"
|
||||||
|
:style="'grid-template-rows: repeat('+Math.ceil(props.columns.length/2+2)+', 1fr);'"
|
||||||
|
v-if="show"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in props.columns"
|
||||||
|
class="checkbox_child"
|
||||||
|
>
|
||||||
|
<FilterCheckbox :colname="item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import FilterCheckbox from './FilterCheckbox.vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
header: string
|
||||||
|
columns: ColumnName[]
|
||||||
|
}>()
|
||||||
|
const {tags} = useStoreRef()
|
||||||
|
const checked = ref(false)
|
||||||
|
const show = ref(true)
|
||||||
|
watch(show,()=>{
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(checked,()=>{
|
||||||
|
if(checked.value === true) {
|
||||||
|
props.columns.forEach(x=>tags.value.add(x))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(checked.value === false) {
|
||||||
|
props.columns.forEach(x=>tags.value.delete(x))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineProps, ref, watch } from 'vue';
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
import { ColumnName } from '../lib/columns';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.checkbox_parent {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
grid-column-gap: 0px;
|
||||||
|
grid-row-gap: 0px;
|
||||||
|
}
|
||||||
|
.checkbox_child {
|
||||||
|
align-content: left;
|
||||||
|
justify-self: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.css-checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.fa {
|
||||||
|
color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.fa-plus {
|
||||||
|
background-color: #E85764;
|
||||||
|
}
|
||||||
|
.fa-minus {
|
||||||
|
background-color: #3AC5C9;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.css-checkbox:checked + .css-label .fa-minus {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.css-checkbox:checked + .css-label .fa-plus {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,24 +0,0 @@
|
||||||
<template>
|
|
||||||
<button @click="refreshSessions">
|
|
||||||
Refresh
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
|
|
||||||
import { Session } from '../lib/session';
|
|
||||||
import { storage } from '../session_storage';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
Sessions: {} as any,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
refreshSessions: function(event:any) {
|
|
||||||
this.Sessions = storage.GetSessions()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
Filters:
|
||||||
|
<br>
|
||||||
|
<FilterCheckboxGroup :header="'tags:'" :columns="TagColumns" />
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Columns:
|
||||||
|
<br>
|
||||||
|
<ColumnCheckboxGroup :header="'action:'" :columns="MoveColumns" :default="true" />
|
||||||
|
<ColumnCheckboxGroup :header="'details:'" :columns="DetailsColumns" :default="true"/>
|
||||||
|
<ColumnCheckboxGroup :header="'equipment:'" :columns="EquipmentColumns" />
|
||||||
|
<ColumnCheckboxGroup :header="'stats:'" :columns="StatsColumns" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import ColumnCheckboxGroup from './ColumnCheckboxGroup.vue';
|
||||||
|
import FilterCheckboxGroup from './FilterCheckboxGroup.vue';
|
||||||
|
import { StatsColumns, MoveColumns, TagColumns, EquipmentColumns, DetailsColumns } from '../lib/columns';
|
||||||
|
|
||||||
|
const { accounts, invs } = useStoreRef()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { useStoreRef } from '../state/state';
|
||||||
|
|
||||||
|
</script>
|
|
@ -5,13 +5,62 @@ import { TricksterInventory, TricksterItem } from "./trickster"
|
||||||
import Core from "handsontable/core";
|
import Core from "handsontable/core";
|
||||||
|
|
||||||
|
|
||||||
type DefaultColumnName = "Image"|"Name"|"Count"
|
export const BasicColumns = [
|
||||||
type ActionColumnName = "Move"|"MoveCount"|"ConfirmMove"
|
"Image","Name","Count",
|
||||||
type TagColumName = "Equip"|"Drill"|"Card"|"Quest"|"Consume"
|
]
|
||||||
type StatColumnName = "AP"|"Gun AP"|"AC"|"DX"|"MP"|"MA"|"MD"|"WT"|"DA"|"LK"|"HP"|"DP"|"HV"
|
|
||||||
type EquipmentColumnName = "MinLvl"|"Slots"|"RefineNumber"|"RefineState"
|
|
||||||
type ColumnName = DefaultColumnName | TagColumName | StatColumnName | ActionColumnName | EquipmentColumnName
|
|
||||||
|
|
||||||
|
export const DetailsColumns = [
|
||||||
|
"Desc","Use",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const MoveColumns = [
|
||||||
|
"Move","MoveCount",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const TagColumns = [
|
||||||
|
"Equip","Drill","Card","Quest","Consume"
|
||||||
|
]
|
||||||
|
|
||||||
|
export const HackColumns = [
|
||||||
|
"All"
|
||||||
|
]
|
||||||
|
|
||||||
|
export const EquipmentColumns = [
|
||||||
|
"MinLvl","Slots","RefineNumber","RefineState",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const StatsColumns = [
|
||||||
|
"AP","GunAP","AC","DX","MP","MA","MD","WT","DA","LK","HP","DP","HV",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const ColumnNames = [
|
||||||
|
...BasicColumns,
|
||||||
|
...MoveColumns,
|
||||||
|
...DetailsColumns,
|
||||||
|
...EquipmentColumns,
|
||||||
|
...StatsColumns,
|
||||||
|
...TagColumns,
|
||||||
|
]
|
||||||
|
|
||||||
|
export type ColumnName = typeof ColumnNames[number]
|
||||||
|
|
||||||
|
const c = (a:ColumnName | ColumnInfo):ColumnName => {
|
||||||
|
switch(typeof a) {
|
||||||
|
case "string":
|
||||||
|
return a
|
||||||
|
case "object":
|
||||||
|
return a.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const LazyColumn = c;
|
||||||
|
export const ColumnSorter = (a:ColumnName | ColumnInfo, b: ColumnName | ColumnInfo):number => {
|
||||||
|
let n1 = ColumnNames.indexOf(c(a))
|
||||||
|
let n2 = ColumnNames.indexOf(c(b))
|
||||||
|
if(n1 == n2) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return n1 > n2 ? 1 : -1
|
||||||
|
}
|
||||||
|
|
||||||
export interface ColumnInfo {
|
export interface ColumnInfo {
|
||||||
name: ColumnName
|
name: ColumnName
|
||||||
|
@ -132,15 +181,6 @@ function moveCountRenderer(instance:Core, td:any, row:number, col:number, prop:a
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfirmMove implements ColumnInfo {
|
|
||||||
name:ColumnName = "ConfirmMove"
|
|
||||||
displayName = "Confirm"
|
|
||||||
writable = true
|
|
||||||
getter(item:TricksterItem):(string|number){
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Equip implements ColumnInfo {
|
class Equip implements ColumnInfo {
|
||||||
name:ColumnName = "Equip"
|
name:ColumnName = "Equip"
|
||||||
displayName = "equip"
|
displayName = "equip"
|
||||||
|
@ -157,6 +197,14 @@ class Drill implements ColumnInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class All implements ColumnInfo {
|
||||||
|
name:ColumnName = "All"
|
||||||
|
displayName = "all"
|
||||||
|
getter(_:TricksterItem):(string|number){
|
||||||
|
return -10000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Card implements ColumnInfo {
|
class Card implements ColumnInfo {
|
||||||
name:ColumnName = "Card"
|
name:ColumnName = "Card"
|
||||||
displayName = "card"
|
displayName = "card"
|
||||||
|
@ -202,7 +250,7 @@ class AP implements ColumnInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GunAP implements ColumnInfo {
|
class GunAP implements ColumnInfo {
|
||||||
name:ColumnName = "Gun AP"
|
name:ColumnName = "GunAP"
|
||||||
displayName = "Gun AP"
|
displayName = "Gun AP"
|
||||||
getter(item:TricksterItem):(string|number){
|
getter(item:TricksterItem):(string|number){
|
||||||
return item.stats ? item.stats["Gun AP"] : ""
|
return item.stats ? item.stats["Gun AP"] : ""
|
||||||
|
@ -301,7 +349,7 @@ class MinLvl implements ColumnInfo {
|
||||||
displayName = "lvl"
|
displayName = "lvl"
|
||||||
getter(item:TricksterItem):(string|number){
|
getter(item:TricksterItem):(string|number){
|
||||||
//TODO:
|
//TODO:
|
||||||
return 0
|
return item.item_min_level? item.item_min_level:""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,13 +358,13 @@ class Slots implements ColumnInfo {
|
||||||
displayName = "slots"
|
displayName = "slots"
|
||||||
getter(item:TricksterItem):(string|number){
|
getter(item:TricksterItem):(string|number){
|
||||||
//TODO:
|
//TODO:
|
||||||
return 0
|
return item.item_slots ? item.item_slots : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RefineNumber implements ColumnInfo {
|
class RefineNumber implements ColumnInfo {
|
||||||
name:ColumnName = "RefineNumber"
|
name:ColumnName = "RefineNumber"
|
||||||
displayName = "R#"
|
displayName = "refine"
|
||||||
getter(item:TricksterItem):(string|number){
|
getter(item:TricksterItem):(string|number){
|
||||||
return item.refine_level ? item.refine_level : 0
|
return item.refine_level ? item.refine_level : 0
|
||||||
}
|
}
|
||||||
|
@ -324,31 +372,84 @@ class RefineNumber implements ColumnInfo {
|
||||||
|
|
||||||
class RefineState implements ColumnInfo {
|
class RefineState implements ColumnInfo {
|
||||||
name:ColumnName = "RefineState"
|
name:ColumnName = "RefineState"
|
||||||
displayName = "State"
|
displayName = "bork"
|
||||||
getter(item:TricksterItem):(string|number){
|
getter(item:TricksterItem):(string|number){
|
||||||
return item.refine_state ? item.refine_state : 0
|
return item.refine_state ? item.refine_state : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Desc implements ColumnInfo {
|
||||||
|
name:ColumnName = "Desc"
|
||||||
|
displayName = "desc"
|
||||||
|
renderer = descRenderer
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function descRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
let showText = stringifiedValue;
|
||||||
|
const div= document.createElement('div');
|
||||||
|
div.innerHTML = showText
|
||||||
|
div.title = showText
|
||||||
|
div.style.maxWidth = "30ch"
|
||||||
|
div.style.textOverflow = "ellipsis"
|
||||||
|
div.style.overflow= "hidden"
|
||||||
|
div.style.whiteSpace= "nowrap"
|
||||||
|
Handsontable.dom.addEvent(div, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(div);
|
||||||
|
td.classList.add("htLeft")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Use implements ColumnInfo {
|
||||||
|
name:ColumnName = "Use"
|
||||||
|
displayName = "use"
|
||||||
|
renderer= useRenderer;
|
||||||
|
getter(item:TricksterItem):(string|number){
|
||||||
|
return item.item_use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function useRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
|
||||||
|
const stringifiedValue = Handsontable.helper.stringify(value);
|
||||||
|
let showText = stringifiedValue;
|
||||||
|
const div= document.createElement('div');
|
||||||
|
div.title = showText
|
||||||
|
div.innerHTML = showText
|
||||||
|
div.style.maxWidth = "30ch"
|
||||||
|
div.style.textOverflow = "ellipsis"
|
||||||
|
div.style.overflow= "hidden"
|
||||||
|
div.style.whiteSpace= "nowrap"
|
||||||
|
Handsontable.dom.addEvent(div, 'mousedown', event =>{
|
||||||
|
event!.preventDefault();
|
||||||
|
});
|
||||||
|
Handsontable.dom.empty(td);
|
||||||
|
td.appendChild(div);
|
||||||
|
td.classList.add("htLeft")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const ColumnByNames = (...n:ColumnName[]) => {
|
export const ColumnByNames = (...n:ColumnName[]) => {
|
||||||
return n.map(ColumnByName)
|
return n.map(ColumnByName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const ColumnByName = (n:ColumnName) => {
|
export const ColumnByName = (n:ColumnName) => {
|
||||||
return Columns[n]
|
return Columns[n]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Columns:{[Property in ColumnName]:ColumnInfo}= {
|
||||||
export const Columns = {
|
Use: new Use(),
|
||||||
|
Desc: new Desc(),
|
||||||
Image: new Image(),
|
Image: new Image(),
|
||||||
Name: new Name(),
|
Name: new Name(),
|
||||||
Count: new Count(),
|
Count: new Count(),
|
||||||
Move: new Move(),
|
Move: new Move(),
|
||||||
MoveCount: new MoveCount(),
|
MoveCount: new MoveCount(),
|
||||||
ConfirmMove: new ConfirmMove(),
|
|
||||||
Equip: new Equip(),
|
Equip: new Equip(),
|
||||||
Drill: new Drill(),
|
Drill: new Drill(),
|
||||||
Card: new Card(),
|
Card: new Card(),
|
||||||
|
@ -356,7 +457,6 @@ export const Columns = {
|
||||||
Consume: new Consume(),
|
Consume: new Consume(),
|
||||||
AP: new AP(),
|
AP: new AP(),
|
||||||
GunAP: new GunAP(),
|
GunAP: new GunAP(),
|
||||||
'Gun AP': new GunAP(),
|
|
||||||
AC: new AC(),
|
AC: new AC(),
|
||||||
DX: new DX(),
|
DX: new DX(),
|
||||||
MP: new MP(),
|
MP: new MP(),
|
||||||
|
@ -372,33 +472,5 @@ export const Columns = {
|
||||||
Slots: new Slots(),
|
Slots: new Slots(),
|
||||||
RefineNumber: new RefineNumber(),
|
RefineNumber: new RefineNumber(),
|
||||||
RefineState: new RefineState(),
|
RefineState: new RefineState(),
|
||||||
image: new Image(),
|
All: new All(),
|
||||||
name: new Name(),
|
|
||||||
count: new Count(),
|
|
||||||
move: new Move(),
|
|
||||||
movecount: new MoveCount(),
|
|
||||||
confirmmove: new ConfirmMove(),
|
|
||||||
equip: new Equip(),
|
|
||||||
drill: new Drill(),
|
|
||||||
card: new Card(),
|
|
||||||
quest: new Quest(),
|
|
||||||
consume: new Consume(),
|
|
||||||
ap: new AP(),
|
|
||||||
gunap: new GunAP(),
|
|
||||||
'gun ap': new GunAP(),
|
|
||||||
ac: new AC(),
|
|
||||||
dx: new DX(),
|
|
||||||
mp: new MP(),
|
|
||||||
ma: new MA(),
|
|
||||||
md: new MD(),
|
|
||||||
wt: new WT(),
|
|
||||||
da: new DA(),
|
|
||||||
lk: new LK(),
|
|
||||||
hp: new HP(),
|
|
||||||
dp: new DP(),
|
|
||||||
hv: new HV(),
|
|
||||||
minlvl: new MinLvl(),
|
|
||||||
slots: new Slots(),
|
|
||||||
refinenumber: new RefineNumber(),
|
|
||||||
refinestate: new RefineState(),
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
import { Axios, AxiosResponse } from "axios"
|
||||||
|
import log from "loglevel"
|
||||||
|
import { Session } from "./session"
|
||||||
|
import { TricksterInventory, TricksterItem, TricksterWallet } from "./trickster"
|
||||||
|
|
||||||
|
|
||||||
|
export interface LTOApi {
|
||||||
|
GetCharacters:(name:string)=>Promise<Array<TricksterInventory>>
|
||||||
|
GetAccounts:() =>Promise<Array<string>>
|
||||||
|
GetLoggedin: ()=>Promise<boolean>
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LTOApiv0 implements LTOApi {
|
||||||
|
|
||||||
|
s: Session
|
||||||
|
|
||||||
|
constructor(s:Session) {
|
||||||
|
this.s = s
|
||||||
|
}
|
||||||
|
GetCharacters = async (account: string):Promise<Array<TricksterInventory>> =>{
|
||||||
|
return this.s.authed_request("GET", `item-manager/items/account/${account}`,undefined).then(async (ans:AxiosResponse)=>{
|
||||||
|
const o = ans.data
|
||||||
|
log.debug("GetCharacters", o)
|
||||||
|
let out = [{
|
||||||
|
name: account,
|
||||||
|
id: ":" + account,
|
||||||
|
path: account,
|
||||||
|
wallet:{
|
||||||
|
galders:0,
|
||||||
|
state:0,
|
||||||
|
job_img: "BANK",
|
||||||
|
} as TricksterWallet,
|
||||||
|
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
|
||||||
|
v.unique_id = Number(k)
|
||||||
|
return v
|
||||||
|
}),
|
||||||
|
} as TricksterInventory]
|
||||||
|
await Promise.all(Object.entries(o.characters).map(async (x:[string,any])=>{
|
||||||
|
return this.GetInventory(`${account}/${x[1].name}`).then((ans)=>{
|
||||||
|
out.push(ans)
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
return out
|
||||||
|
})
|
||||||
|
}
|
||||||
|
GetInventory = async (char_path: string):Promise<TricksterInventory> =>{
|
||||||
|
if(char_path.startsWith(":")) {
|
||||||
|
char_path = char_path.replace(":","")
|
||||||
|
}
|
||||||
|
return this.s.authed_request("GET", `item-manager/items/account/${char_path}`,undefined).then((ans:AxiosResponse)=>{
|
||||||
|
const o = ans.data
|
||||||
|
log.debug("GetInventory", o)
|
||||||
|
let name = ""
|
||||||
|
let id = ""
|
||||||
|
let wallet:TricksterWallet = {galders:0,state:0,job_img:""}
|
||||||
|
if(char_path.includes("/")) {
|
||||||
|
let [char, val] = Object.entries(o.characters)[0] as [string,any]
|
||||||
|
name = val.name
|
||||||
|
id = char
|
||||||
|
wallet = {
|
||||||
|
galders:val.galders as number,
|
||||||
|
state:val.state as number,
|
||||||
|
job_img: val.job_img as string
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
name = char_path
|
||||||
|
id = char_path
|
||||||
|
wallet = {
|
||||||
|
galders: 0,
|
||||||
|
state: 0,
|
||||||
|
job_img: "bank",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let out = {
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
wallet,
|
||||||
|
path: char_path,
|
||||||
|
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
|
||||||
|
v.unique_id = Number(k)
|
||||||
|
return v
|
||||||
|
}),
|
||||||
|
} as TricksterInventory
|
||||||
|
return out
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
GetAccounts = async ():Promise<string[]> => {
|
||||||
|
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
|
||||||
|
log.debug("GetAccounts", ans.data)
|
||||||
|
return ans.data.map((x:any)=>x.name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
GetLoggedin = async ():Promise<boolean> => {
|
||||||
|
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
|
||||||
|
if(ans.status == 401) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if(ans.status == 200) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import axios from "axios";
|
import axios, { AxiosResponse, Method } from "axios";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import { getCookie, removeCookie } from "typescript-cookie";
|
import { getCookie, removeCookie } from "typescript-cookie";
|
||||||
|
|
||||||
|
@ -6,15 +6,20 @@ export interface Session {
|
||||||
user:string
|
user:string
|
||||||
xsrf:string
|
xsrf:string
|
||||||
csrf:string
|
csrf:string
|
||||||
lto:string
|
authed_request:(verb:Method,url:string,data:any)=>Promise<any>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const API_ROOT = "/lifeto/"
|
export const SITE_ROOT = "/lifeto/"
|
||||||
|
export const API_ROOT = "api/lifeto/"
|
||||||
|
|
||||||
const endpoint = (name:string)=>{
|
const login_endpoint = (name:string)=>{
|
||||||
return API_ROOT + name
|
return SITE_ROOT + name
|
||||||
}
|
}
|
||||||
|
const api_endpoint = (name:string)=>{
|
||||||
|
return SITE_ROOT+API_ROOT + name
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class LoginHelper {
|
export class LoginHelper {
|
||||||
user:string
|
user:string
|
||||||
|
@ -26,9 +31,8 @@ export class LoginHelper {
|
||||||
}
|
}
|
||||||
login = async ():Promise<TokenSession> =>{
|
login = async ():Promise<TokenSession> =>{
|
||||||
removeCookie("XSRF-TOKEN")
|
removeCookie("XSRF-TOKEN")
|
||||||
removeCookie("lifeto_session", {path:'/'})
|
|
||||||
await sleep(1000)
|
await sleep(1000)
|
||||||
return axios.get(endpoint("login"),{withCredentials:false})
|
return axios.get(login_endpoint("login"),{withCredentials:false})
|
||||||
.then(async (x)=>{
|
.then(async (x)=>{
|
||||||
console.log(x)
|
console.log(x)
|
||||||
if(x.data){
|
if(x.data){
|
||||||
|
@ -37,7 +41,7 @@ export class LoginHelper {
|
||||||
}catch(e){
|
}catch(e){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return axios.post(endpoint("login"),{
|
return axios.post(login_endpoint("login"),{
|
||||||
login:this.user,
|
login:this.user,
|
||||||
password:this.pass,
|
password:this.pass,
|
||||||
redirectTo:"lifeto"
|
redirectTo:"lifeto"
|
||||||
|
@ -45,41 +49,38 @@ export class LoginHelper {
|
||||||
.then(async (x)=>{
|
.then(async (x)=>{
|
||||||
await sleep(100)
|
await sleep(100)
|
||||||
let xsrf= getCookie("XSRF-TOKEN")
|
let xsrf= getCookie("XSRF-TOKEN")
|
||||||
let lifeto = getCookie("lifeto_session")
|
return new TokenSession(this.user,this.csrf!, xsrf!)
|
||||||
return new TokenSession(this.user,this.csrf!, xsrf!, lifeto!)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const sleep= async(ms:number)=> {
|
const sleep= async(ms:number)=> {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms))
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
}
|
}
|
||||||
export class TokenSession {
|
|
||||||
|
export class TokenSession implements Session {
|
||||||
csrf:string
|
csrf:string
|
||||||
xsrf:string
|
xsrf:string
|
||||||
lto:string
|
|
||||||
user:string
|
user:string
|
||||||
constructor(name:string, csrf:string, xsrf: string, lifeto:string){
|
constructor(name:string, csrf:string, xsrf: string){
|
||||||
this.user = name
|
this.user = name
|
||||||
this.csrf = csrf
|
this.csrf = csrf
|
||||||
this.xsrf = xsrf;
|
this.xsrf = xsrf;
|
||||||
this.lto = lifeto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authed_request = async (verb:string,url:string,data:any) => {
|
authed_request = async (verb:string,url:string,data:any):Promise<AxiosResponse> => {
|
||||||
let promise
|
let promise
|
||||||
switch (verb){
|
switch (verb.toLowerCase()){
|
||||||
case "post":
|
case "post":
|
||||||
promise = axios.post(endpoint(url),data,this.genHeaders())
|
promise = axios.post(api_endpoint(url),data,this.genHeaders())
|
||||||
break;
|
break;
|
||||||
case "postraw":
|
case "postraw":
|
||||||
const querystring = qs.stringify(data)
|
const querystring = qs.stringify(data)
|
||||||
promise = axios.post(endpoint(url),querystring,this.genHeaders())
|
promise = axios.post(api_endpoint(url),querystring,this.genHeaders())
|
||||||
break;
|
break;
|
||||||
case "get":
|
case "get":
|
||||||
default:
|
default:
|
||||||
promise = axios.get(endpoint(url),this.genHeaders())
|
promise = axios.get(api_endpoint(url),this.genHeaders())
|
||||||
}
|
}
|
||||||
return promise.then(x=>{
|
return promise.then(x=>{
|
||||||
if(x.data){
|
if(x.data){
|
||||||
|
@ -93,7 +94,6 @@ export class TokenSession {
|
||||||
return y.split("=")[1].split(";")[0];
|
return y.split("=")[1].split(";")[0];
|
||||||
})
|
})
|
||||||
this.xsrf = cookies[0]
|
this.xsrf = cookies[0]
|
||||||
this.lto = cookies[1]
|
|
||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
})
|
})
|
||||||
|
@ -101,19 +101,8 @@ export class TokenSession {
|
||||||
genHeaders = ()=>{
|
genHeaders = ()=>{
|
||||||
const out = {
|
const out = {
|
||||||
headers:{
|
headers:{
|
||||||
Cookie:`XSRF-TOKEN=${this.xsrf}; lifeto_session=${this.lto}`,
|
Accept: "application/json",
|
||||||
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
|
||||||
Connection: "keep-alive",
|
|
||||||
"X-Requested-With":"XMLHttpRequest",
|
|
||||||
Host: "beta.lifeto.co",
|
|
||||||
"Alt-Used": "beta.lifeto.co",
|
|
||||||
"Update-Insecure-Requests": 1,
|
"Update-Insecure-Requests": 1,
|
||||||
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
|
|
||||||
"Sec-Fetch-Mode":"navigate",
|
|
||||||
"Sec-Fetch-Dest":"document",
|
|
||||||
"Sec-Fetch-Site":"same-origin",
|
|
||||||
"Sec-Fetch-User":"?1",
|
|
||||||
"TE":"trailers"
|
|
||||||
},
|
},
|
||||||
withCredentials:true
|
withCredentials:true
|
||||||
}
|
}
|
||||||
|
|
134
src/lib/table.ts
134
src/lib/table.ts
|
@ -1,46 +1,137 @@
|
||||||
import { HotTableProps } from "@handsontable/vue3/types"
|
import { HotTableProps } from "@handsontable/vue3/types"
|
||||||
import { TricksterInventory } from "./trickster"
|
import { TricksterInventory } from "./trickster"
|
||||||
import {ColumnInfo} from "./columns"
|
import {ColumnInfo, ColumnName, Columns, ColumnSorter, LazyColumn} from "./columns"
|
||||||
import { ColumnSettings } from "handsontable/settings"
|
import { ColumnSettings } from "handsontable/settings"
|
||||||
import { PredefinedMenuItemKey } from "handsontable/plugins/contextMenu"
|
import { PredefinedMenuItemKey } from "handsontable/plugins/contextMenu"
|
||||||
|
import { ref } from "vue"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface InventoryTableOptions {
|
||||||
|
columns: ColumnSet
|
||||||
|
tags: ColumnSet
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Mappable<T> {
|
||||||
|
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class ColumnSet implements Set<ColumnInfo>, Mappable<ColumnInfo>{
|
||||||
|
s: Set<ColumnName> = new Set()
|
||||||
|
size: number;
|
||||||
|
dirty = ref(0)
|
||||||
|
constructor(i?:Iterable<ColumnInfo | ColumnName>){
|
||||||
|
if(i){
|
||||||
|
for (const a of i) {
|
||||||
|
this.s.add(LazyColumn(a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.size = 0
|
||||||
|
this.mark()
|
||||||
|
}
|
||||||
|
map<U>(callbackfn: (value: ColumnInfo, index: number, array: ColumnInfo[]) => U, thisArg?: any): U[] {
|
||||||
|
return Array.from(this.values()).map(callbackfn, thisArg)
|
||||||
|
}
|
||||||
|
[Symbol.iterator](): IterableIterator<ColumnInfo>{
|
||||||
|
return this.values()
|
||||||
|
}
|
||||||
|
[Symbol.toStringTag] = "ColumnSet";
|
||||||
|
entries(): IterableIterator<[ColumnInfo, ColumnInfo]>{
|
||||||
|
return Array.from(this.values()).map((x):[ColumnInfo,ColumnInfo]=>{return [x,x]}).values()
|
||||||
|
}
|
||||||
|
keys(): IterableIterator<ColumnInfo>{
|
||||||
|
return this.values()
|
||||||
|
}
|
||||||
|
forEach(callbackfn: (value: ColumnInfo, value2: ColumnInfo, set: Set<ColumnInfo>) => void, thisArg?: any): void{
|
||||||
|
Array.from(this.values()).forEach((v)=>{
|
||||||
|
if(this.has(v)) {
|
||||||
|
callbackfn(v, v, new Set(this.values()))
|
||||||
|
}
|
||||||
|
}, thisArg)
|
||||||
|
}
|
||||||
|
values(): IterableIterator<ColumnInfo>{
|
||||||
|
return Array.from(this.s.values()).sort(ColumnSorter).map((a, b)=>{
|
||||||
|
return Columns[a]
|
||||||
|
}).values()
|
||||||
|
}
|
||||||
|
mark() {
|
||||||
|
this.dirty.value = this.dirty.value + 1
|
||||||
|
this.size = this.s.size
|
||||||
|
}
|
||||||
|
add(value: ColumnInfo | ColumnName): this {
|
||||||
|
this.mark()
|
||||||
|
this.s.add(LazyColumn(value))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
clear(): void {
|
||||||
|
this.mark()
|
||||||
|
this.s.clear()
|
||||||
|
}
|
||||||
|
delete(value: ColumnInfo | ColumnName): boolean{
|
||||||
|
this.mark()
|
||||||
|
return this.s.delete(LazyColumn(value))
|
||||||
|
}
|
||||||
|
has(value: ColumnInfo | ColumnName): boolean{
|
||||||
|
return this.s.has(LazyColumn(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class InventoryTable {
|
export class InventoryTable {
|
||||||
inventory:TricksterInventory
|
inv!:TricksterInventory
|
||||||
columns: ColumnInfo[]
|
o!: InventoryTableOptions
|
||||||
|
|
||||||
constructor(inv:TricksterInventory, ...columns:ColumnInfo[]) {
|
constructor(inv:TricksterInventory, o:InventoryTableOptions) {
|
||||||
this.inventory = inv
|
this.setInv(inv)
|
||||||
this.columns = columns
|
this.setOptions(o)
|
||||||
|
}
|
||||||
|
setOptions(o:InventoryTableOptions) {
|
||||||
|
this.o = o
|
||||||
|
}
|
||||||
|
setInv(inv:TricksterInventory) {
|
||||||
|
this.inv = inv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getTableColumnNames(): string[] {
|
getTableColumnNames(): string[] {
|
||||||
return this.columns.map(x=>x.displayName)
|
return this.o.columns.map(x=>x.displayName)
|
||||||
}
|
}
|
||||||
|
|
||||||
getTableColumnSettings(): ColumnSettings[] {
|
getTableColumnSettings(): ColumnSettings[] {
|
||||||
return this.columns.map(x=>({
|
return this.o.columns.map(x=>({
|
||||||
renderer: x.renderer ? x.renderer : "text",
|
renderer: x.renderer ? x.renderer : "text",
|
||||||
dropdownMenu: x.filtering ? DefaultDropdownItems() : false,
|
dropdownMenu: x.filtering ? DefaultDropdownItems() : false,
|
||||||
readOnly: x.writable ? false : true,
|
readOnly: x.writable ? false : true,
|
||||||
selectionMode: x.writable ? "multiple" : "single"
|
selectionMode: x.writable ? "multiple" : "single"
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
getTableRows():any[][] {
|
getTableRows():any[][] {
|
||||||
return this.inventory.items.map((item)=>{
|
return Object.values(this.inv.items)
|
||||||
return this.columns.map(x=>x.getter(item))
|
.filter((item):boolean=>{
|
||||||
|
let found = false
|
||||||
|
if(this.o.tags.s.size > 0) {
|
||||||
|
let comparer = 1
|
||||||
|
for(const tag of this.o.tags.values()) {
|
||||||
|
let chk = tag.getter(item)
|
||||||
|
if(chk === comparer) {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
return found
|
||||||
|
})
|
||||||
|
.map((item)=>{
|
||||||
|
return this.o.columns.map(x=>{
|
||||||
|
return x.getter(item)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildTable():TableRecipe {
|
BuildTable():TableRecipe {
|
||||||
const s = DefaultSettings()
|
const s = DefaultSettings()
|
||||||
|
const dat = this.getTableRows()
|
||||||
return {
|
return {
|
||||||
data: this.getTableRows(),
|
data: dat,
|
||||||
settings: {
|
settings: {
|
||||||
data: this.getTableRows(),
|
data: dat,
|
||||||
colHeaders:this.getTableColumnNames(),
|
colHeaders:this.getTableColumnNames(),
|
||||||
columns:this.getTableColumnSettings(),
|
columns:this.getTableColumnSettings(),
|
||||||
...s
|
...s
|
||||||
|
@ -71,6 +162,7 @@ export const DefaultSettings = ():HotTableProps=>{
|
||||||
indicator: true,
|
indicator: true,
|
||||||
headerAction: true,
|
headerAction: true,
|
||||||
},
|
},
|
||||||
|
className: 'htLeft',
|
||||||
contextMenu: false,
|
contextMenu: false,
|
||||||
readOnlyCellClassName: "",
|
readOnlyCellClassName: "",
|
||||||
licenseKey:"non-commercial-and-evaluation",
|
licenseKey:"non-commercial-and-evaluation",
|
||||||
|
|
|
@ -11,6 +11,10 @@ export interface TricksterItem {
|
||||||
item_name: string;
|
item_name: string;
|
||||||
item_id: number;
|
item_id: number;
|
||||||
item_count: number;
|
item_count: number;
|
||||||
|
item_desc: string;
|
||||||
|
item_use: string;
|
||||||
|
item_slots?: number;
|
||||||
|
item_min_level?: number;
|
||||||
is_equip?: boolean;
|
is_equip?: boolean;
|
||||||
is_drill?: boolean;
|
is_drill?: boolean;
|
||||||
item_expire_time?: ItemExpireTime;
|
item_expire_time?: ItemExpireTime;
|
||||||
|
@ -29,9 +33,10 @@ export interface TricksterWallet {
|
||||||
|
|
||||||
export interface TricksterInventory {
|
export interface TricksterInventory {
|
||||||
name:string
|
name:string
|
||||||
|
path:string
|
||||||
|
id:string
|
||||||
wallet?:TricksterWallet
|
wallet?:TricksterWallet
|
||||||
items:TricksterItem[]
|
items:{[key:string]:TricksterItem}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,14 +44,11 @@ export interface TricksterInventory {
|
||||||
export const SampleData:{[key:string]:TricksterInventory} = {
|
export const SampleData:{[key:string]:TricksterInventory} = {
|
||||||
aysheBoyfriend: {
|
aysheBoyfriend: {
|
||||||
name: sampleAyshe.characters[100047311].name,
|
name: sampleAyshe.characters[100047311].name,
|
||||||
items: Object.entries(sampleAyshe.items).map(([k, v]:[string, any])=>{
|
items: sampleAyshe.items,
|
||||||
v.unique_id = k
|
|
||||||
return v
|
|
||||||
}),
|
|
||||||
wallet: {
|
wallet: {
|
||||||
galders: sampleAyshe.characters[100047311].galders,
|
galders: sampleAyshe.characters[100047311].galders,
|
||||||
job_img: sampleAyshe.characters[100047311].job_img,
|
job_img: sampleAyshe.characters[100047311].job_img,
|
||||||
state: sampleAyshe.characters[100047311].state
|
state: sampleAyshe.characters[100047311].state
|
||||||
}
|
}
|
||||||
}
|
} as any
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import App from './App.vue'
|
||||||
|
|
||||||
|
|
||||||
import { globalCookiesConfig } from "vue3-cookies";
|
import { globalCookiesConfig } from "vue3-cookies";
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
import log from 'loglevel';
|
||||||
|
|
||||||
globalCookiesConfig({
|
globalCookiesConfig({
|
||||||
expireTimes: "365d",
|
expireTimes: "365d",
|
||||||
|
@ -12,4 +14,9 @@ globalCookiesConfig({
|
||||||
sameSite: "None",
|
sameSite: "None",
|
||||||
});
|
});
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
log.setLevel("debug")
|
||||||
|
|
||||||
|
const pinia = createPinia()
|
||||||
|
createApp(App).
|
||||||
|
use(pinia).
|
||||||
|
mount('#app')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div> {{loginString}} </div>
|
||||||
<section class="login_modal">
|
<section class="login_modal">
|
||||||
<div class="login_field">
|
<div class="login_field">
|
||||||
<label for="userName">Username: </label>
|
<label for="userName">Username: </label>
|
||||||
|
@ -28,39 +29,47 @@
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useVModel } from '@vueuse/core'
|
const username = ref("")
|
||||||
|
const password = ref("")
|
||||||
|
const loginString = ref("not logged in")
|
||||||
|
|
||||||
const props = defineProps<{
|
const login = () => {
|
||||||
username:string
|
new LoginHelper(username.value, password.value).login()
|
||||||
password:string
|
.then((session)=>{
|
||||||
}>()
|
console.log(session, "adding to storage")
|
||||||
const data = {
|
storage.AddSession(session)
|
||||||
username: useVModel(props, 'username', defineEmits(['update:username'])),
|
}).catch((e)=>{
|
||||||
password:useVModel(props, 'password', defineEmits(['update:password']))
|
if(e.code == "ERR_BAD_REQUEST") {
|
||||||
|
alert("invalid username/password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
alert("unknown error, please report")
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const s = storage.GetSession()
|
||||||
|
const api = new LTOApiv0(s)
|
||||||
|
if (s != undefined) {
|
||||||
|
username.value = s.user
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateLogin = () => {
|
||||||
|
api.GetLoggedin().then((res)=>{
|
||||||
|
if(res) {
|
||||||
|
loginString.value = "logged in as " + s.user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
updateLogin()
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
|
import { defineComponent, computed, PropType, defineProps, defineEmits, ref} from 'vue';
|
||||||
|
import { LTOApiv0 } from '../lib/lifeto';
|
||||||
import { LoginHelper, Session } from '../lib/session';
|
import { LoginHelper, Session } from '../lib/session';
|
||||||
import { storage } from '../session_storage';
|
import { storage } from '../session_storage';
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
methods: {
|
|
||||||
login: function() {
|
|
||||||
new LoginHelper(this.username, this.password).login()
|
|
||||||
.then((session)=>{
|
|
||||||
console.log(session, "adding to storage")
|
|
||||||
storage.AddSession(session)
|
|
||||||
}).catch((e)=>{
|
|
||||||
if(e.code == "ERR_BAD_REQUEST") {
|
|
||||||
alert("invalid username/password")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
alert("unknown error, please report")
|
|
||||||
console.log(e)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { getCookie, setCookie} from 'typescript-cookie'
|
import { getCookie, setCookie} from 'typescript-cookie'
|
||||||
import { Session } from './lib/session'
|
import { Session, TokenSession } from './lib/session'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,53 +10,27 @@ export const nameCookie = (...s:string[]):string=>{
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Storage {
|
export class Storage {
|
||||||
GetSessions():{[key:string]:Session} {
|
|
||||||
const all_accounts = getCookie(nameCookie("all_accounts"))
|
GetSession():Session {
|
||||||
const accounts = all_accounts?.split(",")
|
const {user, xsrf, csrf} = {
|
||||||
let out:{[key:string]:Session} = {};
|
user: getCookie(nameCookie("user"))!,
|
||||||
for (const account in accounts) {
|
xsrf: getCookie(nameCookie("xsrf"))!,
|
||||||
let tmp = {
|
csrf: getCookie(nameCookie("csrf"))!
|
||||||
user: account,
|
|
||||||
xsrf: getCookie(nameCookie("xsrf",account))!,
|
|
||||||
lto: getCookie(nameCookie("lto",account))!,
|
|
||||||
csrf: getCookie(nameCookie("csrf",account))!
|
|
||||||
}
|
|
||||||
out[account] = tmp
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
RemoveSessions(...s:Session[]) {
|
|
||||||
for(const v of s) {
|
|
||||||
this.RemoveSession(v)
|
|
||||||
}
|
}
|
||||||
|
return new TokenSession(user, xsrf, csrf)
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveSession(s:Session) {
|
RemoveSession() {
|
||||||
const all_accounts = getCookie(nameCookie("all_accounts"))
|
setCookie(nameCookie("user"),"")
|
||||||
let accounts = all_accounts?.split(",")
|
setCookie(nameCookie("xsrf"),"")
|
||||||
accounts = accounts ? accounts : []
|
setCookie(nameCookie("csrf"),"")
|
||||||
accounts = [...new Set(accounts)]
|
|
||||||
accounts = accounts.filter(x=>x!=s.user)
|
|
||||||
|
|
||||||
setCookie(nameCookie("all_accounts"),accounts.join(","))
|
|
||||||
setCookie(nameCookie("lto",s.user), "")
|
|
||||||
setCookie(nameCookie("xsrf",s.user),"")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSessions(...s:Session[]) {
|
|
||||||
for(const v of s) {
|
|
||||||
this.AddSession(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AddSession(s:Session) {
|
AddSession(s:Session) {
|
||||||
const all_accounts = getCookie(nameCookie("all_accounts"))
|
setCookie(nameCookie("user"),s.user)
|
||||||
let accounts = all_accounts?.split(",")
|
setCookie(nameCookie("xsrf"),s.xsrf)
|
||||||
accounts = accounts ? accounts : []
|
setCookie(nameCookie("csrf"),s.csrf)
|
||||||
accounts.push(s.user)
|
|
||||||
accounts = [...new Set(accounts)]
|
|
||||||
setCookie(nameCookie("lto",s.user), s.lto)
|
|
||||||
setCookie(nameCookie("xsrf",s.user),s.xsrf)
|
|
||||||
setCookie(nameCookie("csrf",s.user),s.csrf)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { defineStore, storeToRefs } from 'pinia'
|
||||||
|
import { BasicColumns, ColumnInfo, ColumnName, Columns, DetailsColumns, MoveColumns } from '../lib/columns'
|
||||||
|
import { ColumnSet } from '../lib/table'
|
||||||
|
import { TricksterInventory } from '../lib/trickster'
|
||||||
|
|
||||||
|
const _defaultColumn:(ColumnInfo| ColumnName)[] = [
|
||||||
|
...BasicColumns,
|
||||||
|
...MoveColumns,
|
||||||
|
...DetailsColumns,
|
||||||
|
]
|
||||||
|
export const useStore = defineStore('state', {
|
||||||
|
state: ()=> {
|
||||||
|
return {
|
||||||
|
accounts: new Set() as Set<string>,
|
||||||
|
invs: new Map() as Map<string,TricksterInventory>,
|
||||||
|
activeTable: "none",
|
||||||
|
screen: "default",
|
||||||
|
columns: new ColumnSet(_defaultColumn),
|
||||||
|
tags: new ColumnSet(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export const useStoreRef = ()=>{return storeToRefs(useStore())};
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,6 @@ export default defineConfig({
|
||||||
target: "https://beta.lifeto.co/",
|
target: "https://beta.lifeto.co/",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/lifeto/, ''),
|
rewrite: (path) => path.replace(/^\/lifeto/, ''),
|
||||||
hostRewrite: "localhost:3001/lifeto",
|
|
||||||
cookieDomainRewrite:{
|
|
||||||
"*":"",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue