made the open data importer its own component
This commit is contained in:
parent
12da77f037
commit
86fd0dcab1
@ -110,8 +110,8 @@ class OpenDataImporter:
|
|||||||
for f in Food.objects.filter(space=self.request.space).filter(name__in=identifier_list).values_list('id', 'name', 'plural_name'):
|
for f in Food.objects.filter(space=self.request.space).filter(name__in=identifier_list).values_list('id', 'name', 'plural_name'):
|
||||||
existing_objects_flat.append(f[1])
|
existing_objects_flat.append(f[1])
|
||||||
existing_objects_flat.append(f[2])
|
existing_objects_flat.append(f[2])
|
||||||
existing_objects['name'] = f
|
existing_objects[f[1]] = f
|
||||||
existing_objects['plural_name'] = f
|
existing_objects[f[2]] = f
|
||||||
|
|
||||||
self._update_slug_cache(Unit, 'unit')
|
self._update_slug_cache(Unit, 'unit')
|
||||||
self._update_slug_cache(FoodPropertyType, 'property')
|
self._update_slug_cache(FoodPropertyType, 'property')
|
||||||
@ -159,7 +159,7 @@ class OpenDataImporter:
|
|||||||
update_field_list = ['open_data_slug', ]
|
update_field_list = ['open_data_slug', ]
|
||||||
update_list.append(Food(id=existing_food_id, open_data_slug=k, ))
|
update_list.append(Food(id=existing_food_id, open_data_slug=k, ))
|
||||||
|
|
||||||
foods = Food.load_bulk(insert_list, None)
|
Food.load_bulk(insert_list, None)
|
||||||
Food.objects.bulk_update(update_list, update_field_list)
|
Food.objects.bulk_update(update_list, update_field_list)
|
||||||
|
|
||||||
self._update_slug_cache(Food, 'food')
|
self._update_slug_cache(Food, 'food')
|
||||||
@ -187,7 +187,7 @@ class OpenDataImporter:
|
|||||||
|
|
||||||
FoodProperty.objects.bulk_create(food_property_list, ignore_conflicts=True, unique_fields=('space', 'food', 'property_type',))
|
FoodProperty.objects.bulk_create(food_property_list, ignore_conflicts=True, unique_fields=('space', 'food', 'property_type',))
|
||||||
Automation.objects.bulk_create(alias_list, ignore_conflicts=True, unique_fields=('space', 'param_1', 'param_2',))
|
Automation.objects.bulk_create(alias_list, ignore_conflicts=True, unique_fields=('space', 'param_1', 'param_2',))
|
||||||
return foods
|
return insert_list + update_list
|
||||||
|
|
||||||
def import_conversion(self):
|
def import_conversion(self):
|
||||||
datatype = 'conversion'
|
datatype = 'conversion'
|
||||||
|
@ -1428,9 +1428,7 @@ class ImportOpenData(APIView):
|
|||||||
return Response(metadata)
|
return Response(metadata)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
# serializer load data ?
|
|
||||||
# TODO validate data
|
# TODO validate data
|
||||||
# TODO add option to handle merging of existing data (merge, override, ignore)
|
|
||||||
print(request.data)
|
print(request.data)
|
||||||
selected_version = request.data['selected_version']
|
selected_version = request.data['selected_version']
|
||||||
selected_datatypes = request.data['selected_datatypes']
|
selected_datatypes = request.data['selected_datatypes']
|
||||||
|
@ -51,14 +51,14 @@
|
|||||||
<td>{{ us.user.username }}</td>
|
<td>{{ us.user.username }}</td>
|
||||||
<td>
|
<td>
|
||||||
<generic-multiselect
|
<generic-multiselect
|
||||||
class="input-group-text m-0 p-0"
|
class="input-group-text m-0 p-0"
|
||||||
@change="us.groups = $event.val; updateUserSpace(us)"
|
@change="us.groups = $event.val; updateUserSpace(us)"
|
||||||
label="name"
|
label="name"
|
||||||
:initial_selection="us.groups"
|
:initial_selection="us.groups"
|
||||||
:model="Models.GROUP"
|
:model="Models.GROUP"
|
||||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||||
:limit="10"
|
:limit="10"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@ -90,14 +90,14 @@
|
|||||||
<td>{{ il.email }}</td>
|
<td>{{ il.email }}</td>
|
||||||
<td>
|
<td>
|
||||||
<generic-multiselect
|
<generic-multiselect
|
||||||
class="input-group-text m-0 p-0"
|
class="input-group-text m-0 p-0"
|
||||||
@change="il.group = $event.val;"
|
@change="il.group = $event.val;"
|
||||||
label="name"
|
label="name"
|
||||||
:initial_single_selection="il.group"
|
:initial_single_selection="il.group"
|
||||||
:model="Models.GROUP"
|
:model="Models.GROUP"
|
||||||
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
|
||||||
:limit="10"
|
:limit="10"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td><input type="date" v-model="il.valid_until" class="form-control"></td>
|
<td><input type="date" v-model="il.valid_until" class="form-control"></td>
|
||||||
@ -164,6 +164,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h4>{{ $t('Open_Data_Import') }}</h4>
|
||||||
|
<open-data-import-component></open-data-import-component>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col col-12">
|
<div class="col col-12">
|
||||||
<h4 class="mt-2"><i class="fas fa-trash"></i> {{ $t('Delete') }}</h4>
|
<h4 class="mt-2"><i class="fas fa-trash"></i> {{ $t('Delete') }}</h4>
|
||||||
@ -198,6 +207,7 @@ import GenericMultiselect from "@/components/GenericMultiselect";
|
|||||||
import GenericModalForm from "@/components/Modals/GenericModalForm";
|
import GenericModalForm from "@/components/Modals/GenericModalForm";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import VueClipboard from 'vue-clipboard2'
|
import VueClipboard from 'vue-clipboard2'
|
||||||
|
import OpenDataImportComponent from "@/components/OpenDataImportComponent.vue";
|
||||||
|
|
||||||
Vue.use(VueClipboard)
|
Vue.use(VueClipboard)
|
||||||
|
|
||||||
@ -206,7 +216,7 @@ Vue.use(BootstrapVue)
|
|||||||
export default {
|
export default {
|
||||||
name: "SpaceManageView",
|
name: "SpaceManageView",
|
||||||
mixins: [ResolveUrlMixin, ToastMixin, ApiMixin],
|
mixins: [ResolveUrlMixin, ToastMixin, ApiMixin],
|
||||||
components: {GenericMultiselect, GenericModalForm},
|
components: {GenericMultiselect, GenericModalForm, OpenDataImportComponent},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
ACTIVE_SPACE_ID: window.ACTIVE_SPACE_ID,
|
ACTIVE_SPACE_ID: window.ACTIVE_SPACE_ID,
|
||||||
@ -239,7 +249,7 @@ export default {
|
|||||||
if (link) {
|
if (link) {
|
||||||
content = localStorage.BASE_PATH + this.resolveDjangoUrl('view_invite', inviteLink.uuid)
|
content = localStorage.BASE_PATH + this.resolveDjangoUrl('view_invite', inviteLink.uuid)
|
||||||
}
|
}
|
||||||
this.$copyText(content)
|
this.$copyText(content)
|
||||||
},
|
},
|
||||||
loadInviteLinks: function () {
|
loadInviteLinks: function () {
|
||||||
let apiFactory = new ApiApiFactory()
|
let apiFactory = new ApiApiFactory()
|
||||||
|
@ -1,47 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div id="app">
|
<div id="app">
|
||||||
Import Component
|
|
||||||
|
|
||||||
<div v-id="metadata !== undefined">
|
<beta-warning></beta-warning>
|
||||||
|
|
||||||
|
<div v-if="metadata !== undefined">
|
||||||
|
{{ $t('Data_Import_Info') }}
|
||||||
|
|
||||||
|
|
||||||
<select class="form-control" v-model="selected_version">
|
<select class="form-control" v-model="selected_version">
|
||||||
<option v-for="v in metadata.versions" v-bind:key="v">{{ v }}</option>
|
<option v-for="v in metadata.versions" v-bind:key="v">{{ v }}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select class="form-control">
|
<b-checkbox v-model="update_existing" class="mt-1">{{ $t('Update_Existing_Data') }}</b-checkbox>
|
||||||
<option>{{$t('Metric')}}</option>
|
<b-checkbox v-model="use_metric" class="mt-1">{{ $t('Use_Metric') }}</b-checkbox>
|
||||||
<option>{{$t('Imperial')}}</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select class="form-control">
|
|
||||||
<option selected>{{$t('Ignore')}}</option>
|
|
||||||
<option>{{$t('Merge')}}</option>
|
|
||||||
<option>{{$t('Replace')}}</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div v-if="selected_version !== undefined">
|
<div v-if="selected_version !== undefined" class="mt-3">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('Datatype') }}</th>
|
<th>{{ $t('Datatype') }}</th>
|
||||||
<th>{{ $t('Number of Objects') }}</th>
|
<th>{{ $t('Number of Objects') }}</th>
|
||||||
|
<th>{{ $t('Imported') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="d in metadata.datatypes" v-bind:key="d">
|
<tr v-for="d in metadata.datatypes" v-bind:key="d">
|
||||||
<td>{{ d }}</td>
|
<td>{{ $t(d.charAt(0).toUpperCase() + d.slice(1)) }}</td>
|
||||||
<td>{{ metadata[selected_version][d] }}</td>
|
<td>{{ metadata[selected_version][d] }}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="import_count !== undefined">{{ import_count[d] }}</template>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button class="btn btn-success" @click="doImport">{{ $t('Import') }}</button>
|
<button class="btn btn-success" @click="doImport">{{ $t('Import') }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="response_data !== undefined">
|
|
||||||
{{response_data}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -53,6 +47,7 @@ import {BootstrapVue} from "bootstrap-vue"
|
|||||||
import "bootstrap-vue/dist/bootstrap-vue.css"
|
import "bootstrap-vue/dist/bootstrap-vue.css"
|
||||||
import {ApiMixin, resolveDjangoUrl, StandardToasts} from "@/utils/utils";
|
import {ApiMixin, resolveDjangoUrl, StandardToasts} from "@/utils/utils";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import BetaWarning from "@/components/BetaWarning.vue";
|
||||||
|
|
||||||
|
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
@ -61,12 +56,14 @@ Vue.use(BootstrapVue)
|
|||||||
export default {
|
export default {
|
||||||
name: "TestView",
|
name: "TestView",
|
||||||
mixins: [ApiMixin],
|
mixins: [ApiMixin],
|
||||||
components: {},
|
components: {BetaWarning},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
metadata: undefined,
|
metadata: undefined,
|
||||||
selected_version: undefined,
|
selected_version: undefined,
|
||||||
response_data: undefined,
|
update_existing: true,
|
||||||
|
use_metric: true,
|
||||||
|
import_count: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -80,12 +77,18 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
doImport: function () {
|
doImport: function () {
|
||||||
axios.post(resolveDjangoUrl('api_import_open_data'), {'selected_version': this.selected_version, 'selected_datatypes': this.metadata.datatypes}).then(r => {
|
axios.post(resolveDjangoUrl('api_import_open_data'), {
|
||||||
|
'selected_version': this.selected_version,
|
||||||
|
'selected_datatypes': this.metadata.datatypes,
|
||||||
|
'update_existing': this.update_existing,
|
||||||
|
'use_metric': this.use_metric,
|
||||||
|
}).then(r => {
|
||||||
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
|
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
|
||||||
|
this.import_count = r.data
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE, err)
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE, err)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
94
vue/src/components/OpenDataImportComponent.vue
Normal file
94
vue/src/components/OpenDataImportComponent.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<beta-warning></beta-warning>
|
||||||
|
|
||||||
|
<div v-if="metadata !== undefined">
|
||||||
|
{{ $t('Data_Import_Info') }}
|
||||||
|
<a href="https://github.com/TandoorRecipes/open-tandoor-data" target="_blank" rel="noreferrer nofollow">{{$t('Learn_More')}}</a>
|
||||||
|
|
||||||
|
|
||||||
|
<select class="form-control" v-model="selected_version">
|
||||||
|
<option v-for="v in metadata.versions" v-bind:key="v">{{ v }}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<b-checkbox v-model="update_existing" class="mt-1">{{ $t('Update_Existing_Data') }}</b-checkbox>
|
||||||
|
<b-checkbox v-model="use_metric" class="mt-1">{{ $t('Use_Metric') }}</b-checkbox>
|
||||||
|
|
||||||
|
|
||||||
|
<div v-if="selected_version !== undefined" class="mt-3">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>{{ $t('Datatype') }}</th>
|
||||||
|
<th>{{ $t('Number of Objects') }}</th>
|
||||||
|
<th>{{ $t('Imported') }}</th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="d in metadata.datatypes" v-bind:key="d">
|
||||||
|
<td>{{ $t(d.charAt(0).toUpperCase() + d.slice(1)) }}</td>
|
||||||
|
<td>{{ metadata[selected_version][d] }}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="import_count !== undefined">{{ import_count[d] }}</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button class="btn btn-success" @click="doImport">{{ $t('Import') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from "vue"
|
||||||
|
import {BootstrapVue} from "bootstrap-vue"
|
||||||
|
|
||||||
|
import "bootstrap-vue/dist/bootstrap-vue.css"
|
||||||
|
import {ApiMixin, resolveDjangoUrl, StandardToasts} from "@/utils/utils";
|
||||||
|
import axios from "axios";
|
||||||
|
import BetaWarning from "@/components/BetaWarning.vue";
|
||||||
|
|
||||||
|
|
||||||
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "OpenDataImportComponent",
|
||||||
|
mixins: [ApiMixin],
|
||||||
|
components: {BetaWarning},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
metadata: undefined,
|
||||||
|
selected_version: undefined,
|
||||||
|
update_existing: true,
|
||||||
|
use_metric: true,
|
||||||
|
import_count: undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$i18n.locale = window.CUSTOM_LOCALE
|
||||||
|
|
||||||
|
axios.get(resolveDjangoUrl('api_import_open_data')).then(r => {
|
||||||
|
this.metadata = r.data
|
||||||
|
}).catch(err => {
|
||||||
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doImport: function () {
|
||||||
|
axios.post(resolveDjangoUrl('api_import_open_data'), {
|
||||||
|
'selected_version': this.selected_version,
|
||||||
|
'selected_datatypes': this.metadata.datatypes,
|
||||||
|
'update_existing': this.update_existing,
|
||||||
|
'use_metric': this.use_metric,
|
||||||
|
}).then(r => {
|
||||||
|
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
|
||||||
|
this.import_count = r.data
|
||||||
|
}).catch(err => {
|
||||||
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE, err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -78,6 +78,13 @@
|
|||||||
"reusable_help_text": "Should the invite link be usable for more than one user.",
|
"reusable_help_text": "Should the invite link be usable for more than one user.",
|
||||||
"open_data_help_text": "The Tandoor Open Data project provides community contributed data for Tandoor. This field is filled automatically when importing it and allows updates in the future.",
|
"open_data_help_text": "The Tandoor Open Data project provides community contributed data for Tandoor. This field is filled automatically when importing it and allows updates in the future.",
|
||||||
"Open_Data_Slug": "Open Data Slug",
|
"Open_Data_Slug": "Open Data Slug",
|
||||||
|
"Open_Data_Import": "Open Data Import",
|
||||||
|
"Data_Import_Info": "Enhance your Space by importing a community curated list of foods, units and more to improve your recipe collection.",
|
||||||
|
"Update_Existing_Data": "Update Existing Data",
|
||||||
|
"Use_Metric": "Use Metric Units",
|
||||||
|
"Learn_More": "Learn More",
|
||||||
|
"Datatype": "Datatype",
|
||||||
|
"Number of Objects": "Number of Objects",
|
||||||
"Add_Step": "Add Step",
|
"Add_Step": "Add Step",
|
||||||
"Keywords": "Keywords",
|
"Keywords": "Keywords",
|
||||||
"Books": "Books",
|
"Books": "Books",
|
||||||
@ -163,6 +170,8 @@
|
|||||||
"merge_title": "Merge {type}",
|
"merge_title": "Merge {type}",
|
||||||
"move_title": "Move {type}",
|
"move_title": "Move {type}",
|
||||||
"Food": "Food",
|
"Food": "Food",
|
||||||
|
"Property": "Property",
|
||||||
|
"Conversion": "Conversion",
|
||||||
"Original_Text": "Original Text",
|
"Original_Text": "Original Text",
|
||||||
"Recipe_Book": "Recipe Book",
|
"Recipe_Book": "Recipe Book",
|
||||||
"del_confirmation_tree": "Are you sure that you want to delete {source} and all of it's children?",
|
"del_confirmation_tree": "Are you sure that you want to delete {source} and all of it's children?",
|
||||||
|
Loading…
Reference in New Issue
Block a user