import app view refactor

This commit is contained in:
Kaibu 2022-04-23 03:02:46 +02:00
parent 71a60a46be
commit 161ae9879a
4 changed files with 173 additions and 35 deletions

View File

@ -17,7 +17,10 @@
<b-card no-body> <b-card no-body>
<b-card-header header-tag="header" class="p-1" role="tab"> <b-card-header header-tag="header" class="p-1" role="tab">
<b-col cols="12" md="6" offset="0" offset-md="3"> <b-col cols="12" md="6" offset="0" offset-md="3">
<b-button block v-b-toggle.id_accordion_url variant="info">{{ $t('Website') }}</b-button> <b-button block v-b-toggle.id_accordion_url variant="info">{{
$t('Website')
}}
</b-button>
</b-col> </b-col>
</b-card-header> </b-card-header>
<b-collapse id="id_accordion_url" visible accordion="url_import_accordion" <b-collapse id="id_accordion_url" visible accordion="url_import_accordion"
@ -125,8 +128,11 @@
<div class="row mt-1"> <div class="row mt-1">
<div class="col col-md-12 text-center"> <div class="col col-md-12 text-center">
<small class="text-muted">{{$t('click_image_import')}}</small><br/> <small class="text-muted">{{ $t('click_image_import') }}</small><br/>
<span v-if="recipe_images.length === 0">{{$t('no_more_images_found')}}</span> <span
v-if="recipe_images.length === 0">{{
$t('no_more_images_found')
}}</span>
<div class="scrolling-wrapper-flexbox"> <div class="scrolling-wrapper-flexbox">
<div class="wrapper-card" v-for="i in recipe_images" <div class="wrapper-card" v-for="i in recipe_images"
v-bind:key="i" v-bind:key="i"
@ -144,7 +150,7 @@
<b-card no-body> <b-card no-body>
<b-card-title> <b-card-title>
<div class="clearfix"> <div class="clearfix">
<span class="float-left h5">{{$t('Keywords')}}</span> <span class="float-left h5">{{ $t('Keywords') }}</span>
<b-button-group class="float-right"> <b-button-group class="float-right">
<b-button class="float-right" variant="primary" <b-button class="float-right" variant="primary"
@click="$set(recipe_json, 'keywords', recipe_json.keywords.map(x => {x.show = true; return x}))"> @click="$set(recipe_json, 'keywords', recipe_json.keywords.map(x => {x.show = true; return x}))">
@ -258,31 +264,94 @@
</b-tab> </b-tab>
<!-- App Tab --> <!-- App Tab -->
<b-tab v-bind:title="$t('App')"> <b-tab v-bind:title="$t('App')">
<b-container>
<select class="form-control" v-model="recipe_app"> <h4>{{ $t('Select_App_To_Import') }}:</h4>
<option v-for="i in INTEGRATIONS" :value="i.id" v-bind:key="i.id">{{ i.name }}</option> <b-row class="mt-4">
</select> <b-col cols="4" offset="0" offset-md="4" v-for="i in INTEGRATIONS_TD" :value="i.id"
v-bind:key="i.id">
<b-list-group style="max-width: 300px;">
<b-list-group-item class="d-flex align-items-center" v-hover
style="cursor: pointer"
v-bind:class="{ 'bg-success': recipe_app === i.id }"
@click="recipe_app = i.id">
<b-avatar class="mr-3"><i :class="i.icon"
v-if="i.img_src === undefined"></i><img
:src="i.img_src" v-if="i.img_src !== undefined" alt="Icon">
</b-avatar>
<span class="mr-auto">{{ i.name }}</span>
<b-badge variant="success" class="ml-1" v-b-tooltip:top
:title="$t('Import_Supported')"><i
class="fas fa-file-import fa-fw" v-if="i.import"></i></b-badge>
<b-badge variant="warning" class="ml-1" v-b-tooltip:top
:title="$t('Import_Not_Yet_Supported')"><i
class="fas fa-file-import fa-fw" v-if="!i.import"></i></b-badge>
<b-badge variant="success" class="ml-1" v-b-tooltip:top
:title="$t('Export_Supported')"><i
class="fas fa-file-export fa-fw" v-if="i.export"></i></b-badge>
<b-badge variant="warning" class="ml-1" v-b-tooltip:top
:title="$t('Export_Not_Yet_Supported')"><i
class="fas fa-file-export fa-fw" v-if="!i.export"></i></b-badge>
</b-list-group-item>
</b-list-group>
</b-col>
</b-row>
<b-row class="mt-4">
<b-col cols="3" v-for="i in INTEGRATIONS_WO" :value="i.id" v-bind:key="i.id"
class="mt-1">
<b-list-group style="max-width: 300px;">
<b-list-group-item class="d-flex align-items-center" v-hover
style="cursor: pointer"
v-bind:class="{ 'bg-success': recipe_app === i.id }"
@click="recipe_app = i.id">
<b-avatar class="mr-3"><i :class="i.icon"
v-if="i.img_src === undefined"></i><img
:src="i.img_src" v-if="i.img_src !== undefined" alt="Icon">
</b-avatar>
<span class="mr-auto">{{ i.name }}</span>
<b-badge variant="success" class="ml-1" v-b-tooltip:top
:title="$t('Import_Supported')"><i
class="fas fa-file-import fa-fw" v-if="i.import"></i></b-badge>
<b-badge variant="warning" class="ml-1" v-b-tooltip:top
:title="$t('Import_Not_Yet_Supported')"><i
class="fas fa-file-import fa-fw" v-if="!i.import"></i></b-badge>
<b-badge variant="success" class="ml-1" v-b-tooltip:top
:title="$t('Export_Supported')"><i
class="fas fa-file-export fa-fw" v-if="i.export"></i></b-badge>
<b-badge variant="warning" class="ml-1" v-b-tooltip:top
:title="$t('Export_Not_Yet_Supported')"><i
class="fas fa-file-export fa-fw" v-if="!i.export"></i></b-badge>
</b-list-group-item>
</b-list-group>
</b-col>
</b-row>
<b-row v-if="recipe_app_info !== undefined && recipe_app_info.help_url !== ''"
class="mt-3">
<b-col cols="12" class="text-center">
{{ $t('Importer_Help') }} <a
:href="recipe_app_info.help_url"> {{ $t('Documentation') }}</a>
</b-col>
</b-row>
<b-form-checkbox v-model="import_duplicates" name="check-button" switch <b-form-checkbox v-model="import_duplicates" name="check-button" switch
style="margin-top: 1vh"> style="margin-top: 1vh">
{{ $t('import_duplicates') }} {{ $t('import_duplicates') }}
</b-form-checkbox> </b-form-checkbox>
<a href="recipe_app_info.help_url"
v-if="recipe_app_info !== undefined && recipe_app_info.help_url !== ''">{{
$t('Help')
}}</a>
<b-form-file <b-form-file
class="my-2" class="my-2"
multiple multiple
size="lg"
v-model="recipe_files" v-model="recipe_files"
:placeholder="$t('Select_File')" :placeholder="$t('Select_File')"
drop-placeholder="Drop recipe files here..."> drop-placeholder="Drop recipe files here...">
</b-form-file> </b-form-file>
<button @click="importAppRecipe()" class="btn btn-primary shadow-none" type="button" <div class="text-center">
<b-button @click="importAppRecipe()" size="lg"
id="id_btn_app"><i class="fas fa-file-archive"></i> {{ $t('Import') }} id="id_btn_app"><i class="fas fa-file-archive"></i> {{ $t('Import') }}
</button> </b-button>
</div>
</b-container>
</b-tab> </b-tab>
<!-- Source Tab --> <!-- Source Tab -->
<b-tab v-bind:title="$t('Source')"> <b-tab v-bind:title="$t('Source')">
@ -329,7 +398,15 @@ import {BootstrapVue} from 'bootstrap-vue'
import 'bootstrap-vue/dist/bootstrap-vue.css' import 'bootstrap-vue/dist/bootstrap-vue.css'
import {resolveDjangoStatic, resolveDjangoUrl, ResolveUrlMixin, StandardToasts, ToastMixin} from "@/utils/utils"; import {
RandomIconMixin,
resolveDjangoStatic,
resolveDjangoUrl,
ResolveUrlMixin,
StandardToasts,
ToastMixin
} from "@/utils/utils";
import axios from "axios"; import axios from "axios";
import {ApiApiFactory} from "@/utils/openapi/api"; import {ApiApiFactory} from "@/utils/openapi/api";
import {INTEGRATIONS} from "@/utils/integration"; import {INTEGRATIONS} from "@/utils/integration";
@ -344,6 +421,7 @@ export default {
mixins: [ mixins: [
ResolveUrlMixin, ResolveUrlMixin,
ToastMixin, ToastMixin,
RandomIconMixin
], ],
components: { components: {
LoadingSpinner, LoadingSpinner,
@ -354,10 +432,21 @@ export default {
recipe_app_info: function () { recipe_app_info: function () {
return this.INTEGRATIONS.filter(x => x.id === this.recipe_app)[0] return this.INTEGRATIONS.filter(x => x.id === this.recipe_app)[0]
}, },
INTEGRATIONS_WO: function () {
return this.INTEGRATIONS.filter((int) => {
return int.id !== "DEFAULT"
})
},
INTEGRATIONS_TD: function () {
return this.INTEGRATIONS.filter((int) => {
return int.id === "DEFAULT"
})
}
}, },
data() { data() {
return { return {
tab_index: 0, tab_index: 1,
collapse_visible: { collapse_visible: {
url: true, url: true,
options: false, options: false,
@ -400,6 +489,9 @@ export default {
if (window.BOOKMARKLET_IMPORT_ID !== -1) { if (window.BOOKMARKLET_IMPORT_ID !== -1) {
this.loadRecipe('', false, window.BOOKMARKLET_IMPORT_ID) this.loadRecipe('', false, window.BOOKMARKLET_IMPORT_ID)
} }
this.INTEGRATIONS.forEach((int) => {
int.icon = this.getRandomFoodIcon()
})
}, },
methods: { methods: {
/** /**
@ -420,12 +512,12 @@ export default {
let recipe = response.data let recipe = response.data
apiFactory.imageRecipe(response.data.id, undefined, recipe_json.image).then(response => { // save recipe image apiFactory.imageRecipe(response.data.id, undefined, recipe_json.image).then(response => { // save recipe image
if (!silent) { if (!silent) {
StandardToasts.makeStandardToast(this,StandardToasts.SUCCESS_CREATE) StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_CREATE)
} }
this.afterImportAction(action, recipe) this.afterImportAction(action, recipe)
}).catch(e => { }).catch(e => {
if (!silent) { if (!silent) {
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_UPDATE) StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE)
} }
this.afterImportAction(action, recipe) this.afterImportAction(action, recipe)
}) })
@ -434,13 +526,13 @@ export default {
this.failed_imports.push(recipe_json.source_url) this.failed_imports.push(recipe_json.source_url)
} }
if (!silent) { if (!silent) {
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_CREATE) StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE)
} }
}) })
} else { } else {
console.log('cant import recipe without data') console.log('cant import recipe without data')
if (!silent) { if (!silent) {
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_CREATE) StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE)
} }
} }
}, },
@ -576,7 +668,7 @@ export default {
window.location.href = resolveDjangoUrl('view_import_response', response.data['import_id']) window.location.href = resolveDjangoUrl('view_import_response', response.data['import_id'])
}).catch((err) => { }).catch((err) => {
console.log(err) console.log(err)
StandardToasts.makeStandardToast(this,StandardToasts.FAIL_CREATE) StandardToasts.makeStandardToast(this, StandardToasts.FAIL_CREATE)
}) })
}, },
/** /**

View File

@ -393,5 +393,12 @@
"Options": "Options", "Options": "Options",
"Create Food": "Create Food", "Create Food": "Create Food",
"create_food_desc": "Create a food and link it to this recipe.", "create_food_desc": "Create a food and link it to this recipe.",
"additional_options": "Additional Options" "additional_options": "Additional Options",
"Importer_Help": "More information and help on this importer:",
"Documentation": "Documentation",
"Select_App_To_Import": "Please select an App to Import from",
"Import_Supported": "Import supported",
"Export_Supported": "Export supported",
"Import_Not_Yet_Supported": "Import not yet supported",
"Export_Not_Yet_Supported": "Export not yet supported"
} }

View File

@ -1,7 +1,7 @@
// containing all data and functions regarding the different integrations // containing all data and functions regarding the different integrations
export const INTEGRATIONS = [ export const INTEGRATIONS = [
{id: 'DEFAULT', name: "Tandoor", import: true, export: true, help_url: 'https://docs.tandoor.dev/features/import_export/#default'}, {id: 'DEFAULT', name: "Tandoor", import: true, export: true, help_url: 'https://docs.tandoor.dev/features/import_export/#default', img_src: 'https://raw.githubusercontent.com/TandoorRecipes/recipes/develop/docs/logo_color.svg'},
{id: 'CHEFTAP', name: "Cheftap", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#cheftap'}, {id: 'CHEFTAP', name: "Cheftap", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#cheftap'},
{id: 'CHOWDOWN', name: "Chowdown", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#chowdown'}, {id: 'CHOWDOWN', name: "Chowdown", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#chowdown'},
{id: 'COOKBOOKAPP', name: "CookBookApp", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#cookbookapp'}, {id: 'COOKBOOKAPP', name: "CookBookApp", import: true, export: false, help_url: 'https://docs.tandoor.dev/features/import_export/#cookbookapp'},

View File

@ -147,6 +147,45 @@ export class StandardToasts {
} }
} }
/*
* Utility function to get random food icon from fontawesome
* */
export const RandomIconMixin = {
name: "RandomIconMixin",
methods: {
getRandomFoodIcon: function () {
return getRandomFoodIcon()
},
},
}
export function getRandomFoodIcon() {
let icons = [
'fas fa-hamburger',
'fas fa-utensils',
'fas fa-apple-alt',
'fas fa-bacon',
'fas fa-bread-slice',
'fas fa-candy-cane',
'fas fa-carrot',
'fas fa-cheese',
'fas fa-cookie',
'fas fa-drumstick-bite',
'fas fa-egg',
'fas fa-fish',
'fas fa-hotdog',
'fas fa-ice-cream',
'fas fa-lemon',
'fas fa-pepper-hot',
'fas fa-pizza-slice',
'fas fa-cookie-bite'
]
return icons[Math.floor(Math.random() * icons.length)];
}
/* /*
* Utility functions to use djangos gettext * Utility functions to use djangos gettext
* */ * */