start working on import frontend processing
This commit is contained in:
parent
d2a4c49f7b
commit
03fe3d8eb4
|
@ -22,7 +22,6 @@ eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
lib/
|
lib/
|
||||||
lib64/
|
lib64/
|
||||||
parts/
|
|
||||||
sdist/
|
sdist/
|
||||||
var/
|
var/
|
||||||
wheels/
|
wheels/
|
||||||
|
|
|
@ -5,8 +5,10 @@ from geo_lib.types.feature import GeoFeatureSupported
|
||||||
|
|
||||||
|
|
||||||
def generate_auto_tags(feature: GeoFeatureSupported) -> List[str]:
|
def generate_auto_tags(feature: GeoFeatureSupported) -> List[str]:
|
||||||
tags = []
|
tags = [
|
||||||
tags.append(f'type:{feature.type.value}')
|
f'type:{feature.type.value.lower()}'
|
||||||
|
]
|
||||||
|
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
tags.append(f'year:{now.year}')
|
tags.append(f'year:{now.year}')
|
||||||
tags.append(f'month:{now.strftime("%B")}')
|
tags.append(f'month:{now.strftime("%B")}')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {UserInfo} from "@/assets/js/store-types.ts";
|
import {UserInfo} from "@/assets/js/types/store-types";
|
||||||
import {getUserInfo} from "@/assets/js/auth.js";
|
import {getUserInfo} from "@/assets/js/auth.js";
|
||||||
|
|
||||||
export const authMixin = {
|
export const authMixin = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {createStore} from 'vuex'
|
import {createStore} from 'vuex'
|
||||||
import {UserInfo} from './store-types'
|
import {UserInfo} from './types/store-types'
|
||||||
import {ImportQueueItem} from "@/assets/js/import/import-types";
|
import {ImportQueueItem} from "@/assets/js/types/import-types";
|
||||||
|
|
||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const GeoFeatureTypeStrings = {
|
||||||
|
Point: "Point",
|
||||||
|
LineString: "LineString",
|
||||||
|
Polygon: "Polygon"
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
enum GeoFeatureType {
|
||||||
|
POINT = 'Point',
|
||||||
|
LINESTRING = 'LineString',
|
||||||
|
POLYGON = 'Polygon'
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GeoFeatureProps {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
type: GeoFeatureType;
|
||||||
|
description?: string;
|
||||||
|
tags?: string[];
|
||||||
|
geometry: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GeoFeature {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
type: GeoFeatureType;
|
||||||
|
description?: string;
|
||||||
|
tags: string[] = [];
|
||||||
|
geometry: any[];
|
||||||
|
|
||||||
|
constructor(props: GeoFeatureProps) {
|
||||||
|
this.name = props.name;
|
||||||
|
this.id = props.id;
|
||||||
|
this.type = props.type;
|
||||||
|
this.description = props.description;
|
||||||
|
this.tags = props.tags || [];
|
||||||
|
this.geometry = props.geometry || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GeoPoint extends GeoFeature {
|
||||||
|
type: GeoFeatureType = GeoFeatureType.POINT;
|
||||||
|
geometry: number[];
|
||||||
|
|
||||||
|
constructor(props: GeoFeatureProps) {
|
||||||
|
super({...props, type: GeoFeatureType.POINT});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GeoLineString extends GeoFeature {
|
||||||
|
type: GeoFeatureType = GeoFeatureType.LINESTRING;
|
||||||
|
geometry: number[][];
|
||||||
|
|
||||||
|
constructor(props: GeoFeatureProps) {
|
||||||
|
super({...props, type: GeoFeatureType.LINESTRING});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GeoPolygon extends GeoFeature {
|
||||||
|
type: GeoFeatureType = GeoFeatureType.POLYGON;
|
||||||
|
geometry: number[][][];
|
||||||
|
|
||||||
|
constructor(props: GeoFeatureProps) {
|
||||||
|
super({...props, type: GeoFeatureType.POLYGON});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import {getCookie} from "./auth.js"
|
import {getCookie} from "../auth.js"
|
||||||
|
|
||||||
export class UserInfo {
|
export class UserInfo {
|
||||||
username: String;
|
username: String;
|
|
@ -13,7 +13,7 @@ import {mapState} from "vuex"
|
||||||
import {authMixin} from "@/assets/js/authMixin.js";
|
import {authMixin} from "@/assets/js/authMixin.js";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {IMPORT_QUEUE_LIST_URL} from "@/assets/js/import/url.js";
|
import {IMPORT_QUEUE_LIST_URL} from "@/assets/js/import/url.js";
|
||||||
import {ImportQueueItem} from "@/assets/js/import/import-types.ts"
|
import {ImportQueueItem} from "@/assets/js/types/import-types"
|
||||||
import Importqueue from "@/components/import/parts/importqueue.vue";
|
import Importqueue from "@/components/import/parts/importqueue.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -51,9 +51,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
// async created() {
|
||||||
await this.fetchQueueList()
|
// },
|
||||||
},
|
|
||||||
// async mounted() {
|
// async mounted() {
|
||||||
// },
|
// },
|
||||||
// beforeRouteEnter(to, from, next) {
|
// beforeRouteEnter(to, from, next) {
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
</pre>
|
</pre>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden">
|
||||||
|
<!-- Load the queue to populate it. -->
|
||||||
|
<Importqueue/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -25,6 +30,9 @@ import {mapState} from "vuex";
|
||||||
import {authMixin} from "@/assets/js/authMixin.js";
|
import {authMixin} from "@/assets/js/authMixin.js";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {capitalizeFirstLetter} from "@/assets/js/string.js";
|
import {capitalizeFirstLetter} from "@/assets/js/string.js";
|
||||||
|
import Importqueue from "@/components/import/parts/importqueue.vue";
|
||||||
|
import {GeoFeatureTypeStrings} from "@/assets/js/types/geofeature-strings";
|
||||||
|
import {GeoPoint, GeoLineString, GeoPolygon} from "@/assets/js/types/geofeature-types";
|
||||||
|
|
||||||
// TODO: for each feature, query the DB and check if there is a duplicate. For points that's duplicate coords, for linestrings and polygons that's duplicate points
|
// TODO: for each feature, query the DB and check if there is a duplicate. For points that's duplicate coords, for linestrings and polygons that's duplicate points
|
||||||
// TODO: auto-refresh if still processing
|
// TODO: auto-refresh if still processing
|
||||||
|
@ -33,7 +41,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["userInfo"]),
|
...mapState(["userInfo"]),
|
||||||
},
|
},
|
||||||
components: {},
|
components: {Importqueue},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
msg: "",
|
msg: "",
|
||||||
|
@ -49,7 +57,16 @@ export default {
|
||||||
this.msg = capitalizeFirstLetter(responseMsg).trim(".") + "."
|
this.msg = capitalizeFirstLetter(responseMsg).trim(".") + "."
|
||||||
},
|
},
|
||||||
parseGeoJson(item) {
|
parseGeoJson(item) {
|
||||||
return item
|
switch (item.type) {
|
||||||
|
case GeoFeatureTypeStrings.Point:
|
||||||
|
return new GeoPoint(item);
|
||||||
|
case GeoFeatureTypeStrings.LineString:
|
||||||
|
return new GeoLineString(item);
|
||||||
|
case GeoFeatureTypeStrings.Polygon:
|
||||||
|
return new GeoPolygon(item);
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid feature type: ${item.type}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {authMixin} from "@/assets/js/authMixin.js";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {capitalizeFirstLetter} from "@/assets/js/string.js";
|
import {capitalizeFirstLetter} from "@/assets/js/string.js";
|
||||||
import {IMPORT_QUEUE_LIST_URL} from "@/assets/js/import/url.js";
|
import {IMPORT_QUEUE_LIST_URL} from "@/assets/js/import/url.js";
|
||||||
import {ImportQueueItem} from "@/assets/js/import/import-types.ts"
|
import {ImportQueueItem} from "@/assets/js/types/import-types"
|
||||||
import Importqueue from "@/components/import/parts/importqueue.vue";
|
import Importqueue from "@/components/import/parts/importqueue.vue";
|
||||||
|
|
||||||
// TODO: after import, don't disable the upload, instead add the new item to a table at the button and then prompt the user to continue
|
// TODO: after import, don't disable the upload, instead add the new item to a table at the button and then prompt the user to continue
|
||||||
|
@ -97,7 +97,6 @@ export default {
|
||||||
vm.file = null
|
vm.file = null
|
||||||
vm.disableUpload = false
|
vm.disableUpload = false
|
||||||
vm.uploadMsg = ""
|
vm.uploadMsg = ""
|
||||||
await vm.fetchQueueList()
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button @click="fetchQueueList">Refresh</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>File Name</th>
|
||||||
|
<th>Features</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in importQueue" :key="`item-${index}`">
|
||||||
|
<td>
|
||||||
|
<a :href="`/#/import/process/${item.id}`">{{ item.id }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a :href="`/#/import/process/${item.id}`">{{ item.original_filename }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ item.processing === true ? "processing" : item.feature_count }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button @click="deleteItem(item, index)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {mapState} from "vuex";
|
||||||
|
import {authMixin} from "@/assets/js/authMixin.js";
|
||||||
|
import axios from "axios";
|
||||||
|
import {IMPORT_QUEUE_LIST_URL} from "@/assets/js/import/url.js";
|
||||||
|
import {ImportQueueItem} from "@/assets/js/types/import-types";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(["userInfo", "importQueue"]),
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
mixins: [authMixin],
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchQueueList() {
|
||||||
|
const response = await axios.get(IMPORT_QUEUE_LIST_URL)
|
||||||
|
const ourImportQueue = response.data.data.map((item) => new ImportQueueItem(item))
|
||||||
|
this.$store.commit('importQueue', ourImportQueue)
|
||||||
|
},
|
||||||
|
async deleteItem(item, index) {
|
||||||
|
if (window.confirm(`Delete "${item.original_filename}" (#${item.id})`))
|
||||||
|
try {
|
||||||
|
this.importQueue.splice(index, 1)
|
||||||
|
// TODO: add a message popup when delete is completed
|
||||||
|
const response = await axios.delete('/api/data/item/import/delete/' + item.id, {
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': this.userInfo.csrftoken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!response.data.success) {
|
||||||
|
throw new Error("server reported failure")
|
||||||
|
}
|
||||||
|
await this.fetchQueueList()
|
||||||
|
} catch (error) {
|
||||||
|
alert(`Failed to delete ${item.id}: ${error.message}`)
|
||||||
|
this.importQueue.splice(index, 0, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
await this.fetchQueueList()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
Loading…
Reference in New Issue