добавление точки старта

This commit is contained in:
Kseninia Mikhaylova 2024-05-22 14:20:38 +03:00
parent d3cc7b11c2
commit 978800bfae
4 changed files with 239 additions and 166 deletions

View File

@ -1,39 +1,4 @@
[ [
{
"label": "annotations",
"importPath": "__future__",
"description": "__future__",
"isExtraImport": true,
"detail": "__future__",
"documentation": {}
},
{
"label": "os",
"kind": 6,
"isExtraImport": true,
"importPath": "os",
"description": "os",
"detail": "os",
"documentation": {}
},
{
"label": "site",
"kind": 6,
"isExtraImport": true,
"importPath": "site",
"description": "site",
"detail": "site",
"documentation": {}
},
{
"label": "sys",
"kind": 6,
"isExtraImport": true,
"importPath": "sys",
"description": "sys",
"detail": "sys",
"documentation": {}
},
{ {
"label": "json", "label": "json",
"kind": 6, "kind": 6,
@ -132,6 +97,15 @@
"detail": "gyp.common", "detail": "gyp.common",
"documentation": {} "documentation": {}
}, },
{
"label": "os",
"kind": 6,
"isExtraImport": true,
"importPath": "os",
"description": "os",
"detail": "os",
"documentation": {}
},
{ {
"label": "posixpath", "label": "posixpath",
"kind": 6, "kind": 6,
@ -275,6 +249,15 @@
"detail": "code", "detail": "code",
"documentation": {} "documentation": {}
}, },
{
"label": "sys",
"kind": 6,
"isExtraImport": true,
"importPath": "sys",
"description": "sys",
"detail": "sys",
"documentation": {}
},
{ {
"label": "hashlib", "label": "hashlib",
"kind": 6, "kind": 6,
@ -1534,6 +1517,78 @@
"detail": "time", "detail": "time",
"documentation": {} "documentation": {}
}, },
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{ {
"label": "admin", "label": "admin",
"importPath": "django.contrib", "importPath": "django.contrib",
@ -1558,14 +1613,6 @@
"detail": "django.apps", "detail": "django.apps",
"documentation": {} "documentation": {}
}, },
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{ {
"label": "routers", "label": "routers",
"importPath": "rest_framework", "importPath": "rest_framework",
@ -1745,87 +1792,6 @@
"detail": "django.core.wsgi", "detail": "django.core.wsgi",
"documentation": {} "documentation": {}
}, },
{
"label": "bin_dir",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "bin_dir = os.path.dirname(abs_file)\nbase = bin_dir[: -len(\"bin\") - 1] # strip away the bin part from the __file__, plus the path separator\n# prepend bin to PATH (this file is inside the bin directory)\nos.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"interactive-table-py3.10\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "base",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "base = bin_dir[: -len(\"bin\") - 1] # strip away the bin part from the __file__, plus the path separator\n# prepend bin to PATH (this file is inside the bin directory)\nos.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"interactive-table-py3.10\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path.decode(\"utf-8\") if \"\" else path)",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "os.environ[\"PATH\"]",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "os.environ[\"PATH\"] = os.pathsep.join([bin_dir, *os.environ.get(\"PATH\", \"\").split(os.pathsep)])\nos.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"interactive-table-py3.10\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path.decode(\"utf-8\") if \"\" else path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "os.environ[\"VIRTUAL_ENV\"]",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "os.environ[\"VIRTUAL_ENV\"] = base # virtual env is right above bin directory\nos.environ[\"VIRTUAL_ENV_PROMPT\"] = \"interactive-table-py3.10\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path.decode(\"utf-8\") if \"\" else path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "os.environ[\"VIRTUAL_ENV_PROMPT\"]",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "os.environ[\"VIRTUAL_ENV_PROMPT\"] = \"interactive-table-py3.10\" or os.path.basename(base) # noqa: SIM222\n# add the virtual environments libraries to the host python import mechanism\nprev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path.decode(\"utf-8\") if \"\" else path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "prev_length",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "prev_length = len(sys.path)\nfor lib in \"../lib/python3.10/site-packages\".split(os.pathsep):\n path = os.path.realpath(os.path.join(bin_dir, lib))\n site.addsitedir(path.decode(\"utf-8\") if \"\" else path)\nsys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "sys.path[:]",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]\nsys.real_prefix = sys.prefix\nsys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "sys.real_prefix",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "sys.real_prefix = sys.prefix\nsys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{
"label": "sys.prefix",
"kind": 5,
"importPath": ".venv.bin.activate_this",
"description": ".venv.bin.activate_this",
"peekOfCode": "sys.prefix = base",
"detail": ".venv.bin.activate_this",
"documentation": {}
},
{ {
"label": "_Known", "label": "_Known",
"kind": 6, "kind": 6,
@ -8315,6 +8281,42 @@
"detail": "admin_front.node_modules.node-gyp.gyp.test_gyp", "detail": "admin_front.node_modules.node-gyp.gyp.test_gyp",
"documentation": {} "documentation": {}
}, },
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0001_initial",
"description": "back.api.migrations.0001_initial",
"peekOfCode": "class Migration(migrations.Migration):\n initial = True\n dependencies = [\n ]\n operations = [\n migrations.CreateModel(\n name='Floorplan',\n fields=[\n ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n ('title', models.CharField(max_length=200)),",
"detail": "back.api.migrations.0001_initial",
"documentation": {}
},
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths",
"description": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0001_initial'),\n ]\n operations = [\n migrations.AddField(\n model_name='floorplan',\n name='d_border',\n field=models.IntegerField(default=1),\n preserve_default=False,",
"detail": "back.api.migrations.0002_floorplan_d_border_floorplan_d_size_floorplan_paths",
"documentation": {}
},
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0003_alter_floorplan_paths",
"description": "back.api.migrations.0003_alter_floorplan_paths",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0002_floorplan_d_border_floorplan_d_size_floorplan_paths'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='paths',\n field=models.TextField(),\n ),",
"detail": "back.api.migrations.0003_alter_floorplan_paths",
"documentation": {}
},
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size",
"description": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0003_alter_floorplan_paths'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='d_border',\n field=models.IntegerField(blank=True, null=True),\n ),",
"detail": "back.api.migrations.0004_alter_floorplan_d_border_alter_floorplan_d_size",
"documentation": {}
},
{ {
"label": "ApiConfig", "label": "ApiConfig",
"kind": 6, "kind": 6,
@ -8428,7 +8430,7 @@
"kind": 6, "kind": 6,
"importPath": "back.api.views", "importPath": "back.api.views",
"description": "back.api.views", "description": "back.api.views",
"peekOfCode": "class FloorplanView(APIView):\n parser_classes = (MultiPartParser,)\n def post(self, request):\n try:\n file = request.FILES[\"demo\"]\n logger.info(file.__dict__)\n res = parse_image(read_image(file.read()))\n serializer = FloorplanSerializer(\n data={\n \"title\": file.name,", "peekOfCode": "class FloorplanView(APIView):\n parser_classes = (\n MultiPartParser,\n JSONParser,\n )\n def post(self, request):\n try:\n file = request.FILES[\"demo\"]\n logger.info(file.__dict__)\n res = parse_image(read_image(file.read()))",
"detail": "back.api.views", "detail": "back.api.views",
"documentation": {} "documentation": {}
}, },

View File

@ -5,14 +5,20 @@ import * as d3 from "d3";
const point_array = useState<number[][] | undefined>('point_array', () => undefined) const point_array = useState<number[][] | undefined>('point_array', () => undefined)
const chunk_size = useState<number>('chunk_size', () => 8) const chunk_size = useState<number>('chunk_size', () => 8)
const threshold = useState<number>('threshold', () => 20) const threshold = useState<number>('threshold', () => 20)
const grid_redraw = useState<boolean>('grid_redraw', () => false)
const active_point = useState<{ x: number, y: number } | undefined>('active_point', () => undefined)
const target_points = useState<{ x: number, y: number, type: string }[]>('target_points', () => [])
const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>() const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>()
const props = defineProps(['cw', 'ch']) const props = defineProps(['cw', 'ch'])
const d3svg = ref() const d3svg = ref()
const setActivePoint = (item: { x: number, y: number }) => {
active_point.value = { x: item.x, y: item.y }
}
const sampling_data = () => { const sampling_data = () => {
grid_redraw.value = true
const points = point_array.value const points = point_array.value
const chunk = chunk_size.value const chunk = chunk_size.value
if (!points) return if (!points) return
@ -28,6 +34,7 @@ const sampling_data = () => {
return el.filter(e => e > 0).length > threshold.value ? 1 : 0 return el.filter(e => e > 0).length > threshold.value ? 1 : 0
}) })
}); });
const res: any[] = [] const res: any[] = []
prepared_array.forEach((line, indexY) => { prepared_array.forEach((line, indexY) => {
line.forEach((point, indexX) => { line.forEach((point, indexX) => {
@ -48,33 +55,46 @@ const sampling_data = () => {
// svg.selectAll("path").remove(); // svg.selectAll("path").remove();
const path_elements = svg.selectAll("path") const path_elements = svg.selectAll("path")
paths_array.value.forEach((element, i) => { paths_array.value.forEach(async (element, i) => {
if (!d3.select(path_elements.nodes()[i]).empty()) { let _class = '';
console.log(`update ${i}`) if (element.unwalkable) {
d3.select(path_elements.nodes()[i]) _class += ' unwalkable'
.transition()
.duration(300)
.attr('d', element.path)
.attr('class', element.unwalkable ? 'unwalkable' : 'walkable')
} else { } else {
console.log(`add ${i}`) _class += ' walkable'
}
if (target_points.value.find(el => el.x == element.x && el.y === element.y)) {
_class += ' active'
}
const clickFunk = () => setActivePoint({ x: element.x, y: element.y })
if (path_elements.nodes()[i]) {
// console.log(`update ${i}`)
d3.select(path_elements.nodes()[i])
// .transition()
// .duration(300)
.attr('d', element.path)
.attr('class', _class)
.on('click', clickFunk)
} else {
// console.log(`add${i}`)
svg.append("path") svg.append("path")
.attr('d', element.path) .attr('d', element.path)
.attr('class', element.unwalkable ? 'unwalkable' : 'walkable') .attr('class', _class)
.on('click', clickFunk)
} }
}); });
console.timeEnd('redraw D3') console.timeEnd('redraw D3')
grid_redraw.value = false
} }
watch(point_array, () => { watch(point_array, () => {
console.log('point_array')
sampling_data() sampling_data()
}) }, { deep: true })
watch(target_points, () => {
sampling_data()
}, { deep: true })
watch(chunk_size, () => { watch(chunk_size, () => {
console.log('chunk size')
sampling_data() sampling_data()
}) })
watch(threshold, () => { watch(threshold, () => {
console.log('threshold')
sampling_data() sampling_data()
}) })
onMounted(() => { onMounted(() => {
@ -83,15 +103,6 @@ onMounted(() => {
</script> </script>
<template> <template>
<div> <div>
<svg :width="props.cw" :height="props.ch" v-if="false">
<path v-for="item in paths_array" :d="item.path" :class="[
{ 'unwalkable': item.unwalkable },
// { 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) },
// { 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) },
// { 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) },
]">
</path>
</svg>
<svg :width="props.cw" :height="props.ch" ref="d3svg" id="d3svg"></svg> <svg :width="props.cw" :height="props.ch" ref="d3svg" id="d3svg"></svg>
</div> </div>
</template> </template>
@ -102,10 +113,6 @@ svg path {
stroke: rgba(70, 70, 0, 0.1); stroke: rgba(70, 70, 0, 0.1);
} }
svg path:hover {
fill: red
}
svg path.unwalkable { svg path.unwalkable {
fill: rgba(70, 70, 0, 0.5); fill: rgba(70, 70, 0, 0.5);
} }
@ -114,11 +121,16 @@ svg path.endPoint {
fill: blue; fill: blue;
} }
svg path.startPoint { svg path.active {
fill: lawngreen; fill: lawngreen;
} }
svg path.pathPoint { svg path.active {
fill: gold; /* fill: gold; */
}
svg path:hover {
fill: rgba(255, 0, 0, 0.5);
} }
</style> </style>

View File

@ -1,12 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FileUploadUploadEvent } from '~/node_modules/primevue/fileupload/FileUpload.d.ts' import type { FileUploadUploadEvent } from '~/node_modules/primevue/fileupload/FileUpload.d.ts'
import PF, { Grid } from 'pathfinding' import { Grid } from 'pathfinding'
import { chunks } from '~/helpers';
const config = useRuntimeConfig() const config = useRuntimeConfig()
const point_array = useState('point_array', () => [[]]) const point_array = useState('point_array', () => [[]])
const chunk_size = useState('chunk_size', () => 8) const chunk_size = useState('chunk_size', () => 8)
const threshold = useState('threshold', () => 20) const threshold = useState('threshold', () => 20)
const grid_redraw = useState<boolean>('grid_redraw', () => false)
const active_point = useState<{ x: number, y: number } | undefined>('active_point', () => undefined)
const target_points = useState<{ x: number, y: number, type: string }[]>('target_points', () => [])
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
@ -27,6 +29,8 @@ const title = ref()
const dataToState = (data: any) => { const dataToState = (data: any) => {
point_array.value = data.np_field point_array.value = data.np_field
title.value = data.title title.value = data.title
if (data.d_size) chunk_size.value = data.d_size
if (data.d_border) threshold.value = data.d_border
} }
const onUpload = (event: FileUploadUploadEvent) => { const onUpload = (event: FileUploadUploadEvent) => {
@ -84,6 +88,7 @@ const updateValues = async () => {
const res = await fetch(`${config.public.apiBase}/api/floorplan/${selectFile.value}`, { const res = await fetch(`${config.public.apiBase}/api/floorplan/${selectFile.value}`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Accept': 'application/json',
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
@ -94,9 +99,36 @@ const updateValues = async () => {
}) })
const data = await res.json() const data = await res.json()
} }
const target_array = ref<{ type: string, title: string, points?: { x: number, y: number } }[]>([])
const target_type = ref()
const addTargetType = (name: string) => {
target_type.value = name
}
onMounted(async () => { onMounted(async () => {
await loadFiles() await loadFiles()
}) })
watch(grid_redraw, () => {
loading.value = grid_redraw.value
})
watch(active_point, () => {
if (target_type.value === 'start') {
if (!active_point.value) return
const t_index = target_array.value.findIndex(el => el.type == 'start')
if (t_index !== -1) target_array.value.splice(t_index, 1)
const t = ({ type: 'start', title: 'home', points: active_point.value })
const t_state_index = target_points.value.findIndex(el => el.type == 'start')
if (t_state_index !== -1) target_points.value.splice(t_state_index, 1)
const t_state = ({ type: 'start', x: active_point.value.x, y: active_point.value.y })
target_array.value.push(t)
target_points.value.push(t_state)
}
})
</script> </script>
<template> <template>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
@ -105,7 +137,7 @@ onMounted(async () => {
<Dropdown v-model="selectFile" placeholder="Выберите файл" :options="files" optionLabel="title" <Dropdown v-model="selectFile" placeholder="Выберите файл" :options="files" optionLabel="title"
optionValue="id" :loading="loadingFile" :disabled="!files.length || loadingFile" optionValue="id" :loading="loadingFile" :disabled="!files.length || loadingFile"
@change="selectFileEvent" /> @change="selectFileEvent" />
<Button @click="fileBtnClick()"> <Button @click="fileBtnClick()" :disabled="loadingFile">
<span style="display: contents;" v-if="isBlockOpen('upload_file')"> <span style="display: contents;" v-if="isBlockOpen('upload_file')">
Выбрать план из загруженных Выбрать план из загруженных
</span> </span>
@ -121,7 +153,9 @@ onMounted(async () => {
:disabled="loading" /> :disabled="loading" />
</Panel> </Panel>
<Panel header="Данные для работы"> <Panel header="Данные для координатной сетки">
<p>Рекомендуем использовать сетку с наиболее крупными ячейками</p>
<Divider />
<div class="flex align-middle items-end gap-2"> <div class="flex align-middle items-end gap-2">
<div class="flex flex-col"> <div class="flex flex-col">
<label for="title">Название</label> <label for="title">Название</label>
@ -129,17 +163,40 @@ onMounted(async () => {
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<label for="chunk">Значение дискретизации</label> <label for="chunk">Значение дискретизации</label>
<InputNumber id="chunk" type="text" showButtons :min="0" :max="50" v-model="chunk_size" /> <InputNumber id="chunk" type="text" showButtons :min="8" :max="50" v-model="chunk_size" />
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<label for="threshold">Пороговое значение</label> <label for="threshold">Пороговое значение</label>
<InputNumber id="threshold" type="text" showButtons :min="0" :max="chunk_size * chunk_size" <InputNumber id="threshold" showButtons :min="0" :max="chunk_size * chunk_size" :disabled="loading"
v-model="threshold" /> v-model="threshold" />
</div> </div>
<Button @click="updateValues">Сохранить данные</Button> <Button @click="updateValues">Сохранить данные</Button>
</div> </div>
</Panel> </Panel>
<Panel header="Данные о помещениях">
<div class="flex gap-2">
<div class="flex flex-col gap-2">
<Button @click="addTargetType('start')">{{ !target_array.filter(el => el.type == 'start').length ?
`Добавить` : 'Изменить' }}
точку старта</Button>
<Button @click="addTargetType('cabinet')">Добавить точку входа в кабинет</Button>
</div>
<div class="flex flex-col">
<span v-if="active_point">
{{ active_point }}
</span>
<ul>
<li v-for="item in target_array">
{{ item.title }}
{{ item.type }}
{{ item.points }}
</li>
</ul>
</div>
</div>
</Panel>
<Panel :header="loading ? `Идет отрисовка` : `Обработанный план здания`"> <Panel :header="loading ? `Идет отрисовка` : `Обработанный план здания`">
<div style=" max-width: 100%; overflow: auto; position: relative;"> <div style=" max-width: 100%; overflow: auto; position: relative;">
<FloorplanCanvas :cw="cw" :ch="ch" /> <FloorplanCanvas :cw="cw" :ch="ch" />

View File

@ -30,7 +30,10 @@ class Products(APIView):
class FloorplanView(APIView): class FloorplanView(APIView):
parser_classes = (MultiPartParser,) parser_classes = (
MultiPartParser,
JSONParser,
)
def post(self, request): def post(self, request):
try: try:
@ -84,10 +87,9 @@ class FloorplanView(APIView):
if id is not None: if id is not None:
item = Floorplan.objects.get(id=id) item = Floorplan.objects.get(id=id)
serializer = FloorplanSerializer(item, data=request.data, partial=True) serializer = FloorplanSerializer(item, data=request.data, partial=True)
data = serializer.data
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return JsonResponse(status=201) return JsonResponse(serializer.data, status=201)
else: else:
logger.info(serializer.errors) logger.info(serializer.errors)
else: else: