Skip to content

Commit

Permalink
plumbing: tags into members
Browse files Browse the repository at this point in the history
  • Loading branch information
NyaomiDEV committed Jul 28, 2024
1 parent 34e3c26 commit f0afbd8
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 18 deletions.
12 changes: 9 additions & 3 deletions src/components/MemberInList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
IonAvatar,
IonLabel,
IonItemOptions,
IonItemOption
IonItemOption,
IonChip
} from "@ionic/vue";
import { Member, getTable } from '../lib/db/entities/members';
import { getBlobURL } from '../lib/util/blob';
import MemberEdit from "../modals/MemberEdit.vue";
import { provide, ref } from "vue";
import { inject, provide, ref } from "vue";
import { Tag } from "../lib/db/entities/tags";
const props = defineProps<{
member: Member,
Expand All @@ -26,6 +28,8 @@
async function removeFromDatabase() {
await getTable().delete(member.uuid);
}
const tags = inject<Tag[]>("tags");
</script>

<template>
Expand All @@ -47,8 +51,10 @@
<h2>
{{ member.name }}
</h2>
<div class="member-tags">
<IonChip v-if="tags?.length" v-for="tag in member.tags">{{ tags.find(x => x.uuid === tag)!.name }}</IonChip>
</div>
</IonLabel>
<!-- TODO: Add tags as chips -> @mecha-cat -->
</IonItem>
<IonItemOptions>
<IonItemOption v-if="canDelete" color="danger" @click="removeFromDatabase()">Delete</IonItemOption>
Expand Down
55 changes: 47 additions & 8 deletions src/modals/MemberEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
IonItem,
modalController,
IonModal,
IonButtons
IonButtons,
IonChip
} from "@ionic/vue";
import Color from "../components/Color.vue";
import TagListSelect from "./TagListSelect.vue";
import {
pencilOutline as pencilIOS,
saveOutline as saveIOS,
Expand All @@ -38,10 +41,11 @@
import journalMD from "@material-design-icons/svg/outlined/book.svg";
import { Member, getTable, newMember } from '../lib/db/entities/members';
import { Tag } from "../lib/db/entities/tags";
import { getBlobURL } from '../lib/util/blob';
import { getFiles } from "../lib/util/misc";
import { resizeImage } from "../lib/util/image";
import { Ref, inject, ref } from "vue";
import { Ref, inject, provide, ref, toRaw } from "vue";
import { getMarkdownFor } from "../lib/markdown";
import { addMaterialColors, unsetMaterialColors } from "../lib/theme";
Expand All @@ -53,25 +57,34 @@
edit?: boolean
}>();
const isIOS = inject<boolean>("isIOS");
const isTagListSelectOpen = ref(false);
provide("isTagListSelectionOpen", isTagListSelectOpen);
const member = ref({
...props.member || {},
name: props.member?.name || "",
isArchived: props.member?.isArchived || false,
isCustomFront: props.member?.isCustomFront || false,
...props.member || {}
tags: props.member?.tags || [],
} as PartialBy<Member, "uuid">);
const isEditing = ref(props.add || props.edit);
async function toggleEditing(){
if(isEditing.value){
const { uuid, ...memberWithoutUUID } = member.value;
// tags will be proxy
memberWithoutUUID.tags = toRaw(memberWithoutUUID.tags);
console.log(memberWithoutUUID);
if(!props.add){
await getTable().update(member.value.uuid, memberWithoutUUID);
await getTable().update(uuid, memberWithoutUUID);
// update member in props, since it's reactive
for(const prop in member.value)
props.member![prop] = member.value[prop];
for(const prop in memberWithoutUUID)
props.member![prop] = memberWithoutUUID[prop];
isEditing.value = false;
} else {
Expand All @@ -94,10 +107,11 @@
if(isOpen) {
isOpen.value = false;
member.value = {
...props.member || {},
name: props.member?.name || "",
isArchived: props.member?.isArchived || false,
isCustomFront: props.member?.isCustomFront || false,
...props.member || {}
tags: props.member?.tags || [],
};
}
}
Expand All @@ -110,6 +124,8 @@
unsetMaterialColors(self.value.$el);
}
}
const tags = inject<Tag[]>("tags");
</script>

<template>
Expand Down Expand Up @@ -144,7 +160,7 @@
</div>

