shape onModel improvements; vline fixes; time entry; couple bugs remain with dca dragging
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import "/public/charting_library/charting_library.js"
|
||||
// import "/public/datafeeds/udf/dist/bundle.js"
|
||||
import "/charting_library/charting_library.js?url"
|
||||
// import "/datafeeds/udf/dist/bundle.js?url"
|
||||
import {onMounted, ref} from "vue";
|
||||
import {initWidget} from "@/charts/chart.js";
|
||||
|
||||
|
||||
@@ -1,19 +1,53 @@
|
||||
<template>
|
||||
<rung-builder name='DCA' :order="order" :builder="builder"
|
||||
v-model:value-a="absTimeA" v-model:value-b="absTimeB" :mode="1" :flip="flipped"
|
||||
v-model:value-a="absTimeA" v-model:value-b="absTimeB"
|
||||
:shape="VLine"
|
||||
:mode="1" :flip="flipped" :orientation="0"
|
||||
:get-model-value="getModelValue" :set-model-value="setModelValue"
|
||||
:get-points-value="getPointsValue"
|
||||
:set-values="setValues" :set-weights="setWeights"
|
||||
:std-width="stdWidth" :build-tranches="buildTranches">
|
||||
|
||||
<!--
|
||||
<v-list style="background-color: inherit">
|
||||
<v-list-item v-for="t in absoluteTimes">{{t}}</v-list-item>
|
||||
</v-list>
|
||||
-->
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<absolute-time-entry v-model="absTimeA"/>
|
||||
</td>
|
||||
<td class="weight">{{ weights.length ? allocationText(weights[0]) : '' }}</td>
|
||||
</tr>
|
||||
<tr v-if="weights.length>2" v-for="i in weights.length-2" class="ml-5">
|
||||
<td class="pl-5">{{ times[1+i] }}</td>
|
||||
<td class="weight">{{ allocationText(weights[1+i]) }}</td>
|
||||
</tr>
|
||||
<tr v-if="weights.length>1">
|
||||
<td>
|
||||
<!--
|
||||
<v-text-field type="number" v-model="lowerPrice" min="0"
|
||||
density="compact" hide-details class="mx-1 my-2" variant="outlined"
|
||||
label="Price"
|
||||
:color="color" :base-color="color"
|
||||
style="flex: 6em"
|
||||
/>
|
||||
-->
|
||||
</td>
|
||||
<td class="weight">{{ allocationText(weights[weights.length-1]) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</rung-builder>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {builderDefaults, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {allocationText, builderDefaults, MIN_EXECUTION_TIME, useChartOrderStore} from "@/orderbuild.js";
|
||||
import {VLine} from "@/charts/shape.js";
|
||||
import {sideColor} from "@/misc.js";
|
||||
import {useTheme} from "vuetify";
|
||||
@@ -22,6 +56,8 @@ import {DISTANT_FUTURE, MAX_FRACTION, newTranche} from "@/blockchain/orderlib.js
|
||||
import RungBuilder from "@/components/chart/RungBuilder.vue";
|
||||
import {computed, ref, watchEffect} from "vue";
|
||||
import {chart, dragging} from "@/charts/chart.js";
|
||||
import AbsoluteTimeEntry from "@/components/AbsoluteTimeEntry.vue";
|
||||
import TimeEntry from "@/components/TimeEntry.vue";
|
||||
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
@@ -50,10 +86,9 @@ builderDefaults(props.builder, {
|
||||
color: defaultColor,
|
||||
})
|
||||
|
||||
const rawTimes = ref([])
|
||||
const times = ref([])
|
||||
const weights = ref([])
|
||||
|
||||
const times = computed(()=>rawTimes.value.map((t)=>Math.round(t)))
|
||||
const endTimes = computed(()=>{
|
||||
if (props.builder.rungs === 1)
|
||||
return DISTANT_FUTURE
|
||||
@@ -63,10 +98,10 @@ const endTimes = computed(()=>{
|
||||
})
|
||||
const absoluteTimes = computed(()=>{
|
||||
// console.log('absoluteTimes', props.builder.relative, times.value)
|
||||
if (!props.builder.relative)
|
||||
// if (!props.builder.relative)
|
||||
return times.value
|
||||
const now = s.clock
|
||||
return times.value.map((t)=>now+t)
|
||||
// const now = s.clock
|
||||
// return times.value.map((t)=>now+t)
|
||||
})
|
||||
|
||||
|
||||
@@ -77,7 +112,7 @@ watchEffect(()=>{
|
||||
const range = chart.getVisibleRange()
|
||||
const width = range.to - range.from
|
||||
const now = s.clock
|
||||
const extra = (Math.max(0,endTime - now) + minWidth.value) / width
|
||||
const extra = (Math.max(0,endTime - now) + stdWidth.value/2) / width
|
||||
// console.log('visrange', range, width, absV)
|
||||
if (range.to < endTime) {
|
||||
// console.log('scrolling')
|
||||
@@ -93,39 +128,38 @@ watchEffect(()=>{
|
||||
const absTimeA = computed({
|
||||
get() {
|
||||
let result = props.builder.timeA
|
||||
if (props.builder.relative)
|
||||
result += s.clock
|
||||
// console.log('absTimeA', result)
|
||||
// if (props.builder.relative)
|
||||
// result += s.clock
|
||||
console.log('get absTimeA', result)
|
||||
return result
|
||||
},
|
||||
set(v) {
|
||||
// console.log('set absTimeA', props.builder.timeA, v)
|
||||
if (props.builder.relative)
|
||||
v -= s.clock
|
||||
console.error('set absTimeA', props.builder.timeA, v)
|
||||
// if (props.builder.relative)
|
||||
// v -= s.clock
|
||||
props.builder.timeA = v
|
||||
// console.log('absTimeA=',props.builder.timeA)
|
||||
scroll()
|
||||
console.log('absTimeA=',props.builder.timeA)
|
||||
}
|
||||
})
|
||||
const absTimeB = computed({
|
||||
get() {
|
||||
let result = props.builder.timeB
|
||||
if (props.builder.relative)
|
||||
result += s.clock
|
||||
// if (props.builder.relative)
|
||||
// result += s.clock
|
||||
// console.log('absTimeB', result)
|
||||
return result
|
||||
},
|
||||
set(v) {
|
||||
// console.log('set absTimeB', props.builder.timeB, v)
|
||||
const absV = v
|
||||
if ( v !== null && props.builder.relative )
|
||||
v -= s.clock
|
||||
console.error('set absTimeB', props.builder.timeB, v)
|
||||
// if ( v !== null && props.builder.relative )
|
||||
// v -= s.clock
|
||||
props.builder.timeB = v
|
||||
const maxA = v - minWidth.value;
|
||||
if (props.builder.timeA > maxA)
|
||||
if (props.builder.timeA > maxA) {
|
||||
console.log('scootching A to', maxA)
|
||||
props.builder.timeA = maxA
|
||||
// console.log('absTimeB=',props.builder.timeB)
|
||||
scroll()
|
||||
}
|
||||
console.log('absTimeB=',props.builder.timeB)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -135,37 +169,6 @@ const flipped = computed(()=>{
|
||||
return a !== null && b !== null && a > b
|
||||
})
|
||||
|
||||
const higherIndex = computed(()=>flipped.value ? 0 : weights.value.length-1)
|
||||
const lowerIndex = computed(()=>!flipped.value ? 0 : weights.value.length-1)
|
||||
const innerIndexes = computed(()=>{
|
||||
const n = times.value.length
|
||||
const f = flipped.value
|
||||
const result = []
|
||||
for (let i=1; i<n-1; i++)
|
||||
result.push(f?i:n-1-i)
|
||||
return result
|
||||
})
|
||||
|
||||
const earlierTime = computed({
|
||||
get() { return !flipped.value ? props.builder.timeA : props.builder.timeB },
|
||||
set(v) {
|
||||
if (!flipped.value)
|
||||
props.builder.timeA = v
|
||||
else
|
||||
props.builder.timeB = v
|
||||
}
|
||||
})
|
||||
|
||||
const laterTime = computed({
|
||||
get() { return !flipped.value ? props.builder.timeA : props.builder.timeB },
|
||||
set(v) {
|
||||
if (!flipped.value)
|
||||
props.builder.timeA = v
|
||||
else
|
||||
props.builder.timeB = v
|
||||
}
|
||||
})
|
||||
|
||||
function buildTranches() {
|
||||
const order = props.order
|
||||
const builder = props.builder
|
||||
@@ -201,7 +204,8 @@ function getPointsValue(points) {
|
||||
|
||||
function setModelValue(model, value) {
|
||||
// console.log('DCA set model value', model, value)
|
||||
const v = value === null ? null : props.builder.relative ? s.clock + Math.round(value) : Math.round(value)
|
||||
// const v = value === null ? null : props.builder.relative ? s.clock + Math.round(value) : Math.round(value)
|
||||
const v = value === null ? null : Math.round(value)
|
||||
if (model.time !== v) {
|
||||
// console.log('DCA do set time', v)
|
||||
model.time = v
|
||||
@@ -209,12 +213,15 @@ function setModelValue(model, value) {
|
||||
}
|
||||
|
||||
function setValues(values) {
|
||||
times.value = values.map((t)=>Math.round(t))
|
||||
/*
|
||||
if (!props.builder.relative)
|
||||
rawTimes.value = values
|
||||
else {
|
||||
const now = s.clock
|
||||
rawTimes.value = values.map((v)=>v-now)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function setWeights(ws) { weights.value = ws }
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Click the chart!
|
||||
</div>
|
||||
<div v-if="rungs>1" class="mx-2 d-flex align-center">
|
||||
<v-slider v-if="rungs>1" direction="vertical" min="-100" max="100" v-model="skew100"
|
||||
<v-slider v-if="rungs>1" :direction="orientation?'vertical':'horizontal'" min="-100" max="100" v-model="skew100"
|
||||
class="no-slider-bg ml-2 mr-4" hide-details/>
|
||||
<v-text-field type="number" v-model="skew100" min="-100" max="100"
|
||||
density="compact" hide-details variant="outlined" label="Skew" step="5"
|
||||
@@ -41,7 +41,7 @@ import {useTheme} from "vuetify";
|
||||
import {linspace, sideColor} from "@/misc.js";
|
||||
import {computed, onUnmounted, watchEffect} from "vue";
|
||||
import Color from "color";
|
||||
import {cancelDrawing, chart} from "@/charts/chart.js";
|
||||
import {cancelDrawing} from "@/charts/chart.js";
|
||||
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
@@ -57,6 +57,7 @@ const props = defineProps({
|
||||
shape: Function, // shape() -> Shape
|
||||
mode: { type: Number, default: 0 }, // rung addition mode: 0 = split, 1 = extend
|
||||
flip: { type: Boolean, default: false }, // if true, the skew slider is flipped upside-down
|
||||
orientation: { type: Number, default: 1 }, // 0 = horizontal slider, 1 = vertical
|
||||
getModelValue: Function, // getModelValue(model) -> value
|
||||
setModelValue: Function, // setModelValue(model,value) -> void
|
||||
getPointsValue: Function, // getValueFromPoints(points) -> value
|
||||
@@ -89,6 +90,7 @@ const rungs = computed({
|
||||
props.builder.rungs = 1
|
||||
return
|
||||
}
|
||||
const prevR = props.builder.rungs
|
||||
r = Number(r)
|
||||
props.builder.rungs = r
|
||||
const b = valueB.value
|
||||
@@ -115,8 +117,10 @@ const rungs = computed({
|
||||
}
|
||||
else {
|
||||
// from multi to multi
|
||||
if (props.mode===1)
|
||||
valueB.value = valueA.value + props.stdWidth * (r-1)
|
||||
if (props.mode===1) {
|
||||
const width = (valueB.value - valueA.value) / (prevR-1)
|
||||
valueB.value = valueA.value + width * (r-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -182,82 +186,62 @@ function createShape(value, model, onModel, onDelete) {
|
||||
}
|
||||
|
||||
|
||||
function translateOnDrag(shape) {
|
||||
const oldOnPoints = shape.onPoints
|
||||
shape.onPoints = function (points) {
|
||||
function translateOnModel(shape) {
|
||||
const oldOnModel = shape.onModel
|
||||
shape.onModel = function (model, oldModel) {
|
||||
oldOnModel.call(this, ...arguments)
|
||||
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
|
||||
if (!this.beingDragged()) {
|
||||
oldOnPoints.call(this, points)
|
||||
oldOnModel.call(this, ...arguments)
|
||||
return
|
||||
}
|
||||
const prev = props.getModelValue(this.model)
|
||||
oldOnPoints.call(this, points)
|
||||
const prev = props.getModelValue(oldModel)
|
||||
const cur = props.getModelValue(this.model)
|
||||
const delta = cur - prev
|
||||
// console.log('delta', points, shape.ourPoints, prev, cur, delta)
|
||||
// console.log('delta', shape.id, prev, cur, delta)
|
||||
if (delta !== 0) {
|
||||
valueA.value += delta
|
||||
valueB.value += delta
|
||||
if (rungs.value > 1)
|
||||
valueB.value += delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function translateOnDrag(shape) {
|
||||
// const oldOnPoints = shape.onPoints
|
||||
// shape.onPoints = function (points) {
|
||||
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
|
||||
// if (!this.beingDragged()) {
|
||||
// oldOnPoints.call(this, points)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // todo vectorize
|
||||
// const prev = props.getPointsValue(shape.ourPoints)
|
||||
// const cur = props.getPointsValue(points)
|
||||
// const delta = cur - prev
|
||||
// console.log('delta', points, shape.ourPoints, prev, cur, delta)
|
||||
// if (delta !== 0) {
|
||||
// valueA.value += delta
|
||||
// valueB.value += delta
|
||||
// }
|
||||
// oldOnPoints.call(this, points)
|
||||
// }
|
||||
// }
|
||||
|
||||
function setModelColor(model) {
|
||||
if (model.color && model.color !== color.value)
|
||||
color.value = model.color
|
||||
}
|
||||
|
||||
const shapeA = createShape(valueA.value, {color: defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
if (value!==null && value!==undefined)
|
||||
if (value !== valueA.value)
|
||||
valueA.value = value;
|
||||
if (model.color)
|
||||
color.value = model.color
|
||||
setModelColor(model)
|
||||
},
|
||||
deleteSelf)
|
||||
|
||||
if (props.mode===1)
|
||||
translateOnDrag(shapeA)
|
||||
translateOnModel(shapeA)
|
||||
|
||||
const shapeB = createShape(valueB.value, {color:defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
if (value!==null && value!==undefined)
|
||||
if (value !== valueB.value)
|
||||
valueB.value = value;
|
||||
if (model.color)
|
||||
color.value = model.color
|
||||
setModelColor(model)
|
||||
},
|
||||
deleteSelf)
|
||||
|
||||
function interiorOnModel(model) {
|
||||
if (model.color)
|
||||
color.value = model.color
|
||||
setModelColor(model)
|
||||
}
|
||||
|
||||
let interiorShapes = []
|
||||
|
||||
function createInteriorShape(index) {
|
||||
const shape = new props.shape(makeModel(index), interiorOnModel, deleteSelf)
|
||||
translateOnDrag(shape)
|
||||
translateOnModel(shape)
|
||||
interiorShapes.push(shape)
|
||||
}
|
||||
|
||||
@@ -388,6 +372,9 @@ if (!valueA.value)
|
||||
:deep(.v-slider.v-input--vertical > .v-input__control) {
|
||||
min-height: 5em !important;
|
||||
}
|
||||
:deep(.v-slider.v-input--horizontal > .v-input__control) {
|
||||
min-width: 5em !important;
|
||||
}
|
||||
:deep(.v-slider.no-slider-bg .v-slider-track__fill) {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user