Basic goal list editing / creation / deletion
This commit is contained in:
parent
40f2750f4f
commit
b5add9b8a0
@ -8,6 +8,8 @@
|
|||||||
<q-card-section class="q-gutter-y-md column">
|
<q-card-section class="q-gutter-y-md column">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="goal_name"
|
v-model="goal_name"
|
||||||
|
:error="!!name_error.length"
|
||||||
|
:error-message="name_error"
|
||||||
square
|
square
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
@ -155,9 +157,21 @@ goal_name.value = data.goal?.name ?? '';
|
|||||||
goal_description.value = data.goal?.description ?? '';
|
goal_description.value = data.goal?.description ?? '';
|
||||||
goal_tags.value = data.goal?.tags ?? [];
|
goal_tags.value = data.goal?.tags ?? [];
|
||||||
|
|
||||||
|
const name_error = computed(() => {
|
||||||
|
if (isNameReserved(goal_name.value)) {
|
||||||
|
return 'Name is reserved';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
function isNameReserved(name: string) {
|
||||||
|
return name.length && data.reserved_names.some(reserved_name =>
|
||||||
|
reserved_name !== data.goal?.name
|
||||||
|
&& stringCompare(reserved_name, name));
|
||||||
|
}
|
||||||
|
|
||||||
function canSave() {
|
function canSave() {
|
||||||
return goal_name.value?.length > 0
|
return !isNameReserved(goal_name.value);
|
||||||
&& !data.reserved_names.some(name => name !== data.goal?.name && stringCompare(name, goal_name.value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTag(value: string, done: Function) {
|
function addTag(value: string, done: Function) {
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
>
|
>
|
||||||
<q-card-section class="q-gutter-y-md column">
|
<q-card-section class="q-gutter-y-md column">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="goal_name"
|
v-model="goal_list_name"
|
||||||
|
:error="!!name_error.length"
|
||||||
|
:error-message="name_error"
|
||||||
square
|
square
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
@ -19,7 +21,7 @@
|
|||||||
|
|
||||||
<q-input
|
<q-input
|
||||||
class="col-10"
|
class="col-10"
|
||||||
v-model="goal_description"
|
v-model="goal_list_description"
|
||||||
square
|
square
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
@ -38,36 +40,24 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<q-select
|
|
||||||
label="Select Tags"
|
|
||||||
square
|
|
||||||
filled
|
|
||||||
v-model="goal_tags"
|
|
||||||
use-input
|
|
||||||
use-chips
|
|
||||||
multiple
|
|
||||||
clearable
|
|
||||||
hint="Optional"
|
|
||||||
hide-dropdown-icon
|
|
||||||
input-debounce="0"
|
|
||||||
:options="all_tags"
|
|
||||||
@new-value="addTag"
|
|
||||||
></q-select>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
<q-separator />
|
<q-separator />
|
||||||
|
|
||||||
<q-card-actions>
|
<q-card-actions>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="data.goal"
|
v-if="data.goal_list"
|
||||||
flat
|
flat
|
||||||
color="red"
|
color="red"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
:label="delete_label"
|
:label="delete_label"
|
||||||
@click="deleteGoal()"
|
@click="deleteGoalList()"
|
||||||
:disabled="!delete_enabled"
|
:disabled="!delete_actually_enabled"
|
||||||
/>
|
>
|
||||||
|
<q-tooltip v-if="has_goals">
|
||||||
|
Cannot delete goal list with goals
|
||||||
|
</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
|
||||||
<q-space/>
|
<q-space/>
|
||||||
|
|
||||||
@ -83,7 +73,7 @@
|
|||||||
color="green"
|
color="green"
|
||||||
icon="save"
|
icon="save"
|
||||||
label="Save"
|
label="Save"
|
||||||
@click="saveGoal()"
|
@click="saveGoalList()"
|
||||||
:disabled="!canSave()"
|
:disabled="!canSave()"
|
||||||
/>
|
/>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
@ -95,43 +85,50 @@
|
|||||||
bordered
|
bordered
|
||||||
>
|
>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<MarkdownRenderer :text="goal_description"/>
|
<MarkdownRenderer :text="goal_list_description"/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BingoGoal from '@/js/lib/BingoGoal.ts';
|
import BingoGoalList from '@/js/lib/BingoGoalList.ts';
|
||||||
import {
|
import {
|
||||||
stringCompare
|
stringCompare
|
||||||
} from '@/js/lib/Util.ts';
|
} from '@/js/lib/Util.ts';
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'cancel',
|
'cancel',
|
||||||
'createGoal',
|
'createGoalList',
|
||||||
'updateGoal',
|
'updateGoalList',
|
||||||
'deleteGoal'
|
'deleteGoalList'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data
|
data
|
||||||
} = defineProps<{
|
} = defineProps<{
|
||||||
data: {
|
data: {
|
||||||
all_tags: string[],
|
|
||||||
reserved_names: string[],
|
reserved_names: string[],
|
||||||
goal?: BingoGoal,
|
goal_list?: BingoGoalList,
|
||||||
},
|
},
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const all_tags: Ref<string[]> = ref([ ...data.all_tags ]);
|
|
||||||
|
|
||||||
const markdown_preview = ref(false);
|
const markdown_preview = ref(false);
|
||||||
|
|
||||||
const delete_label = ref('Delete (5)');
|
const delete_label = ref('Delete (5)');
|
||||||
const delete_enabled = ref(false);
|
const delete_enabled = ref(false);
|
||||||
|
|
||||||
|
const has_goals = computed(() => {
|
||||||
|
return data.goal_list?.goals?.length;
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
if (has_goals) {
|
||||||
|
delete_label.value = 'Delete';
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let countdown = 5;
|
let countdown = 5;
|
||||||
let interval = setInterval(() => {
|
let interval = setInterval(() => {
|
||||||
if (--countdown <= 0) {
|
if (--countdown <= 0) {
|
||||||
@ -147,58 +144,55 @@ onMounted(() => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
const goal_name = ref('');
|
const delete_actually_enabled = computed(() => {
|
||||||
const goal_description = ref('');
|
return delete_enabled.value && !has_goals;
|
||||||
const goal_tags: Ref<string[]> = ref([ ]);
|
});
|
||||||
|
|
||||||
goal_name.value = data.goal?.name ?? '';
|
const goal_list_name = ref('');
|
||||||
goal_description.value = data.goal?.description ?? '';
|
const goal_list_description = ref('');
|
||||||
goal_tags.value = data.goal?.tags ?? [];
|
|
||||||
|
|
||||||
function canSave() {
|
goal_list_name.value = data.goal_list?.name ?? '';
|
||||||
return goal_name.value?.length > 0
|
goal_list_description.value = data.goal_list?.description ?? '';
|
||||||
&& !data.reserved_names.some(name => name !== data.goal?.name && stringCompare(name, goal_name.value));
|
|
||||||
|
const name_error = computed(() => {
|
||||||
|
if (isNameReserved(goal_list_name.value)) {
|
||||||
|
return 'Name is reserved';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
function isNameReserved(name: string) {
|
||||||
|
return name.length && data.reserved_names.some(reserved_name =>
|
||||||
|
reserved_name !== data.goal_list?.name
|
||||||
|
&& stringCompare(reserved_name, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTag(value: string, done: Function) {
|
function canSave() {
|
||||||
// Exit if tag already exists
|
return !isNameReserved(goal_list_name.value);
|
||||||
if (goal_tags.value.some(tag => stringCompare(tag, value))) {
|
|
||||||
done();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tag = all_tags.value.find(tag => stringCompare(tag, value));
|
|
||||||
value = tag ?? value;
|
|
||||||
|
|
||||||
if (!data.all_tags.some(tag => stringCompare(tag, value))) {
|
|
||||||
all_tags.value.push(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
done(value, 'toggle');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveGoal() {
|
function saveGoalList() {
|
||||||
const goal = new BingoGoal(goal_name.value);
|
const goal_list = new BingoGoalList(goal_list_name.value);
|
||||||
goal.description = goal_description.value;
|
goal_list.description = goal_list_description.value;
|
||||||
goal.tags = goal_tags.value;
|
|
||||||
|
|
||||||
// Create new goal
|
// Create new goal list
|
||||||
if (!data.goal) {
|
if (!data.goal_list) {
|
||||||
emit('createGoal', goal);
|
emit('createGoalList', goal_list);
|
||||||
}
|
}
|
||||||
// Update existing goal
|
// Update existing goal list
|
||||||
else {
|
else {
|
||||||
emit('updateGoal', data.goal, goal);
|
goal_list.goals = data.goal_list.goals;
|
||||||
|
|
||||||
|
emit('updateGoalList', data.goal_list, goal_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteGoal() {
|
function deleteGoalList() {
|
||||||
emit('deleteGoal', data.goal);
|
emit('deleteGoalList', data.goal_list);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- TODO: Can't seem to work with flexbox to an extent that makes me happy... -->
|
<!-- TODO: Can't seem to work with flexbox to an extent that makes me happy... -->
|
||||||
|
|
||||||
<q-card class="column" style="width: 100%; min-width: 700px; height: 80vh;">
|
<q-card class="column" style="width: 100%; min-width: 800px; height: 80vh;">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<q-card-section class="row justify-evenly q-gutter-md">
|
<q-card-section class="row justify-evenly q-gutter-md">
|
||||||
<q-input
|
<q-input
|
||||||
@ -86,16 +86,16 @@
|
|||||||
/>
|
/>
|
||||||
<div>{{ prop.node.item?.name || prop.node.label }}</div>
|
<div>{{ prop.node.item?.name || prop.node.label }}</div>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="prop.node.goal?.description?.length"
|
v-if="prop.node.item?.description?.length"
|
||||||
icon="help_outline"
|
icon="help_outline"
|
||||||
flat
|
flat
|
||||||
round
|
round
|
||||||
size="sm"
|
size="sm"
|
||||||
@click="openInfoDialog(prop.node.goal.description)"
|
@click="event => openInfoDialog(prop.node.item?.description, event)"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
<q-badge
|
<q-badge
|
||||||
outline
|
outline
|
||||||
v-for="tag in prop.node.goal.tags"
|
v-for="tag in prop.node.item?.tags"
|
||||||
:key="tag"
|
:key="tag"
|
||||||
:color="getColorForString(tag)"
|
:color="getColorForString(tag)"
|
||||||
class="q-ml-sm"
|
class="q-ml-sm"
|
||||||
@ -116,6 +116,14 @@
|
|||||||
@click="event => openEditGoalListDialog(prop.node, event)"
|
@click="event => openEditGoalListDialog(prop.node, event)"
|
||||||
/>
|
/>
|
||||||
<div>{{ prop.node.item?.name || prop.node.label }}</div>
|
<div>{{ prop.node.item?.name || prop.node.label }}</div>
|
||||||
|
<q-btn
|
||||||
|
v-if="prop.node.item?.description?.length"
|
||||||
|
icon="help_outline"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
size="sm"
|
||||||
|
@click="event => openInfoDialog(prop.node.item?.description, event)"
|
||||||
|
></q-btn>
|
||||||
<q-badge
|
<q-badge
|
||||||
outline
|
outline
|
||||||
color="orange"
|
color="orange"
|
||||||
@ -220,19 +228,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
|
||||||
<q-dialog
|
<q-dialog v-model="description_dialog">
|
||||||
v-model="description_dialog"
|
|
||||||
style="min-width: 700px; max-width: 80vw; min-height: 10vh; max-height: 80vh;"
|
|
||||||
>
|
|
||||||
<q-card
|
<q-card
|
||||||
|
class="column"
|
||||||
flat
|
flat
|
||||||
bordered
|
bordered
|
||||||
class="full-width"
|
style="min-width: 700px; max-width: 80vw; min-height: 10vh; max-height: 70vh;"
|
||||||
>
|
>
|
||||||
<q-card-section class="full-height">
|
<div class="col-1">
|
||||||
|
<q-card-section>
|
||||||
|
<span class="text-h4">Description Editor</span>
|
||||||
|
</q-card-section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6">
|
||||||
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="game_description"
|
v-model="game_description"
|
||||||
class="full-height"
|
|
||||||
square
|
square
|
||||||
filled
|
filled
|
||||||
counter
|
counter
|
||||||
@ -240,18 +252,19 @@
|
|||||||
maxlength="500"
|
maxlength="500"
|
||||||
label="Description"
|
label="Description"
|
||||||
type="text"
|
type="text"
|
||||||
>
|
/>
|
||||||
</q-input>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
</div>
|
||||||
|
|
||||||
<q-card-actions>
|
<div class="col-1">
|
||||||
|
<q-card-actions class="full-height items-end">
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
color="red"
|
color="red"
|
||||||
icon="cancel"
|
icon="cancel"
|
||||||
label="Preview"
|
label="Preview"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@click="openInfoDialog(game_description)"
|
@click="event => openInfoDialog(game_description, event)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-space/>
|
<q-space/>
|
||||||
@ -264,13 +277,15 @@
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
/>
|
/>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
|
</div>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<q-dialog v-model="info_dialog" style="min-width: 700px; max-width: 80vw; min-height: 10vh; max-height: 80vh;">
|
<q-dialog v-model="info_dialog">
|
||||||
<q-card
|
<q-card
|
||||||
flat
|
flat
|
||||||
bordered
|
bordered
|
||||||
|
style="min-width: 700px; max-width: 80vw; min-height: 10vh; max-height: 80vh;"
|
||||||
>
|
>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<MarkdownRenderer :text="info_dialog_text"/>
|
<MarkdownRenderer :text="info_dialog_text"/>
|
||||||
@ -288,24 +303,26 @@
|
|||||||
/>
|
/>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
<!-- <q-dialog v-model="edit_goal_list_dialog" persistent>
|
<q-dialog v-model="edit_goal_list_dialog" persistent>
|
||||||
<EditGoalListDialog
|
<EditGoalListDialog
|
||||||
:data="edit_goal_list_data"
|
:data="edit_goal_list_data"
|
||||||
@cancel="edit_goal_list_dialog = false"
|
@cancel="edit_goal_list_dialog = false"
|
||||||
|
@create-goal-list="create_goal_list"
|
||||||
|
@update-goal-list="update_goal_list"
|
||||||
@delete-goal-list="delete_goal_list"
|
@delete-goal-list="delete_goal_list"
|
||||||
@emit-goal-list="emit_goal_list"
|
|
||||||
/>
|
/>
|
||||||
</q-dialog> -->
|
</q-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
interface Node {
|
interface Node {
|
||||||
label: string;
|
|
||||||
item?: BingoGoal | BingoGoalList | BingoCategory;
|
item?: BingoGoal | BingoGoalList | BingoCategory;
|
||||||
header?: string; // 'goal' | 'goal-list' | 'category' | 'add-goal' | 'add-goal-list' | 'add-category'
|
|
||||||
children?: Node[];
|
|
||||||
goal?: BingoGoal;
|
|
||||||
parent?: BingoCategory | BingoGoalList;
|
parent?: BingoCategory | BingoGoalList;
|
||||||
|
|
||||||
|
label: string;
|
||||||
|
header?: string; // 'goal' | 'goal-list' | 'category' | 'add-goal' | 'add-goal-list' | 'add-category'
|
||||||
|
|
||||||
|
children?: Node[];
|
||||||
}
|
}
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -338,7 +355,7 @@ game.value.is_local = true;
|
|||||||
const game_id = ref(game.value.id);
|
const game_id = ref(game.value.id);
|
||||||
const game_name = ref(game.value.name);
|
const game_name = ref(game.value.name);
|
||||||
const short_description = ref(game.value.short_description);
|
const short_description = ref(game.value.short_description);
|
||||||
const game_description = ref(game.value.description);
|
const game_description = ref(game.value.description.substring(0, 500));
|
||||||
const description_dialog = ref(false);
|
const description_dialog = ref(false);
|
||||||
|
|
||||||
const expanded = ref<Node[]>([]);
|
const expanded = ref<Node[]>([]);
|
||||||
@ -373,7 +390,10 @@ function saveGame() {
|
|||||||
const info_dialog = ref(false);
|
const info_dialog = ref(false);
|
||||||
const info_dialog_text = ref('');
|
const info_dialog_text = ref('');
|
||||||
|
|
||||||
function openInfoDialog(text: string) {
|
function openInfoDialog(text: string, event: Event) {
|
||||||
|
// Stop expanding of the tree
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
info_dialog_text.value = text;
|
info_dialog_text.value = text;
|
||||||
info_dialog.value = true;
|
info_dialog.value = true;
|
||||||
}
|
}
|
||||||
@ -395,7 +415,7 @@ const edit_goal_data = ref<EditGoalData>({
|
|||||||
});
|
});
|
||||||
const edit_goal_dialog = ref(false);
|
const edit_goal_dialog = ref(false);
|
||||||
const openEditGoalDialog = (node: Node) => {
|
const openEditGoalDialog = (node: Node) => {
|
||||||
edit_goal_data.value.goal = node.goal;
|
edit_goal_data.value.goal = node.item as BingoGoal;
|
||||||
edit_goal_data.value.reserved_names = game.value?.reserved_names ?? [];
|
edit_goal_data.value.reserved_names = game.value?.reserved_names ?? [];
|
||||||
edit_goal_data.value.parent_group = node.parent;
|
edit_goal_data.value.parent_group = node.parent;
|
||||||
edit_goal_data.value.all_tags = game.value?.getAllTags() ?? [];
|
edit_goal_data.value.all_tags = game.value?.getAllTags() ?? [];
|
||||||
@ -457,10 +477,12 @@ const delete_goal = (goal: BingoGoal) => {
|
|||||||
/* Edit Goal List Dialog */
|
/* Edit Goal List Dialog */
|
||||||
interface EditGoalListData {
|
interface EditGoalListData {
|
||||||
goal_list?: BingoGoalList;
|
goal_list?: BingoGoalList;
|
||||||
|
reserved_names: string[];
|
||||||
parent_group: BingoCategory | undefined;
|
parent_group: BingoCategory | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const edit_goal_list_data = ref<EditGoalListData>({
|
const edit_goal_list_data = ref<EditGoalListData>({
|
||||||
|
reserved_names: [] as string[],
|
||||||
parent_group: undefined
|
parent_group: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -471,27 +493,51 @@ function openEditGoalListDialog(node: Node, event: Event) {
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
edit_goal_list_data.value.goal_list = node.item as BingoGoalList;
|
edit_goal_list_data.value.goal_list = node.item as BingoGoalList;
|
||||||
|
edit_goal_list_data.value.reserved_names = game.value?.reserved_names ?? [];
|
||||||
edit_goal_list_data.value.parent_group = node.parent as BingoCategory;
|
edit_goal_list_data.value.parent_group = node.parent as BingoCategory;
|
||||||
edit_goal_list_dialog.value = true;
|
edit_goal_list_dialog.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit_goal_list = (goal_list: BingoGoalList) => {
|
const create_goal_list = (goal_list: BingoGoalList) => {
|
||||||
// We always assume parent group is a category. You can't add goal lists to goal lists.
|
// We always assume parent group is a category. You can't add goal lists to goal lists.
|
||||||
const category = edit_goal_list_data.value.parent_group as BingoCategory;
|
const category = edit_goal_list_data.value.parent_group as BingoCategory;
|
||||||
|
|
||||||
// Add new goal list
|
// Add goal list to category
|
||||||
if (!edit_goal_list_data.value.goal_list) {
|
if (category) {
|
||||||
category.goal_lists.push(goal_list);
|
category.goal_lists.push(goal_list);
|
||||||
}
|
}
|
||||||
// Replace existing goal list
|
// Add goal list to game
|
||||||
else {
|
else {
|
||||||
const index = category.goal_lists.findIndex(g => g === goal_list);
|
game.value?.items.push(goal_list);
|
||||||
category.goal_lists.splice(index, 1, goal_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset values
|
// Reset values
|
||||||
edit_goal_list_data.value = {
|
edit_goal_list_data.value = {
|
||||||
parent_group: undefined
|
parent_group: undefined,
|
||||||
|
reserved_names: []
|
||||||
|
};
|
||||||
|
edit_goal_list_dialog.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const update_goal_list = (old_goal_list: BingoGoalList, goal_list: BingoGoalList) => {
|
||||||
|
// We always assume parent group is a category. You can't add goal lists to goal lists.
|
||||||
|
const category = edit_goal_list_data.value.parent_group as BingoCategory;
|
||||||
|
|
||||||
|
// Replace existing goal list in category
|
||||||
|
if (category) {
|
||||||
|
const index = category.goal_lists.findIndex(g => g === old_goal_list);
|
||||||
|
category.goal_lists.splice(index, 1, goal_list);
|
||||||
|
}
|
||||||
|
// Replace existing goal list in game
|
||||||
|
else {
|
||||||
|
const index = game.value?.items.findIndex(g => g === old_goal_list);
|
||||||
|
game.value?.items.splice(index, 1, goal_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset values
|
||||||
|
edit_goal_list_data.value = {
|
||||||
|
parent_group: undefined,
|
||||||
|
reserved_names: []
|
||||||
};
|
};
|
||||||
edit_goal_list_dialog.value = false;
|
edit_goal_list_dialog.value = false;
|
||||||
};
|
};
|
||||||
@ -502,13 +548,22 @@ const delete_goal_list = (goal_list: BingoGoalList) => {
|
|||||||
// We always assume parent group is a category. You can't add goal lists to goal lists.
|
// We always assume parent group is a category. You can't add goal lists to goal lists.
|
||||||
const category = edit_goal_list_data.value.parent_group as BingoCategory;
|
const category = edit_goal_list_data.value.parent_group as BingoCategory;
|
||||||
|
|
||||||
|
// Delete goal list from category
|
||||||
|
if (category) {
|
||||||
const index = category.goal_lists.findIndex(g => g === goal_list);
|
const index = category.goal_lists.findIndex(g => g === goal_list);
|
||||||
category.goal_lists.splice(index, 1);
|
category.goal_lists.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
// Delete goal list from game
|
||||||
|
else {
|
||||||
|
const index = game.value?.items.findIndex(g => g === goal_list);
|
||||||
|
game.value?.items.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reset values
|
// Reset values
|
||||||
edit_goal_list_data.value = {
|
edit_goal_list_data.value = {
|
||||||
parent_group: undefined
|
parent_group: undefined,
|
||||||
|
reserved_names: []
|
||||||
};
|
};
|
||||||
edit_goal_list_dialog.value = false;
|
edit_goal_list_dialog.value = false;
|
||||||
};
|
};
|
||||||
@ -575,32 +630,37 @@ const nodes = computed(() => {
|
|||||||
const is_goal_list = item instanceof BingoGoalList;
|
const is_goal_list = item instanceof BingoGoalList;
|
||||||
|
|
||||||
const group_node: Node = {
|
const group_node: Node = {
|
||||||
label: item.name,
|
|
||||||
item,
|
item,
|
||||||
|
|
||||||
|
label: item.name,
|
||||||
header: is_category
|
header: is_category
|
||||||
? 'category'
|
? 'category'
|
||||||
: is_goal_list
|
: is_goal_list
|
||||||
? 'goal-list'
|
? 'goal-list'
|
||||||
: '',
|
: '',
|
||||||
|
|
||||||
children: []
|
children: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (is_category) {
|
if (is_category) {
|
||||||
group_node.children = item.goal_lists.map(goal_list => {
|
group_node.children = item.goal_lists.map(goal_list => {
|
||||||
const goal_list_node: Node = {
|
const goal_list_node: Node = {
|
||||||
label: goal_list.name,
|
|
||||||
item: goal_list,
|
item: goal_list,
|
||||||
|
parent: item,
|
||||||
|
|
||||||
|
label: goal_list.name,
|
||||||
header: 'goal-list',
|
header: 'goal-list',
|
||||||
|
|
||||||
children: []
|
children: []
|
||||||
};
|
};
|
||||||
|
|
||||||
goal_list_node.children?.push(...goal_list.goals.map(goal => {
|
goal_list_node.children?.push(...goal_list.goals.map(goal => {
|
||||||
const goal_node: Node = {
|
const goal_node: Node = {
|
||||||
label: goal.name,
|
|
||||||
item: goal,
|
item: goal,
|
||||||
header: 'goal',
|
parent: goal_list,
|
||||||
goal,
|
|
||||||
parent: goal_list
|
label: goal.name,
|
||||||
|
header: 'goal'
|
||||||
};
|
};
|
||||||
|
|
||||||
return goal_node;
|
return goal_node;
|
||||||
@ -624,11 +684,11 @@ const nodes = computed(() => {
|
|||||||
else if (is_goal_list) {
|
else if (is_goal_list) {
|
||||||
group_node.children = item.goals.map(goal => {
|
group_node.children = item.goals.map(goal => {
|
||||||
const goal_node: Node = {
|
const goal_node: Node = {
|
||||||
label: goal.name,
|
|
||||||
item: goal,
|
item: goal,
|
||||||
header: 'goal',
|
parent: item,
|
||||||
goal,
|
|
||||||
parent: item
|
label: goal.name,
|
||||||
|
header: 'goal'
|
||||||
};
|
};
|
||||||
|
|
||||||
return goal_node;
|
return goal_node;
|
||||||
|
@ -63,7 +63,11 @@ export default class BingoGame {
|
|||||||
names.push(goal.name);
|
names.push(goal.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
names.push(subgroup.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
names.push(group.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
|
@ -6,6 +6,8 @@ import {
|
|||||||
export default class BingoGoalList {
|
export default class BingoGoalList {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
description: string = '';
|
||||||
|
|
||||||
@Type(() => BingoGoal)
|
@Type(() => BingoGoal)
|
||||||
goals: BingoGoal[] = [];
|
goals: BingoGoal[] = [];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user