<div class="member-tags" v-if="!isEditing">
<!-- TODO: Tags -->
<IonChip v-if="tags?.length" v-for="tag in member.tags">{{ tags?.find(x => x.uuid === tag)!.name }}</IonChip>
</div>
<div class="member-description" v-if="!isEditing">
Expand Down Expand Up @@ -176,6 +192,16 @@
<IonItem lines="none">
<IonTextarea mode="md" fill="outline" auto-grow :label="$t('members:edit.description')" labelPlacement="floating" v-model="member.description" />
</IonItem>
<IonItem button lines="none" @click="isTagListSelectOpen = true">
<IonLabel>
{{ $t("members:edit.tags") }}
<div class="member-tags">
<IonChip v-if="tags?.length" v-for="tag in member.tags">{{ tags?.find(x => x.uuid === tag)!.name }}</IonChip>
</div>
</IonLabel>
<TagListSelect :tags="member.tags" :isOpen="isTagListSelectOpen" />
</IonItem>
<IonItem button lines="none">
<Color v-model="member.color" @update:model-value="setAccent">
<IonLabel>
Expand Down Expand Up @@ -229,6 +255,19 @@
margin-bottom: 16px;
}
div.member-tags {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
padding: 0 16px;
}
.member-edit div.member-tags {
padding: 8px 0 0 0;
justify-content: start;
}
ion-avatar {
width: 192px;
height: 192px;
Expand Down
14 changes: 8 additions & 6 deletions src/modals/TagEdit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@
}>();
const tag = ref({
...props.tag || {},
name: props.tag?.name || "",
type: props.tag?.type || "member",
...props.tag || {}
} as PartialBy<Tag, "uuid">);
function dismiss(){
if(isOpen) {
isOpen.value = false;
tag.value = {
...props.tag || {},
name: props.tag?.name || "",
type: props.tag?.type || "member",
...props.tag || {}
};
}
}
Expand All @@ -63,11 +63,11 @@
const { uuid, ...tagWithoutUUID } = tag.value;
if(!props.add){
await getTable().update(tag.value.uuid, tagWithoutUUID);
await getTable().update(uuid, tagWithoutUUID);
// update tag in props, since it's reactive
for(const prop in tag.value)
props.tag![prop] = tag.value[prop];
for(const prop in tagWithoutUUID)
props.tag![prop] = tagWithoutUUID[prop];
try{
await modalController.dismiss(undefined, "modified");
Expand All @@ -83,7 +83,9 @@
async function deleteTag(){
await removeTag(tag.value!.uuid!);
await modalController.dismiss(undefined, "deleted");
try{
await modalController.dismiss(undefined, "deleted");
}catch(_){}
}
const self = ref();
Expand Down
91 changes: 91 additions & 0 deletions src/modals/TagListSelect.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<script setup lang="ts">
import {
IonContent,
IonHeader,
IonToolbar,
IonTitle,
IonButton,
IonIcon,
IonList,
IonItem,
IonModal,
IonSearchbar,
IonButtons,
IonCheckbox,
CheckboxCustomEvent,
} from "@ionic/vue";
import {
chevronBack as backIOS,
} from "ionicons/icons";
import backMD from "@material-design-icons/svg/outlined/arrow_back.svg";
import { inject, Ref, ref, toRaw } from "vue";
import { getFilteredTags } from "../lib/db/liveQueries";
import { UUID } from "../lib/db/types";
const isTagListSelectionOpen = inject<Ref<boolean>>("isTagListSelectionOpen");
const props = defineProps<{
tags?: UUID[]
}>();
async function dismiss(){
if(isTagListSelectionOpen){
props.tags!.length = 0;
props.tags!.push(...toRaw(selectedTags.value));
isTagListSelectionOpen.value = false;
}
}
function check(ev: CheckboxCustomEvent){
if(ev.detail.checked)
selectedTags.value.push(ev.detail.value);
else {
const index = selectedTags.value.indexOf(ev.detail.value);
if(index > -1)
selectedTags.value.splice(index, 1);
}
}
const search = ref("");
const filteredTags = getFilteredTags(search, ref("member"));
const selectedTags: Ref<UUID[]> = ref([...props.tags || []]);
</script>

<template>
<IonModal @didDismiss="dismiss">
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonButton shape="round" fill="clear" @click="dismiss">
<IonIcon slot="icon-only" :md="backMD" :ios="backIOS"></IonIcon>
</IonButton>
</IonButtons>
<IonTitle>Tag select</IonTitle>
</IonToolbar>
<IonToolbar>
<IonSearchbar
:animated="true"
:placeholder="$t('options:tagManagement.searchPlaceholder')"
showCancelButton="focus"
showClearButton="focus"
:spellcheck="false"
v-model="search"
/>
</IonToolbar>
</IonHeader>

<IonContent>
<IonList inset>
<IonItem button v-for="tag in filteredTags" :key="tag.uuid">
<IonCheckbox :value="tag.uuid" :checked="selectedTags.includes(tag.uuid)" @ionChange="check">
{{ tag.name }}
</IonCheckbox>
</IonItem>
</IonList>
</IonContent>
</IonModal>
</template>
11 changes: 10 additions & 1 deletion src/views/tabbed/Members.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,24 @@
IonFabButton,
IonIcon
} from '@ionic/vue';
import { inject, provide, ref } from 'vue';
import { inject, onMounted, provide, ref } from 'vue';
import { getFilteredMembers } from '../../lib/db/liveQueries';
import { addOutline as addIOS } from "ionicons/icons";
import addMD from "@material-design-icons/svg/outlined/add.svg";
import MemberEdit from '../../modals/MemberEdit.vue';
import MemberInList from '../../components/MemberInList.vue';
import { Tag, getTable as getTagsTable } from '../../lib/db/entities/tags';
const isIOS = inject<boolean>("isIOS");
const tags = ref<Tag[]>([]);
provide("tags", tags);
onMounted(loadTags);
async function loadTags(){
tags.value = await getTagsTable().toArray();
}
const search = ref("");
const members = getFilteredMembers(search);
Expand Down

0 comments on commit f0afbd8

Please sign in to comment.