feat: additional cookbook features (tags, tools, and public) (#1116)

* migration: add public, tags, and tools

* generate frontend types

* add help icon

* start replacement for tool-tag-category selector

* add help icon utility

* use generator types

* add support for cookbook features

* add UI elements for cookbook features

* fix tests

* fix type error
This commit is contained in:
Hayden 2022-04-01 09:50:31 -08:00 committed by GitHub
parent 1092e0ce7c
commit cfaac2e060
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 374 additions and 97 deletions

View file

@ -0,0 +1,109 @@
<template>
<v-autocomplete
v-model="selected"
:items="items"
:value="value"
:label="label"
chips
deletable-chips
item-text="name"
multiple
:prepend-inner-icon="$globals.icons.tags"
return-object
v-bind="inputAttrs"
>
<template #selection="data">
<v-chip
:key="data.index"
class="ma-1"
:input-value="data.selected"
close
label
color="accent"
dark
@click:close="removeByIndex(data.index)"
>
{{ data.item.name || data.item }}
</v-chip>
</template>
</v-autocomplete>
</template>
<script lang="ts">
import { defineComponent, useContext } from "@nuxtjs/composition-api";
import { computed, onMounted } from "vue-demi";
import { RecipeCategory, RecipeTag } from "~/types/api-types/user";
import { RecipeTool } from "~/types/api-types/admin";
type OrganizerType = "tag" | "category" | "tool";
export default defineComponent({
props: {
value: {
type: Array as () => (RecipeTag | RecipeCategory | RecipeTool)[] | undefined,
required: true,
},
/**
* The type of organizer to use.
*/
selectorType: {
type: String as () => OrganizerType,
required: true,
},
/**
* List of items that are available to be chosen from
*/
items: {
type: Array as () => (RecipeTag | RecipeCategory | RecipeTool)[],
required: true,
},
inputAttrs: {
type: Object as () => Record<string, any>,
default: () => ({}),
},
},
setup(props, context) {
const selected = computed({
get: () => props.value,
set: (val) => {
context.emit("input", val);
},
});
onMounted(() => {
if (selected.value === undefined) {
selected.value = [];
}
});
const { i18n } = useContext();
const label = computed(() => {
switch (props.selectorType) {
case "tag":
return i18n.t("tag.tags");
case "category":
return i18n.t("category.categories");
case "tool":
return "Tools";
}
});
function removeByIndex(index: number) {
if (selected.value === undefined) {
return;
}
const newSelected = selected.value.filter((_, i) => i !== index);
selected.value = [...newSelected];
}
return {
label,
selected,
removeByIndex,
};
},
});
</script>

View file

@ -0,0 +1,28 @@
<template>
<div class="text-center">
<v-menu top offset-y left open-on-hover>
<template #activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on" @click.stop>
<v-icon> {{ $globals.icons.help }} </v-icon>
</v-btn>
</template>
<v-card max-width="300px">
<v-card-text>
<slot></slot>
</v-card-text>
</v-card>
</v-menu>
</div>
</template>
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
export default defineComponent({
setup() {
return {};
},
});
</script>
<style scoped></style>