one-time hints; builder touchups
This commit is contained in:
@@ -8,6 +8,7 @@ import {tvCustomThemes} from "../../theme.js";
|
|||||||
export let widget = null
|
export let widget = null
|
||||||
export let chart = null
|
export let chart = null
|
||||||
export let crosshairPoint = null
|
export let crosshairPoint = null
|
||||||
|
export let defaultShapeHandler = null // if set, then TV events that dont have a registered shape handler get passed directly to this function
|
||||||
let symbolChangedCbs = [] // callbacks for TV's chart.onSymbolChanged()
|
let symbolChangedCbs = [] // callbacks for TV's chart.onSymbolChanged()
|
||||||
|
|
||||||
|
|
||||||
@@ -268,6 +269,7 @@ export function drawShape(shapeType, ...callbacks) {
|
|||||||
drawingTool = null
|
drawingTool = null
|
||||||
previousDrawingTool = widget.selectedLineTool()
|
previousDrawingTool = widget.selectedLineTool()
|
||||||
co.drawing = true
|
co.drawing = true
|
||||||
|
co.drew = false
|
||||||
widget.selectLineTool(shapeType.code)
|
widget.selectLineTool(shapeType.code)
|
||||||
invokeCallbacks(callbacks, 'onDraw')
|
invokeCallbacks(callbacks, 'onDraw')
|
||||||
}
|
}
|
||||||
@@ -462,9 +464,11 @@ function doHandleDrawingEvent(id, event) {
|
|||||||
const props = shape.getProperties()
|
const props = shape.getProperties()
|
||||||
if (id in shapeCallbacks)
|
if (id in shapeCallbacks)
|
||||||
invokeCallbacks(shapeCallbacks[id], 'onProps', id, shape, props)
|
invokeCallbacks(shapeCallbacks[id], 'onProps', id, shape, props)
|
||||||
else
|
else {
|
||||||
// otherwise it's an event on a shape we don't "own"
|
// otherwise it's an event on a shape we don't "own" that could be being drawn
|
||||||
|
co.drew = true
|
||||||
console.log('warning: ignoring setProperties on TV shape', id, props)
|
console.log('warning: ignoring setProperties on TV shape', id, props)
|
||||||
|
}
|
||||||
} else if (event === 'move') {
|
} else if (event === 'move') {
|
||||||
if (id in shapeCallbacks) {
|
if (id in shapeCallbacks) {
|
||||||
invokeCallbacks(shapeCallbacks[id], 'onMove', id, shape)
|
invokeCallbacks(shapeCallbacks[id], 'onMove', id, shape)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-tooltip v-model="show" :close-on-content-click="true"/>
|
<v-tooltip v-model="show" :close-on-content-click="true" :close-on-back="false" :close-delay="null"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -8,25 +8,26 @@ import {usePrefStore} from "@/store/store.js";
|
|||||||
|
|
||||||
const prefs = usePrefStore()
|
const prefs = usePrefStore()
|
||||||
|
|
||||||
const modelValue = defineModel()
|
|
||||||
const hasBeenShown = ref(false)
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
key: {type: String, required: true},
|
name: {type: String, required: true},
|
||||||
after: {type: String, default: null},
|
when: {type: Boolean, default: true}, // optional conditional for when to show
|
||||||
|
after: {type: String, default: null}, // set to the name of another hint that must happen before this hint, to chain hints into a tutorial.
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const forceClose = ref(false)
|
||||||
|
|
||||||
const show = computed({
|
const show = computed({
|
||||||
get() {
|
get() {
|
||||||
const result = !prefs.hints[props.key] && modelValue.value && (props.after === null || prefs.hints[props.after])
|
const shownBefore = prefs.hints[props.name];
|
||||||
&& !props.finished
|
const whenOk = props.when;
|
||||||
|
const afterOk = props.after === null || prefs.hints[props.after];
|
||||||
|
const result = !forceClose.value && !shownBefore && whenOk && afterOk
|
||||||
|
// console.log(`show ${props.name}? ${result} <=`, !forceClose.value, whenOk, afterOk, prefs.hints)
|
||||||
if (result)
|
if (result)
|
||||||
hasBeenShown.value = true
|
prefs.hints[props.name] = true
|
||||||
else if (hasBeenShown.value)
|
|
||||||
prefs.hints[props.key] = true
|
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
set(v) { if(!v) prefs.hints[props.key] = true}
|
set(v) { if(!v) forceClose.value=true; }
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="element" class="chart"/>
|
<div id="tv-widget" ref="element" class="chart"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// import "/public/datafeeds/udf/dist/bundle.js"
|
|
||||||
import {onMounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {initWidget} from "@/charts/chart.js";
|
import {initWidget} from "@/charts/chart.js";
|
||||||
|
|
||||||
@@ -12,18 +11,8 @@ const element = ref()
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const el = element.value;
|
const el = element.value;
|
||||||
initWidget(el)
|
initWidget(el)
|
||||||
initShapes()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function initShapes() {
|
|
||||||
// const c = widget.chart()
|
|
||||||
// for( const s of ss.shapes ) {
|
|
||||||
// const type = s.type.toLowerCase().replace(' ','_')
|
|
||||||
// console.log('create type', type)
|
|
||||||
// c.createMultipointShape(s.points, {shape:type})
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -11,28 +11,28 @@
|
|||||||
<v-tooltip text="Up to 1000 equal parts spread across time" location="top">
|
<v-tooltip text="Up to 1000 equal parts spread across time" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-clock-outline" @click="build(order,'DCABuilder')">DCA</v-btn>
|
<v-btn id="DCA-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-clock-outline" @click="build(order,'DCABuilder')">DCA</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Trade a price level" location="top">
|
<v-tooltip text="Trade a price level" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
|
<v-btn id="LimitBuilder-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-ray-vertex" @click="build(order,'LimitBuilder')">Limit</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Trade trends and channels" location="top">
|
<v-tooltip text="Trade trends and channels" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-vector-line" @click="build(order,'DiagonalBuilder')">Diagonal</v-btn>
|
<v-btn id="Diagonal-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-vector-line" @click="build(order,'DiagonalBuilder')">Diagonal</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<v-tooltip text="Up to 10 weighted parts spaced out in time" location="top">
|
<v-tooltip text="Up to 10 weighted parts spaced out in time" location="top">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<span v-bind="props">
|
<span v-bind="props">
|
||||||
<v-btn :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-reorder-vertical" @click="build(order,'DateBuilder')">Dates</v-btn>
|
<v-btn id="Dates-button" :class="order.buy?'green':'red'" variant="text" prepend-icon="mdi-reorder-vertical" @click="build(order,'DateBuilder')">Dates</v-btn>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
@@ -44,6 +44,13 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
<!-- mdi-ray-start-end mdi-vector-polyline -->
|
<!-- mdi-ray-start-end mdi-vector-polyline -->
|
||||||
|
|
||||||
|
<!-- after="newbie"-->
|
||||||
|
<span>{{builders.length}}</span>
|
||||||
|
<one-time-hint name="choose-builder" :activator="hintData.activator"
|
||||||
|
:text="hintData.text" location="top"
|
||||||
|
:when="!builtAny"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +62,7 @@
|
|||||||
import BuilderFactory from "@/components/chart/BuilderFactory.vue";
|
import BuilderFactory from "@/components/chart/BuilderFactory.vue";
|
||||||
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
import {builderFuncs, newBuilder, orderFuncs, useChartOrderStore} from "@/orderbuild.js";
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
import {computed, onUnmounted, onUpdated, watchEffect} from "vue";
|
import {computed, onUnmounted, onUpdated, ref, watchEffect} from "vue";
|
||||||
import {toPrecision} from "@/misc.js";
|
import {toPrecision} from "@/misc.js";
|
||||||
import {useTheme} from "vuetify";
|
import {useTheme} from "vuetify";
|
||||||
import RowBar from "@/components/chart/RowBar.vue";
|
import RowBar from "@/components/chart/RowBar.vue";
|
||||||
@@ -63,6 +70,7 @@ import Color from "color";
|
|||||||
import {newOrder} from "@/blockchain/orderlib.js";
|
import {newOrder} from "@/blockchain/orderlib.js";
|
||||||
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
import OrderAmount from "@/components/chart/OrderAmount.vue";
|
||||||
import {track} from "@/track.js";
|
import {track} from "@/track.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
|
||||||
const props = defineProps(['order'])
|
const props = defineProps(['order'])
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
@@ -75,9 +83,12 @@ const tokenIn = computed(()=>props.order.buy ? co.quoteToken : co.baseToken)
|
|||||||
const tokenOut = computed(()=>props.order.buy ? co.baseToken : co.quoteToken)
|
const tokenOut = computed(()=>props.order.buy ? co.baseToken : co.quoteToken)
|
||||||
|
|
||||||
|
|
||||||
|
const builtAny = ref(false)
|
||||||
|
|
||||||
console.log('order', props.order)
|
console.log('order', props.order)
|
||||||
function build(order, component, options={}) {
|
function build(order, component, options={}) {
|
||||||
track('build', {builder:component})
|
track('build', {builder:component})
|
||||||
|
builtAny.value = true
|
||||||
order.builders.push(newBuilder(component, options))
|
order.builders.push(newBuilder(component, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +198,19 @@ const color = computed(()=>theme.value.colors["on-background"])
|
|||||||
// const lightColorStyle = computed(() => { return {'background-color': lightColor.value} })
|
// const lightColorStyle = computed(() => { return {'background-color': lightColor.value} })
|
||||||
// const faintColorStyle = computed(() => { return {'background-color': faintColor.value} })
|
// const faintColorStyle = computed(() => { return {'background-color': faintColor.value} })
|
||||||
|
|
||||||
|
// Tutorial Hint
|
||||||
|
|
||||||
|
let tutorial = 'limit'
|
||||||
|
|
||||||
|
const _hintData = {
|
||||||
|
'limit': {
|
||||||
|
activator: '#LimitBuilder-button',
|
||||||
|
text: '↓ Try a Limit Ladder ↓'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const hintData = computed(()=>_hintData[tutorial] || _hintData['limit'])
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<one-time-hint name="click-chart" activator="#tv-widget" location="center" :when="builder.lineA===null && !co.drew" text="Click the chart!"/>
|
||||||
</rung-builder>
|
</rung-builder>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -102,6 +103,7 @@ import {allocationText, DLine} from "@/charts/shape.js";
|
|||||||
import {vectorEquals, vectorInterpolate} from "@/vector.js";
|
import {vectorEquals, vectorInterpolate} from "@/vector.js";
|
||||||
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
|
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
|
||||||
import {useStore} from "@/store/store.js";
|
import {useStore} from "@/store/store.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
|
|||||||
@@ -33,10 +33,11 @@
|
|||||||
style="flex: 6em"
|
style="flex: 6em"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="weight">{{ weights.length ? allocationTexts[lowerIndex] : '' }}</td>
|
<td class="weight">{{ weights.length > 1 ? allocationTexts[lowerIndex] : '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<one-time-hint name="click-chart" activator="#tv-widget" location="center" :when="priceA===null" text="Click the chart!"/>
|
||||||
</rung-builder>
|
</rung-builder>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -48,6 +49,7 @@ import {MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js";
|
|||||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
import {allocationText, HLine} from "@/charts/shape.js";
|
import {allocationText, HLine} from "@/charts/shape.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
|
||||||
const s = useStore()
|
const s = useStore()
|
||||||
const os = useOrderStore()
|
const os = useOrderStore()
|
||||||
|
|||||||
@@ -17,15 +17,27 @@
|
|||||||
min="1" :max="MAX_RUNGS"
|
min="1" :max="MAX_RUNGS"
|
||||||
:disabled="rungsDisabled"
|
:disabled="rungsDisabled"
|
||||||
style="width: 6.6em; max-height: 2.5em; height: 2.5em"
|
style="width: 6.6em; max-height: 2.5em; height: 2.5em"
|
||||||
|
id="rungs"
|
||||||
/>
|
/>
|
||||||
<v-switch v-model="breakout" :label="order.buy?'Breakout':'Breakdown'"
|
<one-time-hint name="rungs" activator="#rungs" after="choose-builder"
|
||||||
persistent-hint :color="switchColor" :base-color="switchColor" hide-details direction="vertical"
|
text="↓ Try increasing rungs!" location="top"
|
||||||
density="compact"
|
:when="rungs===1&&endpoints[0]!==null"/>
|
||||||
/>
|
<v-tooltip v-if="builder.breakout!==undefined"
|
||||||
<div class="mx-auto"><span style="font-size: .7em; vertical-align: top"
|
:text="order.buy?'Breakout orders buy above the breakout line':'Breakdown orders sell below the breakdown line'">
|
||||||
:style="builder.breakout?{color:new Color(color).lighten(0.5).string()}:null">
|
<template #activator="{ props }">
|
||||||
{{description}}
|
<div v-bind="props">
|
||||||
</span></div>
|
<v-switch v-model="breakout" :label="order.buy?'Breakout':'Breakdown'"
|
||||||
|
persistent-hint :color="switchColor" :base-color="switchColor" hide-details direction="vertical"
|
||||||
|
density="compact"/>
|
||||||
|
<div class="mx-auto">
|
||||||
|
<span style="font-size: .7em; vertical-align: top"
|
||||||
|
:style="builder.breakout?{color:new Color(color).lighten(0.5).string()}:null">
|
||||||
|
{{ description }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot/>
|
<slot/>
|
||||||
@@ -36,8 +48,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="rungs>1" class="mx-2 d-flex justify-start">
|
<div v-if="rungs>1" class="mx-2 d-flex justify-start">
|
||||||
<div class="d-flex align-center mt-2">
|
<div class="d-flex align-center mt-2">
|
||||||
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="balance100"
|
<div id="balance-slider">
|
||||||
class="no-slider-bg ml-2 mr-4" hide-details/>
|
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="balance100"
|
||||||
|
class="no-slider-bg ml-2 mr-4" hide-details/>
|
||||||
|
</div>
|
||||||
|
<one-time-hint name="balance-slider" activator="#balance-slider" after="rungs"
|
||||||
|
text="↓ Slide the amount balance ↓" location="top"
|
||||||
|
:when="balance100===0"/>
|
||||||
<v-text-field type="number" v-model="balance100" min="-100" max="100"
|
<v-text-field type="number" v-model="balance100" min="-100" max="100"
|
||||||
density="compact" hide-details variant="outlined" label="Balance" step="5"
|
density="compact" hide-details variant="outlined" label="Balance" step="5"
|
||||||
class="balance">
|
class="balance">
|
||||||
@@ -70,6 +87,7 @@ import {
|
|||||||
vectorSub
|
vectorSub
|
||||||
} from "@/vector.js";
|
} from "@/vector.js";
|
||||||
import {logicalXOR} from "@/common.js";
|
import {logicalXOR} from "@/common.js";
|
||||||
|
import OneTimeHint from "@/components/OneTimeHint.vue";
|
||||||
|
|
||||||
const co = useChartOrderStore()
|
const co = useChartOrderStore()
|
||||||
const endpoints = defineModel('modelValue') // 2-item list of points/values
|
const endpoints = defineModel('modelValue') // 2-item list of points/values
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
|
|||||||
const meanRange = ref(1)
|
const meanRange = ref(1)
|
||||||
|
|
||||||
const drawing = ref(false)
|
const drawing = ref(false)
|
||||||
|
const drew = ref(true) // true if at least one of the points has been drawn already
|
||||||
|
|
||||||
function newOrder() {
|
function newOrder() {
|
||||||
const order = newDefaultOrder()
|
const order = newDefaultOrder()
|
||||||
@@ -97,7 +98,7 @@ export const useChartOrderStore = defineStore('chart_orders', () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
chartReady, selectedSymbol, intervalSecs, baseToken, quoteToken, price,
|
||||||
orders, drawing, newOrder, removeOrder, resetOrders, meanRange,
|
orders, drawing, drew, newOrder, removeOrder, resetOrders, meanRange,
|
||||||
showPoolSelection,
|
showPoolSelection,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user