Skip to content

Commit

Permalink
Make type selection a modal
Browse files Browse the repository at this point in the history
  • Loading branch information
ingalls committed Sep 5, 2024
1 parent bc42c15 commit 3e0edff
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 118 deletions.
109 changes: 5 additions & 104 deletions api/web/src/components/CloudTAK/Map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -240,110 +240,9 @@
width: 380px;
'
>
<div
class='btn-group'
role='group'
>
<input
id='point-default'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='drawModePoint === "u-d-p"'
@click='drawModePoint = "u-d-p"'
>
<label
v-tooltip='"Custom Point"'
for='point-default'
type='button'
class='btn'
><IconPoint
title='Point Icon'
:size='40'
:stroke='1'
/></label>

<input
id='point-unknown'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='drawModePoint === "a-u-G"'
@click='drawModePoint = "a-u-G"'
>
<label
v-tooltip='"Unknown Point"'
for='point-unknown'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-u-G.png'
></label>

<input
id='point-friendly'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='drawModePoint === "a-f-G"'
@click='drawModePoint = "a-f-G"'
>
<label
v-tooltip='"Friendly Point"'
for='point-friendly'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-f-G.png'
></label>

<input
id='point-hostile'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='drawModePoint === "a-h-G"'
@click='drawModePoint = "a-h-G"'
>
<label
v-tooltip='"Hostile Point"'
for='point-hostile'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-h-G.png'
></label>

<input
id='point-neutral'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='drawModePoint === "a-n-G"'
@click='drawModePoint = "a-n-G"'
>
<label
v-tooltip='"Neutral Point"'
for='point-neutral'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-n-G.png'
></label>
</div>
<CoordinateType
v-model='drawModePoint'
/>
</div>

<div
Expand Down Expand Up @@ -531,6 +430,7 @@
import WarnChannels from './util/WarnChannels.vue';
import Status from '../util/Status.vue';
import CoordInput from './CoordInput.vue';
import CoordinateType from './util/CoordinateType.vue';
import { std, stdurl } from '/src/std.ts';
import CloudTAKFeatView from './FeatView.vue';
import {
Expand Down Expand Up @@ -1066,6 +966,7 @@ export default {
Status,
CoordInput,
WarnChannels,
CoordinateType,
SideMenu,
Loading,
SelectFeats,
Expand Down
10 changes: 7 additions & 3 deletions api/web/src/components/CloudTAK/util/Coordinate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,14 @@ export default {
} else {
return `${this.modelValue[1]}, ${this.modelValue[0]}`;
}
} else if (this.mode === 'dms') {
return `${this.asDMS(this.modelValue[1])}, ${this.asDMS(this.modelValue[0])}`;
} else if (this.mode === 'mgrs') {
return this.asMGRS();
} else if (this.mode === 'utm') {
return this.asUTM(this.modelValue[1], this.modelValue[0]);
}
else if (this.mode === 'dms') return `${this.asDMS(this.modelValue[1])}, ${this.asDMS(this.modelValue[0])}`;
else if (this.mode === 'mgrs') return this.asMGRS();
else if (this.mode === 'utm') return this.asUTM(this.modelValue[1], this.modelValue[0]);
return 'UNKNOWN'
}
},
Expand Down
137 changes: 137 additions & 0 deletions api/web/src/components/CloudTAK/util/CoordinateType.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<template>
<div
class='btn-group'
role='group'
>
<input
id='point-default'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='mode === "u-d-p"'
@click='mode = "u-d-p"'
>
<label
v-tooltip='"Custom Point"'
for='point-default'
type='button'
class='btn'
><IconPoint
title='Point Icon'
:size='40'
:stroke='1'
/></label>

<input
id='point-unknown'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='mode === "a-u-G"'
@click='mode = "a-u-G"'
>
<label
v-tooltip='"Unknown Point"'
for='point-unknown'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-u-G.png'
></label>

<input
id='point-friendly'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='mode === "a-f-G"'
@click='mode = "a-f-G"'
>
<label
v-tooltip='"Friendly Point"'
for='point-friendly'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-f-G.png'
></label>

<input
id='point-hostile'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='mode === "a-h-G"'
@click='mode = "a-h-G"'
>
<label
v-tooltip='"Hostile Point"'
for='point-hostile'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-h-G.png'
></label>

<input
id='point-neutral'
type='radio'
class='btn-check'
name='point-type'
autocomplete='off'
:checked='mode === "a-n-G"'
@click='mode = "a-n-G"'
>
<label
v-tooltip='"Neutral Point"'
for='point-neutral'
type='button'
class='btn'
><img
width='40'
height='40'
src='/pngs/a-n-G.png'
></label>
</div>
</template>

<script>
import {
IconPoint
} from '@tabler/icons-vue';
export default {
name: 'CoordinateType',
props: {
modelValue: {
type: String,
required: true,
}
},
emits: [
'update:modelValue',
],
data: function() {
return {
mode: this.modelValue || 'u-d-p'
}
},
watch: {
mode: function() {
this.$emit('update:modelValue', this.mode);
}
},
components: {
IconPoint
}
}
</script>
11 changes: 5 additions & 6 deletions api/web/src/stores/cots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,18 +413,17 @@ export const useCOTStore = defineStore('cots', {

if (is_mission_cot) return;

const exists = this.cots.get(feat.id);
let exists = this.cots.get(feat.id);
if (exists) {
exists.update(feat)

// TODO condition update depending on diff results
this.pending.set(String(feat.id), exists);
await exists.save();
} else {
this.pending.set(String(feat.id), new COT(feat));
}

if (feat.properties && feat.properties.archived) {
await std('/api/profile/feature', { method: 'PUT', body: feat })
const cot = new COT(feat);
this.pending.set(String(feat.id), cot);
await cot.save();
}
}
}
Expand Down
33 changes: 28 additions & 5 deletions api/web/src/stores/cots/cot.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { std } from '../../std.ts';
import { bbox } from '@turf/bbox'
import { useMapStore } from '../map.ts';
import pointOnFeature from '@turf/point-on-feature';
Expand Down Expand Up @@ -34,10 +35,10 @@ export default class COT implements Feature {
geometry: Feature["geometry"];

constructor(feat: Feature) {
this.id = feat.id;
this.type = feat.type;
this.path = feat.path;
this.properties = feat["properties"];
this.id = feat.id || crypto.randomUUID();
this.type = feat.type || 'Feature';
this.path = feat.path || '/';
this.properties = feat["properties"] || {};
this.geometry = feat["geometry"];
}

Expand All @@ -61,6 +62,28 @@ export default class COT implements Feature {
return changed;
}

/**
* Attempt to save the CoT to the database if necessary
*/
async save(): Promise<void> {
if (this.properties.archived) {
await std('/api/profile/feature', {
method: 'PUT',
body: this.as_feature()
})
}
}

as_feature(): GeoJSONFeature<GeoJSONGeometry, Record<string, unknown>> {
return {
id: this.id,
type: this.type,
path: this.path,
properties: this.properties,
geometry: this.geometry
}
}

/**
* The slimmer we can get the Features, the better
* This returns the minium feature we need to actually style the COT in the vector tiles
Expand Down Expand Up @@ -88,7 +111,7 @@ export default class COT implements Feature {
}

bounds(): GeoJSONBBox {
return bbox(this.geometry)
return bbox(this.geometry)
}

/**
Expand Down

0 comments on commit 3e0edff

Please sign in to comment.