mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-05-16 02:03:16 +12:00
added tag support and further improved search
This commit is contained in:
parent
7d2597e3c8
commit
d9a68cf0cf
15
changelog.md
15
changelog.md
|
@ -10,16 +10,21 @@
|
|||
|
||||
- A new logo added to the app (better visibility of the logo in small scales and icons)
|
||||
- Massive overhaul of the search engine used by the Quick opening existing document and single/multi relationship fields (now supports tags, categories, document types, inteligent filtering and inteligent sorting via importance of the found values)
|
||||
- Added color support to single/multi relationship fields
|
||||
- Added a hierarchical path to Quick opening existing document and single/multi relationship fields
|
||||
- Added filtering to include or exclude documents that are considered categories in the Quick opening existing document dialog
|
||||
- Added automatic opening of hierarchical tree branches upon adding/moving documents under/among them
|
||||
- Added tags support
|
||||
|
||||
### QoL adjustments
|
||||
|
||||
- Added a hierarchical path to Quick opening existing document and single/multi relationship fields
|
||||
- Added color support to single/multi relationship fields
|
||||
- Added filtering to include or exclude documents that are considered categories in the Quick opening existing document dialog
|
||||
- Slightly modified the scrollbar visuals to be less intrusive
|
||||
- Added a light golden tint to the background of the app to go easy on user's eyes before farkmode is added
|
||||
- Improved performance by reducing the amount of time the side-tree re-renders
|
||||
- Added automatic opening of hierarchical tree branches upon adding/moving documents under/among them
|
||||
- Alligned custom order sorting for both nodes with and without children
|
||||
- Visually alligned custom order badge for both nodes with and without children
|
||||
- Added dark visuals to the single-select and multi-select fields to align with thge rest of the app
|
||||
- All popup dialogs have been unified to dark-color mode
|
||||
- Prettified a dialog popup for confirmation of closing a document with active edits
|
||||
- Added a small filter over the big white areas to ease-up on the user's eyes before darkmode is added
|
||||
|
||||
## 0.1.2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fantasiaarchive",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "A database manager for world building",
|
||||
"productName": "Fantasia archive",
|
||||
"author": "Elvanos <elvanos66@gmail.com>",
|
||||
|
|
|
@ -44,6 +44,7 @@ export default class AppHeader extends BaseClass {
|
|||
}
|
||||
|
||||
.appHeaderInner {
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
min-height: 40px;
|
||||
-webkit-app-region: drag;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
@click.stop.prevent.middle="processNodeLabelMiddleClick(prop.node)"
|
||||
>
|
||||
<q-icon
|
||||
:style="`color: ${prop.node.color}; width: 22px !important;`"
|
||||
:style="`color: ${determineNodeColor(prop.node)}; width: 22px !important;`"
|
||||
:size="(prop.node.icon.includes('fas')? '16px': '21px')"
|
||||
:name="prop.node.icon"
|
||||
class="q-mr-sm self-center" />
|
||||
|
@ -56,7 +56,7 @@
|
|||
<div class="treeButtonGroup">
|
||||
<q-btn
|
||||
tabindex="-1"
|
||||
v-if="prop.node.children && prop.node.children.length > 0 && !prop.node.isRoot"
|
||||
v-if="prop.node.children && prop.node.children.length > 0 && !prop.node.isRoot && !prop.node.isTag"
|
||||
round
|
||||
flat
|
||||
dense
|
||||
|
@ -74,7 +74,7 @@
|
|||
</q-btn>
|
||||
<q-btn
|
||||
tabindex="-1"
|
||||
v-if="!prop.node.specialLabel || prop.node.isRoot"
|
||||
v-if="(!prop.node.specialLabel && !prop.node.isRoot) || (prop.node.isRoot && !prop.node.isTag)"
|
||||
round
|
||||
flat
|
||||
dense
|
||||
|
@ -134,7 +134,8 @@ import PouchDB from "pouchdb"
|
|||
import { engageBlueprints, retrieveAllBlueprints } from "src/scripts/databaseManager/blueprintManager"
|
||||
// import { cleanDatabases } from "src/scripts/databaseManager/cleaner"
|
||||
import { I_Blueprint } from "src/interfaces/I_Blueprint"
|
||||
import { extend } from "quasar"
|
||||
import { extend, colors } from "quasar"
|
||||
import { tagListBuildFromBlueprints } from "src/scripts/utilities/tagListBuilder"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
|
@ -268,6 +269,8 @@ export default class ObjectTree extends BaseClass {
|
|||
resetTreeFilter () {
|
||||
this.treeFilter = ""
|
||||
const treeFilterDOM = this.$refs.treeFilter as unknown as HTMLInputElement
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
treeFilterDOM.focus()
|
||||
}
|
||||
|
||||
|
@ -358,6 +361,7 @@ export default class ObjectTree extends BaseClass {
|
|||
async buildCurrentObjectTree () {
|
||||
const allBlueprings = this.SGET_allBlueprints
|
||||
const treeObject: any[] = []
|
||||
let allTreeDocuments: I_ShortenedDocument[] = []
|
||||
|
||||
// Process all documents, build hieararchy out of the and sort them via name and custom order
|
||||
for (const blueprint of allBlueprings) {
|
||||
|
@ -393,6 +397,8 @@ export default class ObjectTree extends BaseClass {
|
|||
})
|
||||
|
||||
const documentCount = allDocumentsRows.length
|
||||
const listCopy: I_ShortenedDocument[] = extend(true, [], allDocumentsRows)
|
||||
allTreeDocuments = [...allTreeDocuments, ...listCopy]
|
||||
|
||||
const hierarchicalTreeContent = this.buildTreeHierarchy(allDocumentsRows)
|
||||
|
||||
|
@ -436,6 +442,36 @@ export default class ObjectTree extends BaseClass {
|
|||
return 0
|
||||
})
|
||||
|
||||
const tagList = await tagListBuildFromBlueprints(this.SGET_allBlueprints)
|
||||
|
||||
tagList.forEach((tag: string) => {
|
||||
const tagDocs = allTreeDocuments
|
||||
.filter(doc => {
|
||||
const docTags = doc.extraFields.find(e => e.id === "tags")?.value as unknown as string[]
|
||||
return (docTags && docTags.includes(tag))
|
||||
})
|
||||
.map((doc:I_ShortenedDocument) => {
|
||||
// @ts-ignore
|
||||
doc.key = `${tag}${doc._id}`
|
||||
// @ts-ignore
|
||||
doc.isTag = true
|
||||
return doc
|
||||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
|
||||
const tagObject = {
|
||||
label: `${tag}`,
|
||||
icon: "mdi-tag",
|
||||
_id: `tag-${tag}`,
|
||||
key: `tag-${tag}`,
|
||||
documentCount: tagDocs.length,
|
||||
isRoot: true,
|
||||
isTag: true,
|
||||
children: tagDocs
|
||||
}
|
||||
treeObject.push(tagObject)
|
||||
})
|
||||
|
||||
// Assign the finished object to the render model
|
||||
this.hierarchicalTree = treeObject
|
||||
}
|
||||
|
@ -539,10 +575,15 @@ export default class ObjectTree extends BaseClass {
|
|||
children: []
|
||||
type: string
|
||||
isRoot: boolean
|
||||
isTag: boolean
|
||||
specialLabel: string|boolean
|
||||
}) {
|
||||
this.selectedTreeNode = null
|
||||
|
||||
if (node.isRoot && node.isTag) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!node.specialLabel && !node.isRoot) {
|
||||
// @ts-ignore
|
||||
this.openExistingDocumentRoute(node)
|
||||
|
@ -582,6 +623,11 @@ export default class ObjectTree extends BaseClass {
|
|||
const isExpanded = treeDOM.isExpanded(node.key)
|
||||
treeDOM.setExpanded(node.key, !isExpanded)
|
||||
}
|
||||
|
||||
determineNodeColor (node: {color: string, isTag: boolean, isRoot: boolean}) {
|
||||
// @ts-ignore
|
||||
return (node?.isTag && node?.isRoot) ? colors.getBrand("primary") : node.color
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -47,6 +47,17 @@
|
|||
<q-item-section>
|
||||
<q-item-label v-html="opt.label" ></q-item-label>
|
||||
<q-item-label caption class="text-cultured" v-html="opt.hierarchicalPath"></q-item-label>
|
||||
<q-item-label caption class="text-cultured" v-if="opt.tags">
|
||||
<q-chip
|
||||
v-for="(input,index) in opt.tags" :key="index"
|
||||
outline
|
||||
style="opacity: 0.8;"
|
||||
size="12px"
|
||||
class="bg-dark text-cultured"
|
||||
v-html="`${input}`"
|
||||
>
|
||||
</q-chip>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-btn
|
||||
tabindex="-1"
|
||||
|
@ -127,6 +138,7 @@ export default class ExistingDocumentDialog extends DialogBase {
|
|||
type: doc.type,
|
||||
// @ts-ignore
|
||||
hierarchicalPath: this.getDocumentHieararchicalPath(doc, dbDocuments.rows),
|
||||
tags: doc.extraFields.find(e => e.id === "tags")?.value,
|
||||
color: doc.extraFields.find(e => e.id === "documentColor")?.value,
|
||||
isCategory: doc.extraFields.find(e => e.id === "categorySwitch")?.value
|
||||
} as unknown as I_ShortenedDocument
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
ref="ref_newDocument"
|
||||
style="flex-grow: 1;"
|
||||
dense
|
||||
menu-anchor="bottom middle"
|
||||
menu-self="top middle"
|
||||
class="newDocumentSelect"
|
||||
:options="filteredNewInput"
|
||||
use-input
|
||||
|
@ -101,7 +103,7 @@ export default class NewDocumentDialog extends DialogBase {
|
|||
setTimeout( () =>{
|
||||
// @ts-ignore
|
||||
this.$refs.ref_newDocument.focus()
|
||||
}, 100)
|
||||
}, 300)
|
||||
/* eslint-enable */
|
||||
})
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
v-if="editMode"
|
||||
style="width: 100%;"
|
||||
dense
|
||||
dark
|
||||
menu-anchor="bottom middle"
|
||||
menu-self="top middle"
|
||||
class="multiSelect"
|
||||
:options="extraInput"
|
||||
use-input
|
||||
outlined
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
v-if="editMode"
|
||||
style="width: 100%;"
|
||||
dense
|
||||
dark
|
||||
menu-anchor="bottom middle"
|
||||
menu-self="top middle"
|
||||
class="singleSelect"
|
||||
:options="extraInput"
|
||||
use-input
|
||||
outlined
|
||||
|
|
127
src/components/fields/Field_Tags.vue
Normal file
127
src/components/fields/Field_Tags.vue
Normal file
|
@ -0,0 +1,127 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="flex justify-start items-center text-weight-bolder q-mb-sm q-mt-md">
|
||||
<q-icon v-if="inputIcon" :name="inputIcon" :size="inputIcon.includes('fas')? '15px': '20px'" class="q-mr-md"/>
|
||||
{{inputDataBluePrint.name}}
|
||||
<q-icon v-if="toolTip" name="mdi-help-circle" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
<span v-html="toolTip"/>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!editMode"
|
||||
>
|
||||
<q-chip
|
||||
v-for="(input,index) in localInput" :key="index"
|
||||
color="primary" text-color="white" class="text-bold">
|
||||
{{input}}
|
||||
</q-chip>
|
||||
</div>
|
||||
|
||||
<q-select
|
||||
v-if="editMode"
|
||||
style="width: 100%;"
|
||||
dense
|
||||
dark
|
||||
menu-anchor="bottom middle"
|
||||
menu-self="top middle"
|
||||
class="tagSelect"
|
||||
:options="allTags"
|
||||
use-input
|
||||
outlined
|
||||
use-chips
|
||||
@filter="filterFn"
|
||||
input-debounce="0"
|
||||
new-value-mode="add"
|
||||
multiple
|
||||
v-model="localInput"
|
||||
@input="signalInput"
|
||||
@keydown="signalInput"
|
||||
>
|
||||
</q-select>
|
||||
|
||||
<div class="separatorWrapper">
|
||||
<q-separator color="grey q-mt-lg" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import { tagListBuildFromBlueprints } from "src/scripts/utilities/tagListBuilder"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Tags extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: []
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput = []
|
||||
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue) ? this.inputDataValue : []
|
||||
}
|
||||
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.buildTagList().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
|
||||
allTags: string[] = []
|
||||
|
||||
filterFn (val: string, update: (fn: any) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
this.allTags = this.inputDataBluePrint.predefinedSelectValues
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
update(() => {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
const needle = val.toLowerCase()
|
||||
this.allTags = this.inputDataBluePrint.predefinedSelectValues.filter(v => v.toLowerCase().indexOf(needle) > -1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async buildTagList () {
|
||||
this.allTags = await tagListBuildFromBlueprints(this.SGET_allBlueprints)
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -66,6 +66,9 @@ body {
|
|||
left: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.tagSelect,
|
||||
.singleSelect,
|
||||
.multiSelect,
|
||||
.singleRelashionshipSelect,
|
||||
.multiRelashionshipSelect,
|
||||
.existingDocumentSelect,
|
||||
|
@ -89,7 +92,7 @@ body {
|
|||
}
|
||||
|
||||
.q-position-engine {
|
||||
overflow-y: scroll !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.text-underline {
|
||||
|
|
|
@ -19,7 +19,8 @@ export interface I_ExtraFields {
|
|||
"singleToManyRelationship" |
|
||||
"manyToSingleRelationship" |
|
||||
"manyToManyRelationship" |
|
||||
"break"
|
||||
"break" |
|
||||
"tags"
|
||||
|
||||
predefinedListExtras?: {
|
||||
affix?: string
|
||||
|
|
|
@ -29,6 +29,7 @@ export interface I_ShortenedDocument{
|
|||
children: I_ShortenedDocument[]
|
||||
extraFields: I_ExtraDocumentFields[]
|
||||
color?: string
|
||||
tags?: string[]
|
||||
|
||||
activeTypeSearch?: boolean
|
||||
filteredOut?: boolean
|
||||
|
|
|
@ -171,6 +171,16 @@
|
|||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_Tags
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'tags' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -202,7 +212,7 @@ import Field_MultiSelect from "src/components/fields/Field_MultiSelect.vue"
|
|||
import Field_SingleRelationship from "src/components/fields/Field_SingleRelationship.vue"
|
||||
import Field_MultiRelationship from "src/components/fields/Field_MultiRelationship.vue"
|
||||
import Field_Wysiwyg from "src/components/fields/Field_Wysiwyg.vue"
|
||||
import console from "console"
|
||||
import Field_Tags from "src/components/fields/Field_Tags.vue"
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -216,7 +226,8 @@ import console from "console"
|
|||
Field_MultiSelect,
|
||||
Field_SingleRelationship,
|
||||
Field_MultiRelationship,
|
||||
Field_Wysiwyg
|
||||
Field_Wysiwyg,
|
||||
Field_Tags
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -397,6 +408,18 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
// FIELD - Tags
|
||||
if (field.type === "tags") {
|
||||
this.currentData.hasEdits = true
|
||||
const indexToUpdate = this.currentData.extraFields.findIndex(s => s.id === field.id)
|
||||
this.currentData.extraFields[indexToUpdate].value = inputData
|
||||
|
||||
const dataCopy: I_OpenedDocument = extend(true, {}, this.currentData)
|
||||
|
||||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
}
|
||||
|
||||
toggleEditMode () {
|
||||
|
|
|
@ -62,6 +62,16 @@ export const chaptersBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "content",
|
||||
name: "Chapter content",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const charactersBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const currenciesBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const eventsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const itemsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const languagesBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const locationsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -62,6 +62,16 @@ export const loreNotesBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "notes",
|
||||
name: "Note list",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const magicBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const mythsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const politicalGroupsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const racesBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const religionsBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -68,6 +68,16 @@ export const techBlueprint: I_Blueprint = {
|
|||
`,
|
||||
sizing: 2
|
||||
},
|
||||
{
|
||||
id: "tags",
|
||||
name: "Tags",
|
||||
type: "tags",
|
||||
icon: "mdi-tag",
|
||||
tooltip:
|
||||
`tags
|
||||
`,
|
||||
sizing: 12
|
||||
},
|
||||
{
|
||||
id: "otherNames",
|
||||
name: "Other names & Epithets",
|
||||
|
|
|
@ -40,20 +40,20 @@ export const advancedDocumentFilter = (inputString: string, documentList: I_Shor
|
|||
const searchWordList = inputString.toLowerCase().split(" ")
|
||||
|
||||
let categorySeach = false as unknown as string
|
||||
let tagSeach = false as unknown as string
|
||||
let tagSearch = false as unknown as string
|
||||
let typeSeach = false as unknown as string
|
||||
|
||||
const categorySeachIndex = searchWordList.findIndex(w => w.charAt(0) === ">")
|
||||
const tagSeachIndex = searchWordList.findIndex(w => w.charAt(0) === "#")
|
||||
const tagSearchIndex = searchWordList.findIndex(w => w.charAt(0) === "#")
|
||||
const typeSeachIndex = searchWordList.findIndex(w => w.charAt(0) === "$")
|
||||
|
||||
if (categorySeachIndex >= 0) {
|
||||
categorySeach = searchWordList[categorySeachIndex].substring(1)
|
||||
searchWordList[categorySeachIndex] = ""
|
||||
}
|
||||
if (tagSeachIndex >= 0) {
|
||||
tagSeach = searchWordList[tagSeachIndex].substring(1)
|
||||
searchWordList[tagSeachIndex] = ""
|
||||
if (tagSearchIndex >= 0) {
|
||||
tagSearch = searchWordList[tagSearchIndex].substring(1)
|
||||
searchWordList[tagSearchIndex] = ""
|
||||
}
|
||||
if (typeSeachIndex >= 0) {
|
||||
typeSeach = searchWordList[typeSeachIndex].substring(1)
|
||||
|
@ -67,7 +67,7 @@ export const advancedDocumentFilter = (inputString: string, documentList: I_Shor
|
|||
/****************************************************************/
|
||||
|
||||
if (categorySeach) {
|
||||
documentList = documentList.filter((doc, index) => {
|
||||
documentList = documentList.filter(doc => {
|
||||
let stringPath = doc.hierarchicalPath as unknown as string
|
||||
stringPath = stringPath.toLowerCase()
|
||||
stringPath = stringPath.replace(/>/gi, "")
|
||||
|
@ -75,12 +75,36 @@ export const advancedDocumentFilter = (inputString: string, documentList: I_Shor
|
|||
stringPath = stringPath.replace(/ /gi, "-")
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
doc.hierarchicalPath = `<span class="text-primary">${doc.hierarchicalPath}</span>`
|
||||
doc.hierarchicalPath = `<span class="text-primary text-bold">${doc.hierarchicalPath}</span>`
|
||||
|
||||
return (stringPath.includes(categorySeach))
|
||||
})
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Tag filter
|
||||
/****************************************************************/
|
||||
if (tagSearch) {
|
||||
documentList = documentList.filter(doc => {
|
||||
let matchFound = false
|
||||
|
||||
if (doc.tags) {
|
||||
doc.tags.forEach((tag, index) => {
|
||||
const ogTag = tag
|
||||
tag = tag.toLowerCase()
|
||||
tag = tag.replace(/>/gi, "")
|
||||
tag = tag.replace(/ {2}/gi, "-")
|
||||
tag = tag.replace(/ /gi, "-")
|
||||
if (tag.includes(tagSearch)) {
|
||||
// @ts-ignore
|
||||
doc.tags[index] = `<span class="text-primary text-bold">${ogTag}</span>`
|
||||
}
|
||||
matchFound = (tag.includes(tagSearch) || matchFound)
|
||||
})
|
||||
}
|
||||
return matchFound
|
||||
})
|
||||
}
|
||||
/****************************************************************/
|
||||
// Type filter
|
||||
/****************************************************************/
|
||||
|
@ -148,13 +172,21 @@ export const advancedDocumentFilter = (inputString: string, documentList: I_Shor
|
|||
// Color the word if they were found
|
||||
documentWordListColoring = documentWordListColoring.map(docWord => {
|
||||
if (foundWordList.includes(docWord.toLowerCase())) {
|
||||
return `<span class="text-primary text-underline">${docWord}</span>`
|
||||
return `<span class="text-primary text-bold">${docWord}</span>`
|
||||
}
|
||||
return docWord
|
||||
})
|
||||
doc.label = documentWordListColoring.join(" ")
|
||||
})
|
||||
|
||||
// Cover case of exact match
|
||||
documentList.map(doc => {
|
||||
if (doc.exactMatch) {
|
||||
doc.label = `<span class="text-primary text-bold">${doc.label}</span>`
|
||||
}
|
||||
return doc
|
||||
})
|
||||
|
||||
/****************************************************************/
|
||||
// Sorting
|
||||
/****************************************************************/
|
||||
|
|
32
src/scripts/utilities/tagListBuilder.ts
Normal file
32
src/scripts/utilities/tagListBuilder.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { I_Blueprint } from "./../../interfaces/I_Blueprint"
|
||||
import PouchDB from "pouchdb"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
|
||||
/**
|
||||
* Build a tag list of all know database documents
|
||||
*/
|
||||
export const tagListBuildFromBlueprints = async (blueprintList: I_Blueprint[]) => {
|
||||
let allTags: string[] = []
|
||||
for (const blueprint of blueprintList) {
|
||||
const CurrentObjectDB = new PouchDB(blueprint._id)
|
||||
|
||||
const dbDocuments = await CurrentObjectDB.allDocs({ include_docs: true })
|
||||
const docsTagsArray = dbDocuments.rows.map(singleDocument => {
|
||||
const doc = singleDocument.doc as unknown as I_ShortenedDocument
|
||||
const tags: string[] = doc.extraFields.find(e => e.id === "tags")?.value
|
||||
|
||||
return (tags) || []
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
allTags = [...allTags, ...docsTagsArray] as unknown as string[]
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
allTags = allTags.flat()
|
||||
|
||||
return [...new Set([
|
||||
...allTags
|
||||
])].sort((a, b) => a.localeCompare(b))
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"baseUrl": ".",
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
|
|
Loading…
Reference in a new issue