0.1.6 - reworked data handling across whole app

This commit is contained in:
Elvanos 2021-04-25 23:01:41 +02:00
parent ee97ccfa42
commit 3d93792c80
36 changed files with 1206 additions and 680 deletions

View file

@ -1,6 +1,6 @@
{
"name": "fantasiaarchive",
"version": "0.1.5",
"version": "0.1.6",
"description": "A database manager for world building",
"productName": "Fantasia Archive",
"author": "Elvanos <elvanos66@gmail.com>",

View file

@ -7,10 +7,10 @@
no-resize
dark
title="Advanced Search Cheatsheet"
:height="480"
:height="510"
:width="425"
:start-x="50"
:start-y="150"
:start-y="150"
:actions="['close']"
content-class="bg-gunmetal-light text-accent advSearchWindow"
>

View file

@ -8,9 +8,9 @@ import { I_NewObjectTrigger } from "src/interfaces/I_NewObjectTrigger"
import { uid, colors, extend } from "quasar"
import { I_FieldRelationship } from "src/interfaces/I_FieldRelationship"
import { I_KeyPressObject } from "src/interfaces/I_KeypressObject"
import PouchDB from "pouchdb"
const Blueprints = namespace("blueprintsModule")
const AllDocuments = namespace("allDocumentsModule")
const OpenedDocuments = namespace("openedDocumentsModule")
const Keybinds = namespace("keybindsModule")
const Options = namespace("optionsModule")
@ -317,6 +317,57 @@ export default class BaseClass extends Vue {
this.SSET_options(optionsSnapshot)
}
/****************************************************************/
// ALL DOCUMENTS MANAGEMENT
/****************************************************************/
@AllDocuments.Getter("getFirstRunState") SGET_allDocumentsFirstRunState!: boolean
@AllDocuments.Action("markAsNonFirstRun") SSET_allDocumentsMarkAsNonFirstRun!: () => void
@AllDocuments.Getter("getAllDocuments") SGET_allDocuments !: {
timestamp: string,
docs: I_ShortenedDocument[]
}
@AllDocuments.Getter("getAllDocumentsWithoutCategories") SGET_allDocumentsWithoutCategories !: {
timestamp: string,
docs: I_ShortenedDocument[]
}
@AllDocuments.Getter("getDocumentsByType") SGET_allDocumentsByType!: (documentTypeID: string) => {
timestamp: string,
id: string,
docs: I_ShortenedDocument[]
}
@AllDocuments.Getter("getDocumentsByTypeWithoutCategories") SGET_allDocumentsByTypeWithoutCategories!: (documentTypeID: string) => {
timestamp: string,
id: string,
docs: I_ShortenedDocument[]
}
@AllDocuments.Getter("getDocument") SGET_document!: (id: string) => I_ShortenedDocument
@AllDocuments.Action("addDocument") SSET_addDocument!: (input: {
doc: I_ShortenedDocument
}) => void
@AllDocuments.Action("updateDocument") SSET_updateDocument!: (input: {
doc: I_ShortenedDocument
}) => void
@AllDocuments.Action("removeDocument") SSET_removeDocument!: (input: {
doc: I_ShortenedDocument
}) => void
@AllDocuments.Action("mapNewDocumentType") SSET_mapNewDocumentType!: (input: {
id: string,
docs: I_ShortenedDocument[]
}) => void
@AllDocuments.Action("resetDocuments") SSET_resetAllDocuments!: () => void
/****************************************************************/
// OPEN DOCUMENTS MANAGEMENT
/****************************************************************/
@ -372,7 +423,7 @@ export default class BaseClass extends Vue {
* @param document - Document object that is expected to contain the field
* @param fieldID - ID of the field to check
*/
retrieveFieldValue (document: I_OpenedDocument, fieldID: string) : string | number | [] | false | I_FieldRelationship {
retrieveFieldValue (document: I_OpenedDocument| I_ShortenedDocument, fieldID: string) : string | number | [] | false | I_FieldRelationship {
const fieldData = document?.extraFields
// Fizzle if field doesnt exist
@ -491,46 +542,43 @@ export default class BaseClass extends Vue {
return hierarchicalString
}
/**
* Retieves ALL documents
*/
async retrieveAllDocuments () {
let allDocs = [] as I_ShortenedDocument[]
for (const blueprint of this.SGET_allBlueprints) {
const CurrentObjectDB = new PouchDB(blueprint._id)
const dbRows = await CurrentObjectDB.allDocs({ include_docs: true })
const dbDocuments = dbRows.rows.map(d => d.doc)
const formattedDocuments: I_ShortenedDocument[] = []
for (const singleDocument of dbDocuments) {
const doc = singleDocument as unknown as I_ShortenedDocument
const pushValue = {
label: doc.extraFields.find(e => e.id === "name")?.value,
icon: doc.icon,
id: doc._id,
url: doc.url,
type: doc.type,
extraFields: doc.extraFields,
// @ts-ignore
hierarchicalPath: this.getDocumentHieararchicalPath(doc, dbDocuments),
tags: doc.extraFields.find(e => e.id === "tags")?.value,
color: doc.extraFields.find(e => e.id === "documentColor")?.value,
bgColor: doc.extraFields.find(e => e.id === "documentBackgroundColor")?.value,
isCategory: doc.extraFields.find(e => e.id === "categorySwitch")?.value,
isMinor: doc.extraFields.find(e => e.id === "minorSwitch")?.value,
isDead: doc.extraFields.find(e => e.id === "deadSwitch")?.value
} as unknown as I_ShortenedDocument
formattedDocuments.push(pushValue)
}
const sortedDocuments = formattedDocuments.sort((a, b) => a.label.localeCompare(b.label))
mapShortDocument (doc: I_ShortenedDocument, dbDocuments: I_OpenedDocument[]) : I_ShortenedDocument {
return {
label: doc.extraFields.find(e => e.id === "name")?.value,
icon: doc.icon,
// @ts-ignore
allDocs = [...allDocs, ...sortedDocuments]
id: doc._id,
_id: doc._id,
url: doc.url,
type: doc.type,
extraFields: doc.extraFields,
hasEdits: false,
// @ts-ignore
hierarchicalPath: this.getDocumentHieararchicalPath(doc, dbDocuments),
tags: doc.extraFields.find(e => e.id === "tags")?.value,
color: doc.extraFields.find(e => e.id === "documentColor")?.value,
bgColor: doc.extraFields.find(e => e.id === "documentBackgroundColor")?.value,
isCategory: doc.extraFields.find(e => e.id === "categorySwitch")?.value,
isMinor: doc.extraFields.find(e => e.id === "minorSwitch")?.value,
isDead: doc.extraFields.find(e => e.id === "deadSwitch")?.value
await CurrentObjectDB.close()
}
return allDocs
}
deepFreeze (object: object) {
// Retrieve the property names defined on object
const propNames = Object.getOwnPropertyNames(object)
// Freeze properties before freezing self
for (const name of propNames) {
const value = object[name]
if (value && typeof value === "object") {
this.deepFreeze(value)
}
}
return Object.freeze(object)
}
}

View file

@ -178,7 +178,7 @@
color="primary"
outline
@click="toggleEditMode"
v-if="currentyEditable && SGET_allOpenedDocuments.docs.length > 0"
v-if="currentyEditable && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -194,7 +194,7 @@
:color="(!hasEdits) ? 'teal-14' : 'primary'"
outline
@click="saveCurrentDocument(true)"
v-if="!currentyEditable && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentyEditable && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -211,7 +211,7 @@
:color="(!hasEdits) ? 'teal-14' : 'primary'"
outline
@click="saveCurrentDocument(false)"
v-if="!currentyEditable && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentyEditable && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -228,7 +228,7 @@
color="primary"
outline
@click="addNewUnderParent"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -245,7 +245,7 @@
color="primary"
outline
@click="copyTargetDocument"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -258,7 +258,7 @@
</q-btn>
<q-separator vertical inset color="accent"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
/>
<q-btn
@ -266,7 +266,7 @@
color="secondary"
outline
@click="deleteObjectAssignUID"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
>
<q-tooltip
:delay="500"
@ -357,33 +357,33 @@ export default class DocumentControl extends BaseClass {
}
// Delete dialog - CTRL + D
if (this.determineKeyBind("deleteDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
if (this.determineKeyBind("deleteDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
this.deleteObjectAssignUID()
}
// Edit document - CTRL + E
if (this.determineKeyBind("editDocument") && this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
if (this.determineKeyBind("editDocument") && this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
this.toggleEditMode()
}
// Save document - CTRL + S
if (this.determineKeyBind("saveDocument") && !this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
if (this.determineKeyBind("saveDocument") && !this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
this.saveCurrentDocument(false).catch(e => console.log(e))
}
// Save document without exiting edit mode - CTRL + ALT + S
if (this.determineKeyBind("saveDocumentNoExit") && !this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
if (this.determineKeyBind("saveDocumentNoExit") && !this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
this.saveCurrentDocument(true).catch(e => console.log(e))
}
// Add new under parent - CTRL + SHIFT + N
if (this.determineKeyBind("addUnderParent") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
if (this.determineKeyBind("addUnderParent") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
await this.sleep(100)
this.addNewUnderParent()
}
// Add new under parent - CTRL + ALT + C
if (this.determineKeyBind("copyDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
// Copy document - CTRL + ALT + C
if (this.determineKeyBind("copyDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
await this.sleep(100)
this.copyTargetDocument()
}
@ -559,17 +559,22 @@ export default class DocumentControl extends BaseClass {
const savedDocument: {
documentCopy: I_OpenedDocument,
allOpenedDocuments: I_OpenedDocument[]
} = await saveDocument(currentDoc, this.documentsCopy, editMode)
} = await saveDocument(currentDoc, this.documentsCopy, this.SGET_allDocuments.docs, editMode).catch(err => console.log(err))
// Update the opened document
const dataPass = { doc: savedDocument.documentCopy, treeAction: true }
this.SSET_updateOpenedDocument(dataPass)
// @ts-ignore
this.SSET_updateDocument({ doc: this.mapShortDocument(savedDocument.documentCopy, this.SGET_allDocumentsByType(savedDocument.documentCopy.type).docs) })
// Update all others
for (const doc of savedDocument.allOpenedDocuments) {
// Update the opened document
const dataPass = { doc: doc, treeAction: true }
this.SSET_updateOpenedDocument(dataPass)
// @ts-ignore
this.SSET_updateDocument({ doc: this.mapShortDocument(doc, this.SGET_allDocumentsByType(doc.type).docs) })
}
this.$q.notify({
@ -699,4 +704,12 @@ export default class DocumentControl extends BaseClass {
}
}
}
html body {
&.q-body--prevent-scroll {
.documentControl {
min-width: calc(100vw - 375px);
}
}
}
</style>

View file

@ -50,7 +50,7 @@
no-connectors
ref="tree"
dark
:duration="200"
:duration="0"
:filter="treeFilter"
:selected.sync="selectedTreeNode"
:expanded.sync="expandedTreeNodes"
@ -81,7 +81,7 @@
<span
class="text-grey-5 text-weight-medium q-ml-xs"
v-if="(prop.node.isRoot || prop.node.isTag) && !disableDocumentCounts">
<span v-html="determineCatyegoryString(prop.node)"/>
<span v-html="determineCategoryString(prop.node)"/>
<q-tooltip
:delay="500"
>
@ -290,7 +290,6 @@ import { Component, Watch } from "vue-property-decorator"
import BaseClass from "src/BaseClass"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import PouchDB from "pouchdb"
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
import { extend, colors } from "quasar"
@ -377,23 +376,7 @@ export default class ObjectTree extends BaseClass {
this.hideTreeIconAddUnder = options.hideTreeIconAddUnder
this.hideTreeIconEdit = options.hideTreeIconEdit
this.hideTreeIconView = options.hideTreeIconView
this.buildCurrentObjectTree().catch((e) => {
console.log(e)
})
}
/****************************************************************/
// BLUEPRINT MANAGEMENT
/****************************************************************/
/**
* In case any of the blueprints change, reload the whole tree
*/
@Watch("SGET_allBlueprints", { deep: true })
reactToBluePrintRefresh () {
this.buildCurrentObjectTree().catch((e) => {
console.log(e)
})
this.buildCurrentObjectTree()
}
/****************************************************************/
@ -417,9 +400,9 @@ export default class ObjectTree extends BaseClass {
*
*/
@Watch("SGET_allOpenedDocuments", { deep: true })
async reactToDocumentListChange (val: { treeAction: boolean, docs: I_OpenedDocument[]}) {
reactToDocumentListChange (val: { treeAction: boolean, docs: I_OpenedDocument[]}) {
if (val.treeAction) {
await this.buildCurrentObjectTree()
this.buildCurrentObjectTree()
this.buildTreeExpands(val?.docs)
this.lastDocsSnapShot = extend(true, [], val.docs)
}
@ -430,6 +413,26 @@ export default class ObjectTree extends BaseClass {
lastDocsSnapShot:I_OpenedDocument[] = []
/**
*
*/
@Watch("SGET_allDocuments", { deep: true })
reactToAllDocumentListChange (val: { docs: I_OpenedDocument[]}) {
if (!this.SGET_allDocumentsFirstRunState) {
this.buildCurrentObjectTree()
}
}
/**
*
*/
@Watch("SGET_allDocumentsFirstRunState")
reactToFirstRunFinish (val: boolean) {
if (!val) {
this.buildCurrentObjectTree()
}
}
/**
* Generic wrapper for adding of new object types to the tree
*/
@ -562,52 +565,50 @@ export default class ObjectTree extends BaseClass {
/**
* Builds a brand new sparkling hearchy tree out of available data
*/
async buildCurrentObjectTree () {
buildCurrentObjectTree () {
const allBlueprings = this.SGET_allBlueprints
let 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) {
const CurrentObjectDB = new PouchDB(blueprint._id)
const allDocuments = this.SGET_allDocumentsByType(blueprint._id)
let allDocumentsRows: I_ShortenedDocument[] = []
const allDocuments = await CurrentObjectDB.allDocs({ include_docs: true })
if (allDocuments && allDocuments.docs) {
allDocumentsRows = allDocuments.docs
.map((doc) => {
const parentDocID = doc.extraFields.find(e => e.id === "parentDoc")?.value.value as unknown as {_id: string}
const color = doc.extraFields.find(e => e.id === "documentColor")?.value as unknown as string
const bgColor = doc.extraFields.find(e => e.id === "documentBackgroundColor")?.value as unknown as string
const allDocumentsRows = allDocuments.rows
.map((singleDocument) => {
const doc = singleDocument.doc as unknown as I_ShortenedDocument
const parentDocID = doc.extraFields.find(e => e.id === "parentDoc")?.value.value as unknown as {_id: string}
const color = doc.extraFields.find(e => e.id === "documentColor")?.value as unknown as string
const bgColor = doc.extraFields.find(e => e.id === "documentBackgroundColor")?.value as unknown as string
const isCategory = doc.extraFields.find(e => e.id === "categorySwitch")?.value as unknown as boolean
const isMinor = doc.extraFields.find(e => e.id === "minorSwitch")?.value as unknown as boolean
const isDead = doc.extraFields.find(e => e.id === "deadSwitch")?.value as unknown as boolean
return {
label: doc.extraFields.find(e => e.id === "name")?.value,
icon: (isCategory) ? "fas fa-folder-open" : doc.icon,
isCategory: !!(isCategory),
isMinor: isMinor,
isDead: isDead,
sticker: doc.extraFields.find(e => e.id === "order")?.value,
parentDoc: (parentDocID) ? parentDocID._id : false,
handler: this.openExistingDocumentRoute,
expandable: true,
color: color,
bgColor: bgColor,
type: doc.type,
children: [],
hasEdits: false,
isNew: false,
url: doc.url,
extraFields: (doc?.extraFields) || [],
_id: singleDocument.id,
key: singleDocument.id
} as I_ShortenedDocument
})
const isCategory = doc.extraFields.find(e => e.id === "categorySwitch")?.value as unknown as boolean
const isMinor = doc.extraFields.find(e => e.id === "minorSwitch")?.value as unknown as boolean
const isDead = doc.extraFields.find(e => e.id === "deadSwitch")?.value as unknown as boolean
return {
label: doc.extraFields.find(e => e.id === "name")?.value,
icon: (isCategory) ? "fas fa-folder-open" : doc.icon,
isCategory: !!(isCategory),
isMinor: isMinor,
isDead: isDead,
sticker: doc.extraFields.find(e => e.id === "order")?.value,
parentDoc: (parentDocID) ? parentDocID._id : false,
handler: this.openExistingDocumentRoute,
expandable: true,
color: color,
bgColor: bgColor,
type: doc.type,
children: [],
hasEdits: false,
isNew: false,
url: doc.url,
extraFields: (doc?.extraFields) || [],
_id: doc._id,
key: doc._id
} as I_ShortenedDocument
})
}
const documentCount = allDocumentsRows.filter(e => !e.isCategory).length
const categoryCount = allDocumentsRows.filter(e => e.isCategory).length
const allCount = allDocumentsRows.length
@ -645,8 +646,6 @@ export default class ObjectTree extends BaseClass {
}
treeObject.push(treeRow)
await CurrentObjectDB.close()
}
// Sort the top level of the blueprints
@ -662,7 +661,7 @@ export default class ObjectTree extends BaseClass {
})
if (!this.noTags) {
const tagList = await tagListBuildFromBlueprints(this.SGET_allBlueprints)
const tagList = tagListBuildFromBlueprints(this.SGET_allDocuments.docs)
let allTags = 0
let allTagsCategories = 0
@ -735,7 +734,17 @@ export default class ObjectTree extends BaseClass {
}
// Assign the finished object to the render model
this.hierarchicalTree = treeObject
treeObject.forEach(cat => this.recursivelyFreezeChildren(cat.children))
// @ts-ignore
this.hierarchicalTree = Object.freeze(treeObject)
}
recursivelyFreezeChildren (children: {children: []}) {
Object.freeze(children)
if (children.children) {
// @ts-ignore
this.recursivelyFreezeChildren(children.children)
}
}
processNodeNewDocumentButton (node: {
@ -962,7 +971,7 @@ export default class ObjectTree extends BaseClass {
}
}
determineCatyegoryString (node: {
determineCategoryString (node: {
documentCount: string
categoryCount: string
}) {

View file

@ -42,7 +42,7 @@
import { Component, Watch, Prop } from "vue-property-decorator"
import DialogBase from "src/components/dialogs/_DialogBase"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import PouchDB from "pouchdb"
@Component({
@ -53,7 +53,7 @@ export default class DeleteDocumentCheckDialog extends DialogBase {
* React to dialog opening request
*/
@Watch("dialogTrigger")
async openDialog (val: string|false) {
openDialog (val: string|false) {
if (val && (this.SGET_allOpenedDocuments.docs.length > 0 || (this.documentType.length > 0 && this.documentId.length > 0))) {
if (this.SGET_getDialogsState) {
return
@ -61,12 +61,9 @@ export default class DeleteDocumentCheckDialog extends DialogBase {
this.SSET_setDialogState(true)
this.dialogModel = true
const documentType = (this.documentType.length > 0) ? this.documentType : this.$route.params.type
const documentID = (this.documentId.length > 0) ? this.documentId : this.$route.params.id
const CurrentObjectDB = new PouchDB(documentType)
this.currentDocument = await CurrentObjectDB.get(documentID)
await CurrentObjectDB.close()
this.currentDocument = this.SGET_document(documentID)
}
}
@ -85,25 +82,27 @@ export default class DeleteDocumentCheckDialog extends DialogBase {
/**
* Current document for deletion
*/
currentDocument = false as unknown as I_OpenedDocument
currentDocument = false as unknown as I_ShortenedDocument
/**
* Delete the document
*/
async deleteDocument () {
const documentType = (this.documentType.length > 0) ? this.documentType : this.$route.params.type
const CurrentObjectDB = new PouchDB(documentType)
window.FA_dbs[documentType] = new PouchDB(documentType)
// @ts-ignore
await CurrentObjectDB.remove(this.currentDocument)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[documentType].remove(this.currentDocument)
const dataPass = { doc: this.currentDocument, treeAction: true }
this.dialogModel = false
this.SSET_setDialogState(false)
// @ts-ignore
this.SSET_removeOpenedDocument(dataPass)
await CurrentObjectDB.close()
// @ts-ignore
this.SSET_removeDocument({ doc: this.mapShortDocument(this.currentDocument, this.SGET_allDocumentsByType(this.currentDocument.type)) })
}
}
</script>

View file

@ -216,7 +216,6 @@ import { Component, Watch } from "vue-property-decorator"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
import { extend } from "quasar"
import PouchDB from "pouchdb"
import { createNewWithParent } from "src/scripts/documentActions/createNewWithParent"
import { copyDocumentName, copyDocumentTextColor, copyDocumentBackgroundColor } from "src/scripts/documentActions/uniqueFieldCopy"
@ -373,13 +372,14 @@ export default class ExistingDocumentDialog extends DialogBase {
async populateExistingObjectDialog () {
this.allDocumentBluePrints = this.SGET_allBlueprints
this.existingObjectsFullList = await this.retrieveAllDocuments()
this.existingObjectsFullList = this.SGET_allDocuments.docs
this.preFilterDocuments()
await this.$nextTick()
if (this.$refs.ref_existingDocument) {
/*eslint-disable */
await this.sleep(100)
// @ts-ignore
this.$refs.ref_existingDocument.focus()
/* eslint-enable */
@ -449,7 +449,7 @@ export default class ExistingDocumentDialog extends DialogBase {
* Either as a focus with closure of the dialog.
* Or as a background tab without closing of the dialog.
*/
async openExistingInput (e: I_ShortenedDocument) {
openExistingInput (e: I_ShortenedDocument) {
// @ts-ignore
e = (Array.isArray(e)) ? e[0] : e
// Open document and close dialog
@ -461,12 +461,11 @@ export default class ExistingDocumentDialog extends DialogBase {
}
// Open document and DO NOT close the dialog
else {
// @ts-ignore
this.existingDocumentModel = []
const CurrentObjectDB = new PouchDB(e.type)
// @ts-ignore
const retrievedObject = await CurrentObjectDB.get(e.id)
const retrievedObject = (this.SGET_openedDocument(e._id)) || this.SGET_document(e._id)
console.log(retrievedObject)
const dataPass = {
doc: retrievedObject,
@ -475,7 +474,6 @@ export default class ExistingDocumentDialog extends DialogBase {
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
await CurrentObjectDB.close()
}
}
@ -484,7 +482,7 @@ export default class ExistingDocumentDialog extends DialogBase {
* Either as a focus with closure of the dialog.
* Or as a background tab without closing of the dialog.
*/
async editExistingInput (e: I_ShortenedDocument) {
editExistingInput (e: I_ShortenedDocument) {
// @ts-ignore
e = (Array.isArray(e)) ? e[0] : e
// Open document and close dialog
@ -499,11 +497,8 @@ export default class ExistingDocumentDialog extends DialogBase {
// @ts-ignore
this.existingDocumentModel = []
const CurrentObjectDB = new PouchDB(e.type)
// @ts-ignore
const retrievedObject = await CurrentObjectDB.get(e.id)
const retrievedObject = (this.SGET_openedDocument(e._id)) || this.SGET_document(e._id)
// @ts-ignore
retrievedObject.hasEdits = true
const dataPass = {
@ -513,7 +508,6 @@ export default class ExistingDocumentDialog extends DialogBase {
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
await CurrentObjectDB.close()
}
}

View file

@ -1,5 +1,6 @@
<template>
<q-dialog
no-route-dismiss
v-model="dialogModel"
@hide="triggerDialogClose"
>

View file

@ -26,6 +26,8 @@
style="width: 400px;"
label="New project name"
v-model="newProjectName"
:error="isInvalid && newProjectName.length > 0"
:error-message="'Your project name contains invalid characters'"
/>
</div>
@ -47,7 +49,7 @@
<q-btn
flat
label="Create new project"
:disable="newProjectName.length === 0"
:disable="isInvalid"
color="primary"
v-close-popup
@click="createNewProject" />
@ -100,6 +102,40 @@ export default class ImportProjectCheckDialog extends DialogBase {
*/
newProjectName = ""
reservedCharacterList = [
"/",
">",
"<",
"|",
":",
"&",
"\\",
"-",
"[",
"]",
"{",
"}",
"*",
"?",
"'",
"\""
]
get isInvalid () {
let isValid = true
if (this.newProjectName.length === 0) {
isValid = false
}
this.reservedCharacterList.forEach(char => {
if (this.newProjectName.includes(char)) {
isValid = false
}
})
return !isValid
}
/**
* Create new project
*/
@ -136,9 +172,14 @@ export default class ImportProjectCheckDialog extends DialogBase {
}
</script>
<style lang="scss" scoped>
<style lang="scss">
.newProjectCheckDialog {
min-width: 600px;
.q-field__messages {
font-weight: 600;
font-size: 14px;
}
}
</style>

View file

@ -144,6 +144,7 @@
:ref="`multieRelationshipField${this.inputDataBluePrint.id}`"
:options="filterList"
use-input
:option-disable="opt => Object(opt) === opt ? disabledIDList.includes(opt._id) : true"
:outlined="!isDarkMode"
:filled="isDarkMode"
use-chips
@ -151,7 +152,7 @@
input-debounce="200"
v-model="localInput"
@filter="filterSelect"
@input="signalInput(false)"
@input="signalInput"
>
<template v-slot:append>
<q-btn round dense flat v-slot:append v-if="!hideAdvSearchCheatsheetButton" icon="mdi-help-rhombus" @click.stop.prevent="SSET_setAdvSearchWindowVisible"
@ -408,7 +409,7 @@
label="Note"
v-model="singleNote.value"
dense
@keyup="signalInput(false)"
@keyup="signalInput"
:outlined="!isDarkMode"
:filled="isDarkMode"
>
@ -431,7 +432,6 @@
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
import FieldBase from "src/components/fields/_FieldBase"
import PouchDB from "pouchdb"
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
import { extend } from "quasar"
import { I_ShortenedDocument, I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
@ -486,7 +486,7 @@ export default class Field_MultiRelationship extends FieldBase {
this.checkNotes()
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -494,7 +494,7 @@ export default class Field_MultiRelationship extends FieldBase {
*/
@Watch("inputDataBluePrint", { deep: true, immediate: true })
reactToBlueprintChanges () {
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -502,7 +502,7 @@ export default class Field_MultiRelationship extends FieldBase {
*/
@Watch("currentId")
reactToIDChanges () {
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -526,7 +526,7 @@ export default class Field_MultiRelationship extends FieldBase {
/**
* A list of all retrieved documents without the current one
*/
allDocumentsWithoutCurrent: I_ShortenedDocument[] = []
allTypeDocuments: I_ShortenedDocument[] = []
/**
* A copy of the list for the filter feed
@ -553,7 +553,9 @@ export default class Field_MultiRelationship extends FieldBase {
filterSelect (val: string, update: (e: () => void) => void) {
if (val === "") {
update(() => {
this.filterList = this.allDocumentsWithoutCurrent.filter((obj) => !obj.isMinor)
this.filterList = this.allTypeDocuments
.filter((obj) => !obj.isMinor && obj._id !== this.currentId)
if (this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
this.refocusSelect().catch(e => console.log(e))
}
@ -563,10 +565,11 @@ export default class Field_MultiRelationship extends FieldBase {
update(() => {
const needle = val.toLowerCase()
this.filterList = extend(true, [], this.allDocumentsWithoutCurrent)
this.filterList = extend(true, [], this.allTypeDocuments)
// @ts-ignore
this.filterList = advancedDocumentFilter(needle, this.filterList, this.SGET_allBlueprints, this.filterList)
.filter((obj) => obj._id !== this.currentId)
if (this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
this.refocusSelect().catch(e => console.log(e))
@ -578,14 +581,13 @@ export default class Field_MultiRelationship extends FieldBase {
* Prepares the initial loading of the list for filtering and furhter use
* Also remove the document itself from the list, checks if connected input fields even exist and altogether formats and clears the list
*/
async reloadObjectListAndCheckIfValueExists () {
reloadObjectListAndCheckIfValueExists () {
if (this.inputDataBluePrint?.relationshipSettings && this.currentId.length > 0) {
// Get a list of all objects connected to this field and remap them
const CurrentObjectDB = new PouchDB(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
let allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows.map(doc => doc.doc)
const allDbObjects = this.SGET_allDocumentsByTypeWithoutCategories(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
// Map all of the documents to something more digestible for the select
let allObjects = allDbObjects.map((doc) => {
allDbObjects.docs.forEach((doc) => {
const objectDoc = doc as unknown as I_ShortenedDocument
const pairedField = (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
@ -601,48 +603,28 @@ export default class Field_MultiRelationship extends FieldBase {
}
}
return {
_id: objectDoc._id,
icon: objectDoc.icon,
value: objectDoc._id,
type: objectDoc.type,
disable: isDisabled,
extraFields: objectDoc.extraFields,
url: `/project/display-content/${objectDoc.type}/${objectDoc._id}`,
label: objectDoc.extraFields.find(e => e.id === "name")?.value,
isCategory: objectDoc.extraFields.find(e => e.id === "categorySwitch")?.value,
isMinor: objectDoc.extraFields.find(e => e.id === "minorSwitch")?.value,
isDead: objectDoc.extraFields.find(e => e.id === "deadSwitch")?.value,
color: objectDoc.extraFields.find(e => e.id === "documentColor")?.value,
bgColor: objectDoc.extraFields.find(e => e.id === "documentBackgroundColor")?.value,
pairedField: pairedField,
tags: objectDoc.extraFields.find(e => e.id === "tags")?.value,
// @ts-ignore
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbObjects)
if (isDisabled) {
this.disabledIDList = [...new Set([
...this.disabledIDList,
doc._id
])]
}
}) as unknown as I_ShortenedDocument[]
// Filter out current object
let allObjectsWithoutCurrent: I_ShortenedDocument[] = allObjects.filter((obj) => obj._id !== this.currentId)
})
// Do a quick check on formatting of the current input (if something is wrong with it, set it as empty array)
this.localInput = (Array.isArray(this.localInput)) ? this.localInput : []
let needsRefresh = false
this.localInput.forEach((s, index) => {
// Proceed only if the local input is properly set up
if (s._id) {
// If the matched object doesn't exist in the object, assume it has been deleted or newer existed and silently emit a signal input which auto-updates the document
if (!allObjectsWithoutCurrent.find(e => e._id === s._id)) {
if (!allDbObjects.docs.find(e => e._id === s._id)) {
// @ts-ignore
this.localInput.splice(index, 1)
needsRefresh = true
}
// If the object does exist, make sure we have the newest available name by reasigning the label if it is different. Then trigger a silent update
else {
const matchedFieldContent = allObjectsWithoutCurrent.find(e => e._id === s._id)
const matchedFieldContent = allDbObjects.docs.find(e => e._id === s._id)
if (matchedFieldContent && (
this.localInput[index].label !== matchedFieldContent.label ||
@ -650,29 +632,12 @@ export default class Field_MultiRelationship extends FieldBase {
) {
this.localInput[index].label = matchedFieldContent.label
this.localInput[index].isDead = matchedFieldContent.extraFields.find(e => e.id === "deadSwitch")?.value
needsRefresh = true
}
}
}
})
if (needsRefresh) {
this.signalInput(true).catch(e => console.log(e))
}
await CurrentObjectDB.close()
// Do a last set of filtering
this.allDocumentsWithoutCurrent = allObjectsWithoutCurrent
.filter((obj) => !obj.isCategory)
// @ts-ignore
allObjectsWithoutCurrent = null
// @ts-ignore
allObjects = null
// @ts-ignore
allDbObjects = null
this.allTypeDocuments = allDbObjects.docs
}
}
@ -683,9 +648,8 @@ export default class Field_MultiRelationship extends FieldBase {
/**
* Opens a new tab from a connected rleationship
*/
async openNewTab (input: I_FieldRelationship) {
const CurrentObjectDB = new PouchDB(input.type)
const retrievedObject = await CurrentObjectDB.get(input._id)
openNewTab (input: I_FieldRelationship) {
const retrievedObject = (this.SGET_openedDocument(input._id)) || this.SGET_document(input._id)
const dataPass = {
doc: retrievedObject,
@ -694,7 +658,6 @@ export default class Field_MultiRelationship extends FieldBase {
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
await CurrentObjectDB.close()
}
moveItem (index: number, direction: "up" | "down") {
@ -704,23 +667,44 @@ export default class Field_MultiRelationship extends FieldBase {
this.localInput.splice(to, 0, this.localInput.splice(from, 1)[0])
this.inputNotes.splice(to, 0, this.inputNotes.splice(from, 1)[0])
this.signalInput().catch(e => console.log(e))
this.signalInput()
}
disabledIDList: string[] = []
processSelectInteraction (input: null| I_ShortenedDocument) {
// TODO ADD THIS
/* if (input) {
this.disabledIDList.push(input._id)
}
else {
const toRemoveIndex = this.disabledIDList.findIndex(id => id === this.inputDataValue.value._id)
if (toRemoveIndex) {
this.disabledIDList.splice(toRemoveIndex, 1)
}
} */
this.signalInput()
}
/**
* Signals the input change to the document body parent component
*/
@Emit()
async signalInput (skipSave?: boolean) {
await this.$nextTick()
signalInput () {
this.checkNotes()
this.inputNotes = this.inputNotes.filter(single => this.localInput.find(e => single.pairedId === e._id))
return {
value: this.localInput,
addedValues: this.inputNotes,
skipSave: (skipSave)
value: this.localInput.map(e => {
return {
_id: e._id,
type: e.type,
url: e.url,
pairedField: (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
}
}),
addedValues: this.inputNotes
}
}
@ -742,7 +726,7 @@ export default class Field_MultiRelationship extends FieldBase {
docToFind = null as unknown as I_OpenedDocument
fixGetCorrectDocument (e: I_OpenedDocument | I_FieldRelationship) {
this.docToFind = (this.allDocumentsWithoutCurrent.find(doc => doc._id === e._id)) as unknown as I_OpenedDocument
this.docToFind = (this.allTypeDocuments.find(doc => doc._id === e._id)) as unknown as I_OpenedDocument
return this.docToFind
}

View file

@ -130,246 +130,247 @@
</q-item>
</q-list>
<div class="flex" v-if="editMode">
<q-select
class="singleRelashionshipSelect"
menu-anchor="bottom middle"
menu-self="top middle"
dark
style="flex-grow: 1;"
dense
:ref="`singleRelationshipField${inputDataBluePrint.id}`"
:options="filterList"
use-input
:outlined="!isDarkMode"
:filled="isDarkMode"
input-debounce="200"
v-model="localInput"
@filter="filterSelect"
@input="signalInput(false)"
>
<template v-slot:append>
<q-btn round dense flat v-slot:append v-if="!hideAdvSearchCheatsheetButton" icon="mdi-help-rhombus" @click.stop.prevent="SSET_setAdvSearchWindowVisible"
>
<q-tooltip :delay="500">
Open search cheatsheet
</q-tooltip>
</q-btn>
</template>
<template v-slot:selected-item="scope">
<q-chip
v-if="scope.opt.label && scope.opt.label.length > 0"
removable
dense
@click="openNewTab(scope.opt)"
@remove="scope.removeAtIndex(scope.index)"
:tabindex="scope.tabindex"
color="accent"
text-color="dark"
class="text-bold"
>
<template v-if="scope.opt.isDead">
</template>
{{ stripTags(scope.opt.label) }}
<q-btn
round
dense
flat
class="z-15 relationshipChipNewTab"
style="color: #000 !important;"
size="sm"
icon="mdi-open-in-new"
@click.stop.prevent="openNewTab(scope.opt)"
<div class="flex" v-if="editMode">
<q-select
class="singleRelashionshipSelect"
menu-anchor="bottom middle"
menu-self="top middle"
dark
style="flex-grow: 1;"
dense
:ref="`singleRelationshipField${inputDataBluePrint.id}`"
:options="filterList"
:option-disable="opt => Object(opt) === opt ? disabledIDList.includes(opt._id) : true"
use-input
:outlined="!isDarkMode"
:filled="isDarkMode"
input-debounce="200"
v-model="localInput"
@filter="filterSelect"
@input="processSelectInteraction"
>
<template v-slot:append>
<q-btn round dense flat v-slot:append v-if="!hideAdvSearchCheatsheetButton" icon="mdi-help-rhombus" @click.stop.prevent="SSET_setAdvSearchWindowVisible"
>
<q-tooltip :delay="500">
Open in new tab without leaving this one
<q-tooltip :delay="500">
Open search cheatsheet
</q-tooltip>
</q-btn>
<q-menu
touch-position
context-menu
auto-close
separate-close-popup
>
<q-list class="bg-gunmetal-light text-accent">
<template>
<q-item clickable @click="copyName(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTextColor(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable @click="copyBackgroundColor(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator dark />
<q-item clickable @click="openExistingInput(fixGetCorrectDocument(scope.opt))">
<q-item-section>Open document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-book-open-page-variant-outline" />
</q-item-section>
</q-item>
<q-item clickable @click="editExistingInput(fixGetCorrectDocument(scope.opt))">
<q-item-section>Edit document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-pencil" />
</q-item-section>
</q-item>
<q-item clickable @click="addNewUnderParent(fixGetCorrectDocument(scope.opt))">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTargetDocument(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-content-copy" />
</q-item-section>
</q-item>
</template>
</q-list>
</q-menu>
</q-chip>
</template>
<template v-slot:option="{ itemProps, itemEvents, opt }">
<q-item
:class="{'hasTextShadow': textShadow, 'isMinor':opt.isMinor}"
v-bind="itemProps"
v-on="itemEvents"
:key="opt.id"
:style="`background-color: ${opt.bgColor}`"
>
<q-item-section avatar>
<q-icon
:style="`color: ${retrieveIconColor(opt)}`"
:name="(opt.isCategory) ? 'fas fa-folder-open' : opt.icon"
/>
</q-item-section>
<q-item-section>
<q-item-label
:style="`color: ${opt.color}`"
>
<span class="isDeadIndicator" v-if="opt.isDead">
</span>
<span :class="{'isDead': (opt.isDead && !hideDeadCrossThrough)}" v-html="opt.label">
</span>
</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="text-cultured noBounce"
v-html="`${input}`"
>
</q-chip>
</q-item-label>
</q-item-section>
<q-tooltip v-if='opt.disable'>
This option is unavailable for selection as it is already paired to another.
</q-tooltip>
<q-menu
touch-position
context-menu
auto-close
separate-close-popup
>
<q-list class="bg-gunmetal-light text-accent">
<template>
<q-item clickable @click="copyName(opt)">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTextColor(opt)">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable @click="copyBackgroundColor(opt)">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator dark />
<q-item clickable @click="openExistingInput(opt)">
<q-item-section>Open document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-book-open-page-variant-outline" />
</q-item-section>
</q-item>
<q-item clickable @click="editExistingInput(opt)">
<q-item-section>Edit document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-pencil" />
</q-item-section>
</q-item>
<q-item clickable @click="addNewUnderParent(opt)">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTargetDocument(opt)">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-content-copy" />
</q-item-section>
</q-item>
</template>
</q-list>
</q-menu>
</q-item>
</template>
</q-select>
<table class="q-mt-sm" v-if="localInput && inputFieldID !== 'parentDoc'">
<tr>
<td>
{{stripTags(localInput.label)}}
</td>
<td>
<q-input
label="Note"
v-model="inputNote.value"
<template v-slot:selected-item="scope">
<q-chip
v-if="scope.opt.label && scope.opt.label.length > 0"
removable
dense
@keyup="signalInput(false)"
:outlined="!isDarkMode"
:filled="isDarkMode"
@click="openNewTab(scope.opt)"
@remove="scope.removeAtIndex(scope.index)"
:tabindex="scope.tabindex"
color="accent"
text-color="dark"
class="text-bold"
>
<template v-if="scope.opt.isDead">
</template>
{{ stripTags(scope.opt.label) }}
<q-btn
round
dense
flat
class="z-15 relationshipChipNewTab"
style="color: #000 !important;"
size="sm"
icon="mdi-open-in-new"
@click.stop.prevent="openNewTab(scope.opt)"
>
</q-input>
</td>
<q-tooltip :delay="500">
Open in new tab without leaving this one
</q-tooltip>
</q-btn>
<q-menu
touch-position
context-menu
auto-close
separate-close-popup
>
</tr>
</table>
<q-list class="bg-gunmetal-light text-accent">
</div>
<template>
<q-item clickable @click="copyName(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTextColor(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable @click="copyBackgroundColor(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator dark />
<q-item clickable @click="openExistingInput(fixGetCorrectDocument(scope.opt))">
<q-item-section>Open document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-book-open-page-variant-outline" />
</q-item-section>
</q-item>
<q-item clickable @click="editExistingInput(fixGetCorrectDocument(scope.opt))">
<q-item-section>Edit document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-pencil" />
</q-item-section>
</q-item>
<q-item clickable @click="addNewUnderParent(fixGetCorrectDocument(scope.opt))">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTargetDocument(fixGetCorrectDocument(scope.opt))">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-content-copy" />
</q-item-section>
</q-item>
</template>
</q-list>
</q-menu>
</q-chip>
</template>
<template v-slot:option="{ itemProps, itemEvents, opt }" >
<q-item
:class="{'hasTextShadow': textShadow, 'isMinor':opt.isMinor}"
v-bind="itemProps"
v-on="itemEvents"
:key="opt.id"
:style="`background-color: ${opt.bgColor}`"
>
<q-item-section avatar>
<q-icon
:style="`color: ${retrieveIconColor(opt)}`"
:name="(opt.isCategory) ? 'fas fa-folder-open' : opt.icon"
/>
</q-item-section>
<q-item-section>
<q-item-label
:style="`color: ${opt.color}`"
>
<span class="isDeadIndicator" v-if="opt.isDead">
</span>
<span :class="{'isDead': (opt.isDead && !hideDeadCrossThrough)}" v-html="opt.label">
</span>
</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="text-cultured noBounce"
v-html="`${input}`"
>
</q-chip>
</q-item-label>
</q-item-section>
<q-tooltip v-if='opt.disable'>
This option is unavailable for selection as it is already paired to another.
</q-tooltip>
<q-menu
touch-position
context-menu
auto-close
separate-close-popup
>
<q-list class="bg-gunmetal-light text-accent">
<template>
<q-item clickable @click="copyName(opt)">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTextColor(opt)">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable @click="copyBackgroundColor(opt)">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator dark />
<q-item clickable @click="openExistingInput(opt)">
<q-item-section>Open document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-book-open-page-variant-outline" />
</q-item-section>
</q-item>
<q-item clickable @click="editExistingInput(opt)">
<q-item-section>Edit document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-pencil" />
</q-item-section>
</q-item>
<q-item clickable @click="addNewUnderParent(opt)">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable @click="copyTargetDocument(opt)">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon color="primary" name="mdi-content-copy" />
</q-item-section>
</q-item>
</template>
</q-list>
</q-menu>
</q-item>
</template>
</q-select>
<table class="q-mt-sm" v-if="localInput && inputFieldID !== 'parentDoc'">
<tr>
<td>
{{stripTags(localInput.label)}}
</td>
<td>
<q-input
label="Note"
v-model="inputNote.value"
dense
@keyup="signalInput"
:outlined="!isDarkMode"
:filled="isDarkMode"
>
</q-input>
</td>
</tr>
</table>
</div>
<div class="separatorWrapper">
<q-separator color="grey q-mt-md" />
@ -384,7 +385,6 @@ import { Component, Emit, Prop, Watch } from "vue-property-decorator"
import FieldBase from "src/components/fields/_FieldBase"
import PouchDB from "pouchdb"
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
import { extend } from "quasar"
@ -442,7 +442,7 @@ export default class Field_SingleRelationship extends FieldBase {
this.inputNote = (!this.inputDataValue?.addedValues) ? this.inputNote : this.inputDataValue.addedValues
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -450,7 +450,7 @@ export default class Field_SingleRelationship extends FieldBase {
*/
@Watch("inputDataBluePrint", { deep: true, immediate: true })
reactToBlueprintChanges () {
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -458,7 +458,7 @@ export default class Field_SingleRelationship extends FieldBase {
*/
@Watch("currentId")
reactToIDChanges () {
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log())
this.reloadObjectListAndCheckIfValueExists()
}
/**
@ -485,7 +485,7 @@ export default class Field_SingleRelationship extends FieldBase {
/**
* A list of all retrieved documents without the current one
*/
allDocumentsWithoutCurrent: I_ShortenedDocument[] = []
allTypeDocuments: I_ShortenedDocument[] = []
/**
* A copy of the list for the filter feed
@ -512,7 +512,8 @@ export default class Field_SingleRelationship extends FieldBase {
filterSelect (val: string, update: (e: () => void) => void) {
if (val === "") {
update(() => {
this.filterList = this.allDocumentsWithoutCurrent.filter((obj) => !obj.isMinor)
this.filterList = this.allTypeDocuments
.filter((obj) => !obj.isMinor && obj._id !== this.currentId)
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
this.refocusSelect().catch(e => console.log(e))
@ -523,9 +524,10 @@ export default class Field_SingleRelationship extends FieldBase {
update(() => {
const needle = val.toLowerCase()
this.filterList = extend(true, [], this.allDocumentsWithoutCurrent)
this.filterList = extend(true, [], this.allTypeDocuments)
// @ts-ignore
this.filterList = advancedDocumentFilter(needle, this.filterList, this.SGET_allBlueprints, this.filterList)
.filter((obj) => obj._id !== this.currentId)
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
this.refocusSelect().catch(e => console.log(e))
@ -533,18 +535,22 @@ export default class Field_SingleRelationship extends FieldBase {
})
}
disabledIDList: string[] = []
/**
* Prepares the initial loading of the list for filtering and furhter use
* Also remove the document itself from the list, checks if connected input fields even exist and altogether formats and clears the list
*/
async reloadObjectListAndCheckIfValueExists () {
reloadObjectListAndCheckIfValueExists () {
if (this.inputDataBluePrint?.relationshipSettings && this.currentId.length > 0) {
// Get a list of all objects connected to this field and remap them
const CurrentObjectDB = new PouchDB(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
let allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows.map(doc => doc.doc)
// If this is the "parentDoc" field, include categories, otherwise, filter them out from the list
const isBelongsUnder = (this.inputDataBluePrint.id === "parentDoc")
const allDbObjects = (isBelongsUnder)
? this.SGET_allDocumentsByType(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
: this.SGET_allDocumentsByTypeWithoutCategories(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
// Map all of the documents to something more digestible for the select
let allObjects = allDbObjects.map((doc) => {
allDbObjects.docs.forEach((doc) => {
const objectDoc = doc as unknown as I_ShortenedDocument
const pairedField = (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
@ -555,69 +561,45 @@ export default class Field_SingleRelationship extends FieldBase {
const pairedFieldObject = objectDoc.extraFields.find(f => f.id === pairedField)
const pairingType = this.inputDataBluePrint.type
if (pairedFieldObject !== undefined && typeof pairedFieldObject?.value !== "string" && pairedFieldObject?.value !== null && pairingType === "singleToSingleRelationship") {
isDisabled = true
if (pairedFieldObject !== undefined && typeof pairedFieldObject?.value !== "string" && pairedFieldObject?.value !== null && pairedFieldObject?.value?.value !== null && pairingType === "singleToSingleRelationship") {
const checkIfExists = allDbObjects.docs.find(f => f._id === pairedFieldObject?.value?.value?._id)
if (checkIfExists) {
isDisabled = true
}
}
}
return {
_id: objectDoc._id,
value: objectDoc._id,
type: objectDoc.type,
icon: objectDoc.icon,
disable: isDisabled,
extraFields: objectDoc.extraFields,
url: `/project/display-content/${objectDoc.type}/${objectDoc._id}`,
label: objectDoc.extraFields.find(e => e.id === "name")?.value,
color: objectDoc.extraFields.find(e => e.id === "documentColor")?.value,
bgColor: objectDoc.extraFields.find(e => e.id === "documentBackgroundColor")?.value,
isCategory: objectDoc.extraFields.find(e => e.id === "categorySwitch")?.value,
isMinor: objectDoc.extraFields.find(e => e.id === "minorSwitch")?.value,
isDead: objectDoc.extraFields.find(e => e.id === "deadSwitch")?.value,
pairedField: pairedField,
tags: objectDoc.extraFields.find(e => e.id === "tags")?.value,
// @ts-ignore
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbObjects)
if (isDisabled) {
this.disabledIDList = [...new Set([
...this.disabledIDList,
doc._id
])]
}
}) as unknown as I_ShortenedDocument[]
// If this is the "parentDoc" field, include categories, otherwise, filter them out from the list
const isBelongsUnder = (this.inputDataBluePrint.id === "parentDoc")
const objectsWithoutCurrent: I_ShortenedDocument[] = (isBelongsUnder)
? allObjects.filter((obj) => obj._id !== this.currentId)
: allObjects.filter((obj) => obj._id !== this.currentId).filter((obj) => !obj.isCategory)
})
// Proceed only if the local input is properly set up
if (this.localInput._id) {
// If the matched object doesn't exist in the object, assume it has been deleted or newer existed and silently emit a signal input which auto-updates the document
if (!objectsWithoutCurrent.find(e => e._id === this.localInput._id)) {
// If the matched object doesn't exist in the object, assume it has been deleted or never existed
if (!allDbObjects.docs.find(e => e._id === this.localInput._id)) {
// @ts-ignore
this.localInput = ""
this.signalInput(true)
}
// If the object does exist, make sure we have the newest available name by reasigning the label if it is different. Then trigger a silent update
// If the object does exist, make sure we have the newest available name by reasigning the label if it is different
else {
const matchedFieldContent = objectsWithoutCurrent.find(e => e._id === this.localInput._id)
const matchedFieldContent = allDbObjects.docs.find(e => e._id === this.localInput._id)
if (matchedFieldContent && (
this.localInput.label !== matchedFieldContent.label ||
this.localInput?.isDead !== matchedFieldContent.extraFields.find(e => e.id === "deadSwitch")?.value)
) {
this.localInput.label = matchedFieldContent.label
this.localInput.isDead = matchedFieldContent.extraFields.find(e => e.id === "deadSwitch")?.value
this.signalInput(true)
}
}
}
await CurrentObjectDB.close()
this.allDocumentsWithoutCurrent = objectsWithoutCurrent
// @ts-ignore
allObjects = null
// @ts-ignore
allDbObjects = null
this.allTypeDocuments = allDbObjects.docs
}
}
@ -628,9 +610,8 @@ export default class Field_SingleRelationship extends FieldBase {
/**
* Opens a new tab from a connected rleationship
*/
async openNewTab (input: I_FieldRelationship) {
const CurrentObjectDB = new PouchDB(input.type)
const retrievedObject = await CurrentObjectDB.get(input._id)
openNewTab (input: I_FieldRelationship) {
const retrievedObject = (this.SGET_openedDocument(input._id)) || this.SGET_document(input._id)
const dataPass = {
doc: retrievedObject,
@ -639,19 +620,41 @@ export default class Field_SingleRelationship extends FieldBase {
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
await CurrentObjectDB.close()
}
processSelectInteraction (input: null| I_ShortenedDocument) {
if (input) {
this.disabledIDList.push(input._id)
}
else {
const toRemoveIndex = this.disabledIDList.findIndex(id => id === this.inputDataValue.value._id)
if (toRemoveIndex) {
this.disabledIDList.splice(toRemoveIndex, 1)
}
}
this.signalInput()
}
/**
* Signals the input change to the document body parent component
*/
@Emit()
signalInput (skipSave?: boolean) {
signalInput () {
this.inputNote = (this.localInput !== null) ? this.inputNote : { pairedId: "", value: "" }
const exportValue = (this.localInput && this.localInput._id)
? {
_id: this.localInput._id,
type: this.localInput.type,
url: this.localInput.url,
pairedField: (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
}
: null
return {
value: this.localInput,
addedValues: this.inputNote,
skipSave: (skipSave)
value: exportValue,
addedValues: this.inputNote
}
}
@ -662,7 +665,7 @@ export default class Field_SingleRelationship extends FieldBase {
docToFind = null as unknown as I_OpenedDocument
fixGetCorrectDocument (e: I_OpenedDocument | I_FieldRelationship) {
this.docToFind = (this.allDocumentsWithoutCurrent.find(doc => doc._id === e._id)) as unknown as I_OpenedDocument
this.docToFind = (this.allTypeDocuments.find(doc => doc._id === e._id)) as unknown as I_OpenedDocument
return this.docToFind
}
@ -700,7 +703,6 @@ export default class Field_SingleRelationship extends FieldBase {
/****************************************************************/
copyName (currentDoc: I_OpenedDocument) {
console.log(currentDoc)
copyDocumentName(currentDoc)
}

View file

@ -104,7 +104,7 @@ export default class Field_Tags extends FieldBase {
@Watch("inputDataValue", { deep: true, immediate: true })
reactToInputChanges () {
this.localInput = (this.inputDataValue) ? this.inputDataValue : []
this.buildTagList().catch(e => console.log(e))
this.buildTagList()
}
/**
@ -117,7 +117,7 @@ export default class Field_Tags extends FieldBase {
*/
@Watch("inputDataBluePrint", { deep: true, immediate: true })
reactToBlueprintChanges () {
this.buildTagList().catch(e => console.log(e))
this.buildTagList()
}
/**
@ -213,8 +213,8 @@ export default class Field_Tags extends FieldBase {
/**
* Build a new tag list from all existing tags on all documents across the whole project
*/
async buildTagList () {
this.allTags = await tagListBuildFromBlueprints(this.SGET_allBlueprints)
buildTagList () {
this.allTags = tagListBuildFromBlueprints(this.SGET_allDocuments.docs)
}
}
</script>

View file

@ -6,6 +6,7 @@
- `#` - Tag
- `>` - Hierarchical path
- `^` - Switch
- `^c` - Is a category
- `^d` - Is Dead/Gone/Destroyed
- `^f` - Is finished
- `^m` - Is a minor document

View file

@ -53,6 +53,7 @@ Except for the advanced search functionality, Fantasia Archive also offers insta
- `#` - Symbol for tag search
- `>` - Symbol for hierarchical path search
- `^` - Symbol for switch search (limited values below)
- `^c` - Displays only documents with `Is a category` ticked on
- `^d` - Displays only documents with `Is Dead/Gone/Destroyed` ticked on
- `^f` - Displays only documents with `Is finished` ticked on
- `^m` - Displays only documents with `Is a minor document` ticked on that are normally invisible and filtered out

View file

@ -9,14 +9,21 @@
- POSSIBLY FIXED: When creating a brand new project, Fantasia Archive sometimes doesn't load the default categories in the left hierarchical tree. A temporary workaround before the issue is fixed is restarting the program - the project stays intact, can be normally edited and no data loss occurs.
- POSSIBLY FIXED: Some users report that dialog (popups) don't function the very first time you start FA. This is solved by restarting the application. The bug doesn't seem to appear again once FA has been started at least once before.
- Overusing Tags currently causes app crashes on some PCs. If you suffer from this issue, reduce the number of tags in your project below 10.
### Bugfixes & Optimizations
- Fixed buttons for moving list items up and down also showing outside of edit mode
- Fixed `Resume project` button working in instances where it shouldnt
- Fixed a visual bug in the top document control bar
- Added a check against invalid characters in new project name to prevent issues while exporting on different OSs
- Hopefully finally fixed the new project creation bugs that have been plaguing the app for last 3 releases
### New features
- Added support for filtering via `Is a category` switch field
- Added "Hamlet" as a predefined location type
### QoL adjustments
## 0.1.5a

4
src/globals.d.ts vendored
View file

@ -7,3 +7,7 @@ declare module "*.png"{
const content: string
export default content
}
interface Window {
FA_dbs: PouchDB.Static[]
}

View file

@ -51,6 +51,7 @@
import { Component, Watch } from "vue-property-decorator"
import BaseClass from "src/BaseClass"
import PouchDB from "pouchdb"
import objectTree from "src/components/ObjectTree.vue"
import appHeader from "src/components/AppHeader.vue"
@ -60,6 +61,7 @@ import { engageBlueprints, retrieveAllBlueprints } from "src/scripts/databaseMan
import { extend } from "quasar"
import { OptionsStateInteface } from "src/store/module-options/state"
import { I_Blueprint } from "src/interfaces/I_Blueprint"
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
@Component({
components: {
@ -69,6 +71,71 @@ import { I_Blueprint } from "src/interfaces/I_Blueprint"
}
})
export default class DocumentLayout extends BaseClass {
/****************************************************************/
// PROJECT SETTINGS FIRST LOAD
/****************************************************************/
/**
* Load all blueprints and build the tree out of them
*/
async created () {
if (this.SGET_allDocumentsFirstRunState) {
await this.processBluePrints()
this.establishAllDocumentDatabases()
await this.loadAllProjectDocuments()
}
// Unfuck the rendering by giving the app some time to load first
await this.$nextTick()
}
/**
* Processes all blueprints and redies the store for population of the app
*/
async processBluePrints (): Promise<void> {
await engageBlueprints()
const allObjectBlueprints = (await retrieveAllBlueprints()).rows.map((blueprint) => {
return blueprint.doc
}) as I_Blueprint[]
this.SSET_allBlueprints(allObjectBlueprints)
}
establishAllDocumentDatabases () {
// @ts-ignore
window.FA_dbs = {}
for (const blueprint of this.SGET_allBlueprints) {
window.FA_dbs[blueprint._id] = new PouchDB(blueprint._id)
}
}
async loadAllProjectDocuments () {
for (const blueprint of this.SGET_allBlueprints) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const dbRows = await window.FA_dbs[blueprint._id].allDocs({ include_docs: true })
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// eslint-disable-next-line
const dbDocuments = dbRows.rows.map((d:any) => d.doc)
const formattedDocuments: I_ShortenedDocument[] = []
for (const singleDocument of dbDocuments) {
const doc = singleDocument as unknown as I_ShortenedDocument
const pushValue = this.mapShortDocument(doc, dbDocuments)
formattedDocuments.push(pushValue)
}
const sortedDocuments = formattedDocuments.sort((a, b) => a.label.localeCompare(b.label))
this.SSET_mapNewDocumentType({
id: blueprint._id,
docs: sortedDocuments
})
}
this.SSET_allDocumentsMarkAsNonFirstRun()
}
/****************************************************************/
// BASIC COMPONENT DATA
/****************************************************************/
@ -90,30 +157,6 @@ export default class DocumentLayout extends BaseClass {
return !this.leftDrawerOpen ? "splitt" : ""
}
/**
* Load all blueprints and build the tree out of them
*/
async created () {
// await cleanDatabases()
await this.processBluePrints()
// Unfuck the rendering by giving the app some time to load first
await this.$nextTick()
}
/**
* Processes all blueprints and redies the store for population of the app
*/
async processBluePrints (): Promise<void> {
await engageBlueprints()
const allObjectBlueprints = (await retrieveAllBlueprints()).rows.map((blueprint) => {
return blueprint.doc
}) as I_Blueprint[]
this.SSET_allBlueprints(allObjectBlueprints)
}
/**
* Special padding reset for the main page
*/

View file

@ -271,9 +271,8 @@ import { Component, Watch } from "vue-property-decorator"
import BaseClass from "src/BaseClass"
import { I_Blueprint, I_ExtraFields } from "src/interfaces/I_Blueprint"
import PouchDB from "pouchdb"
import { extend } from "quasar"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
import { saveDocument } from "src/scripts/databaseManager/documentManager"
@ -394,7 +393,7 @@ export default class PageDocumentDisplay extends BaseClass {
const doc = this.findRequestedOrActiveDocument() as I_OpenedDocument
window.scrollTo({ top: 0, behavior: "auto" })
await this.reloadLocalContent().catch(e => console.log(e))
this.reloadLocalContent()
const scrollTop = (doc.scrollDistance && !this.preventAutoScroll) ? doc.scrollDistance : 0
@ -455,40 +454,41 @@ export default class PageDocumentDisplay extends BaseClass {
const matchingDoc = this.findRequestedOrActiveDocument()
if (matchingDoc && matchingDoc._id === this.currentData._id && !matchingDoc.hasEdits) {
this.reloadLocalContent().catch(e => console.log(e))
this.reloadLocalContent()
}
}
/**
* Attemp to reload the current local content. If it doesn't exist, create a new one.
*/
async reloadLocalContent () {
reloadLocalContent () {
// Determine the type and retrieve the right blueprint
this.bluePrintData = this.retrieveDocumentBlueprint()
// Check if the objects exists in a database
const CurrentObjectDB = new PouchDB(this.$route.params.type)
let retrievedObject = false as unknown as I_OpenedDocument
try {
retrievedObject = await CurrentObjectDB.get(this.$route.params.id)
let retrievedObject = false as unknown as I_OpenedDocument | I_ShortenedDocument
if (this.SGET_document(this.$route.params.id)) {
retrievedObject = this.SGET_document(this.$route.params.id)
}
catch (error) {}
if (!retrievedObject) {
const snapshot: I_OpenedDocument[] = extend(true, [], this.SGET_allOpenedDocuments.docs)
retrievedObject = snapshot.find(s => this.$route.params.id === s._id) as unknown as I_OpenedDocument
if (retrievedObject?.isNew || retrievedObject?.editMode) {
this.editMode = true
}
}
else {
retrievedObject = (this.SGET_openedDocument(retrievedObject._id)) ? this.SGET_openedDocument(retrievedObject._id) : retrievedObject
this.editMode = (this.SGET_openedDocument(retrievedObject._id)?.hasEdits || this.SGET_openedDocument(retrievedObject._id)?.editMode)
if (this.SGET_openedDocument(this.$route.params.id)) {
retrievedObject = this.SGET_openedDocument(this.$route.params.id)
}
// Either create a new document or load existing one
this.currentData = (retrievedObject) ? extend(true, [], retrievedObject) : this.createNewDocumentObject()
const objectFields = await this.mapNewObjectFields()
if (!this.currentData) {
this.$router.push({ path: "/project" }).catch((e: {name: string}) => {
if (e && e.name !== "NavigationDuplicated") {
console.log(e)
}
})
return
}
const objectFields = this.mapNewObjectFields()
if (!objectFields) {
return
@ -496,6 +496,13 @@ export default class PageDocumentDisplay extends BaseClass {
this.currentData.extraFields = objectFields
if (this.currentData.editMode) {
this.editMode = true
}
else {
this.editMode = false
}
if (this.$route.query?.editMode) {
this.editMode = true
this.currentData.editMode = true
@ -509,7 +516,6 @@ export default class PageDocumentDisplay extends BaseClass {
// Attempts to add current document to list
const dataPass = { doc: dataCopy, treeAction: false }
this.SSET_addOpenedDocument(dataPass)
await CurrentObjectDB.close()
}
/**
@ -614,12 +620,6 @@ export default class PageDocumentDisplay extends BaseClass {
this.localDataCopy = extend(true, {}, this.currentData)
const dataPass = { doc: this.localDataCopy, treeAction: false }
// @ts-ignore
if (inputData.skipSave) {
this.currentData.extraFields[indexToUpdate].value.skipSave = false
dataPass.doc.hasEdits = false
}
this.SSET_updateOpenedDocument(dataPass)
}
@ -675,7 +675,7 @@ export default class PageDocumentDisplay extends BaseClass {
/**
* Map new object "name" and "parentDoc" fields if pre-filled
*/
async mapNewObjectFields () {
mapNewObjectFields () {
const currentExtraFields = (this.currentData && this.currentData.extraFields) ? this.currentData.extraFields : []
const blueprint = this.retrieveDocumentBlueprint()
@ -701,11 +701,10 @@ export default class PageDocumentDisplay extends BaseClass {
else if (field.id === "parentDoc") {
if (this.$route.query?.parent) {
// Check if the objects exists in a database
const CurrentObjectDB = new PouchDB(this.$route.params.type)
const parentID = this.$route.query.parent as string
let retrievedObject = false as unknown as I_OpenedDocument
let retrievedObject = false as unknown as I_ShortenedDocument
try {
retrievedObject = await CurrentObjectDB.get(parentID)
retrievedObject = this.SGET_document(parentID)
}
catch (error) {}
@ -729,7 +728,6 @@ export default class PageDocumentDisplay extends BaseClass {
}
}
)
await CurrentObjectDB.close()
}
else {
currentExtraFields.push({ id: field.id, value: "" })
@ -750,6 +748,11 @@ export default class PageDocumentDisplay extends BaseClass {
createNewDocumentObject () : I_OpenedDocument {
this.editMode = true
if (!this.$route.params.id || !this.bluePrintData) {
// @ts-ignore
return false
}
const uniqueID = this.$route.params.id
return {
_id: uniqueID,
@ -919,24 +922,29 @@ export default class PageDocumentDisplay extends BaseClass {
const allDocuments = this.SGET_allOpenedDocuments
const docCopy: I_OpenedDocument[] = extend(true, [], allDocuments.docs)
const openedDocumentsCopy: I_OpenedDocument[] = extend(true, [], allDocuments.docs)
if (currentDoc) {
// @ts-ignore
const savedDocument: {
documentCopy: I_OpenedDocument,
allOpenedDocuments: I_OpenedDocument[]
} = await saveDocument(currentDoc, docCopy, keepEditMode)
} = await saveDocument(currentDoc, openedDocumentsCopy, this.SGET_allDocuments.docs, keepEditMode)
// Update the opened document
const dataPass = { doc: savedDocument.documentCopy, treeAction: true }
this.SSET_updateOpenedDocument(dataPass)
// @ts-ignore
this.SSET_updateDocument({ doc: this.mapShortDocument(savedDocument.documentCopy, this.SGET_allDocumentsByType(savedDocument.documentCopy.type).docs) })
// Update all others
for (const doc of savedDocument.allOpenedDocuments) {
// Update the opened document
const dataPass = { doc: doc, treeAction: true }
this.SSET_updateOpenedDocument(dataPass)
// @ts-ignored
this.SSET_updateDocument({ doc: this.mapShortDocument(doc, this.SGET_allDocumentsByType(doc.type).docs) })
}
this.$q.notify({

View file

@ -6,7 +6,6 @@
'q-pa-xl': !disableDocumentControlBar,
}"
>
<!-- New document dialog -->
<newDocumentDialog
:dialog-trigger="newObjectDialogTrigger"
@ -128,7 +127,6 @@ import { Component, Watch } from "vue-property-decorator"
import BaseClass from "src/BaseClass"
import { Loading, colors } from "quasar"
import PouchDB from "pouchdb"
import newDocumentDialog from "src/components/dialogs/NewDocument.vue"
import { retrieveCurrentProjectName } from "src/scripts/projectManagement/projectManagent"
import { tipsTricks } from "src/scripts/utilities/tipsTricks"
@ -224,7 +222,7 @@ export default class ProjectScreen extends BaseClass {
* Loads graph data
*/
async loadGraphData () {
if (this.SGET_allBlueprints.length === 0) {
if (this.SGET_allDocumentsFirstRunState) {
await this.sleep(1000)
this.loadGraphData().catch(e => console.log(e))
return
@ -234,18 +232,15 @@ export default class ProjectScreen extends BaseClass {
const allBlueprings = this.SGET_allBlueprints
// Process all documents, build hieararchy out of the and sort them via name and custom order
// Retrieve all documents
for (const blueprint of allBlueprings) {
const CurrentObjectDB = new PouchDB(blueprint._id)
const allDocuments = await CurrentObjectDB.allDocs()
const docCount = allDocuments.rows.length
const docCount = this.SGET_allDocumentsByType(blueprint._id).docs.length
this.allDocuments = this.allDocuments + docCount
this.series[0].data.push(docCount)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
this.chartOptions.xaxis.categories.push(blueprint.namePlural)
await CurrentObjectDB.close()
}
this.graphDataLoaded = true

View file

@ -6,6 +6,53 @@ export const charactersBlueprint: I_Blueprint = {
nameSingular: "Character",
icon: "mdi-account",
extraFields: [
/* {
id: "singleTest",
name: "SINGLE TO SINGLE TEST",
type: "singleToSingleRelationship",
icon: "mdi-account",
sizing: 12,
relationshipSettings: {
connectedObjectType: "characters",
connectedField: "singleTest"
}
},
{
id: "singleToMultiTest",
name: "SINGLE TO MULTI TEST",
type: "singleToManyRelationship",
icon: "mdi-account",
sizing: 6,
relationshipSettings: {
connectedObjectType: "characters",
connectedField: "multiToSingleTest"
}
},
{
id: "multiToSingleTest",
name: "MULTI TO SINGLE TEST",
type: "manyToSingleRelationship",
icon: "mdi-account",
sizing: 6,
relationshipSettings: {
connectedObjectType: "characters",
connectedField: "singleToMultiTest"
}
},
{
id: "multiTest",
name: "MULTI TO MULTI TEST",
type: "manyToManyRelationship",
icon: "mdi-account",
sizing: 12,
relationshipSettings: {
connectedObjectType: "characters",
connectedField: "multiTest"
}
}, */
{
id: "breakDocumentSettings",
name: "Document settings",
@ -1414,5 +1461,6 @@ export const charactersBlueprint: I_Blueprint = {
connectedField: "pairedConnectedCharacter"
}
}
]
}

View file

@ -194,7 +194,7 @@ export const guildsBlueprint: I_Blueprint = {
"Military group",
"Economical group",
"Civil group",
"Crimimal group",
"Criminal group",
"Academic group",
"Faction",
"Charity",

View file

@ -175,8 +175,11 @@ export const locationsBlueprint: I_Blueprint = {
"Building",
"City",
"Continent",
"Country",
"Forest",
"Galaxy",
"Hamlet",
"Island",
"Landmark",
"Landmass",
"Moon",

View file

@ -204,6 +204,7 @@ export const politicalGroupsBlueprint: I_Blueprint = {
"Oligarchy",
"Patriarchy",
"Republic",
"Socialism",
"Technocracy",
"Theocracy",
"Theodemocracy",

View file

@ -208,7 +208,7 @@ export const religionsBlueprint: I_Blueprint = {
"Monotheism",
"Naturalism",
"Polytheism",
"Spritism",
"Spiritism",
"Totemism",
"Virtue teaching",
"Other"

View file

@ -1,5 +1,5 @@
import { single_changeRelationshipToAnotherObject, many_changeRelationshipToAnotherObject } from "src/scripts/databaseManager/relationshipManager"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
import { extend } from "quasar"
import PouchDB from "pouchdb"
@ -7,17 +7,25 @@ import PouchDB from "pouchdb"
/**
* Saves the given project and handles all the needed procedures
*/
export const saveDocument = async (document: I_OpenedDocument, allOpenedDocuments: I_OpenedDocument[], editModeAfterSave: boolean) => {
export const saveDocument = async (
document: I_OpenedDocument,
allOpenedDocuments: I_OpenedDocument[],
allDocuments: I_ShortenedDocument[],
editModeAfterSave: boolean
) => {
const BlueprintsDB = new PouchDB("blueprints")
const currentBlueprint: {extraFields: I_ExtraFields[]} = await BlueprintsDB.get(document.type)
let CurrentObjectDB = new PouchDB(document.type)
window.FA_dbs[document.type] = new PouchDB(document.type)
const CurrentObjectDB = window.FA_dbs[document.type]
let currentDocument = false as unknown as I_OpenedDocument
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
currentDocument = await CurrentObjectDB.get(document._id)
}
catch (error) {}
catch (error) {
console.log(error)
}
let documentCopy = {} as unknown as I_OpenedDocument
if (currentDocument) {
@ -30,7 +38,7 @@ export const saveDocument = async (document: I_OpenedDocument, allOpenedDocument
allOpenedDocuments = allOpenedDocuments.filter(doc => doc._id !== document._id)
// Handle relatinship fields
// Handle relationship fields
const single_relationshipTypes = ["singleToSingleRelationship", "singleToManyRelationship"]
const single_allRelationshipFields = documentCopy.extraFields.filter(field => {
const currentField = currentBlueprint.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
@ -48,14 +56,20 @@ export const saveDocument = async (document: I_OpenedDocument, allOpenedDocument
const pairedFieldID = currentBlueprint.extraFields.find(e => e.id === field.id)?.relationshipSettings?.connectedField
const filteredDocuments = single_updatedDocuments.filter(doc => {
const filteredOpenedDocuments = single_updatedDocuments.filter(doc => {
return allOpenedDocuments.find(subDoc => {
return subDoc._id === doc._id
})
})
const filteredallDocuments = single_updatedDocuments.filter(doc => {
return allDocuments.find(subDoc => {
return subDoc._id === doc._id
})
})
// Update the particular field in each currently opened document
filteredDocuments.forEach(doc => {
filteredOpenedDocuments.forEach(doc => {
const toUpdateIndex = doc.extraFields.findIndex(e => e.id === pairedFieldID)
if (toUpdateIndex) {
@ -65,6 +79,18 @@ export const saveDocument = async (document: I_OpenedDocument, allOpenedDocument
}
}
})
// Update the particular field in each all document
filteredallDocuments.forEach(doc => {
const toUpdateIndex = doc.extraFields.findIndex(e => e.id === pairedFieldID)
if (toUpdateIndex) {
const matchingDoc = allDocuments.find(subDoc => subDoc._id === doc._id)
if (matchingDoc) {
matchingDoc.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
}
}
})
}
// Update many fields
@ -90,6 +116,24 @@ export const saveDocument = async (document: I_OpenedDocument, allOpenedDocument
}
}
})
const filteredallDocuments = many_updatedDocuments.filter(doc => {
return allDocuments.find(subDoc => {
return subDoc._id === doc._id
})
})
// Update the particular field in each all document
filteredallDocuments.forEach(doc => {
const toUpdateIndex = doc.extraFields.findIndex(e => e.id === pairedFieldID)
if (toUpdateIndex) {
const matchingDoc = allDocuments.find(subDoc => subDoc._id === doc._id)
if (matchingDoc) {
matchingDoc.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
}
}
})
}
documentCopy.isNew = false
@ -101,14 +145,8 @@ export const saveDocument = async (document: I_OpenedDocument, allOpenedDocument
}
// Save the document
try {
await CurrentObjectDB.put(documentCopy)
}
// This exists here as a backup in case the databases closes the connection from elsewhere in the meantime
catch (error) {
CurrentObjectDB = new PouchDB(document.type)
await CurrentObjectDB.put(documentCopy)
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await CurrentObjectDB.put(documentCopy)
// Set edit mode for frontend
documentCopy.editMode = editModeAfterSave
@ -120,25 +158,19 @@ export const addFieldToDocument = async (targetDocumentID: string, fieldID: stri
const BlueprintsDB = new PouchDB("blueprints")
const currentBlueprint: {extraFields: I_ExtraFields[], _id: string} = await BlueprintsDB.get(blueprintID)
// @ts-ignore
// const fieldBluePrint: I_ExtraFields = currentBlueprint.extraFields.find(e => e.id === fieldID)
const TargetObjectTypDB = new PouchDB(currentBlueprint._id)
const targetDocument: { extraFields: any[]} = await TargetObjectTypDB.get(targetDocumentID)
window.FA_dbs[currentBlueprint._id] = new PouchDB(currentBlueprint._id)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const targetDocument: { extraFields: any[]} = await window.FA_dbs[currentBlueprint._id].get(targetDocumentID)
const newField = {
id: fieldID,
value: ""
}
// singleToNoneRelationship
// singleToManyRelationship
// singleToSingleRelationship
// manyToNoneRelationship
// manyToSingleRelationship
// manyToManyRelationship
targetDocument.extraFields.push(newField)
await TargetObjectTypDB.put(targetDocument)
console.log(newField)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[currentBlueprint._id].put(targetDocument)
}

View file

@ -20,33 +20,33 @@ export const single_changeRelationshipToAnotherObject = async (
if (!previousValue && typeof currentValue !== "string" && currentValue) {
if (fieldType === "singleToSingleRelationship") {
updatedDocuments.push(await single_addRelationShipToAnotherObject(field, currentValue, currentDocument))
updatedDocuments.push(await single_addRelationshipToAnotherObject(field, currentValue, currentDocument))
}
if (fieldType === "singleToManyRelationship") {
updatedDocuments.push(await many_addRelationShipToAnotherObject(field, currentValue, currentDocument))
updatedDocuments.push(await many_addRelationshipToAnotherObject(field, currentValue, currentDocument))
}
}
if (previousValue && typeof currentValue !== "string" && currentValue) {
if (fieldType === "singleToSingleRelationship") {
updatedDocuments.push(await single_removeRelationShipFromAnotherObject(previousValue))
updatedDocuments.push(await single_addRelationShipToAnotherObject(field, currentValue, currentDocument))
updatedDocuments.push(await single_removeRelationshipFromAnotherObject(previousValue))
updatedDocuments.push(await single_addRelationshipToAnotherObject(field, currentValue, currentDocument))
}
if (fieldType === "singleToManyRelationship") {
const removedValued = await many_removeRelationShipFromAnotherObject(previousValue, currentDocument)
const removedValued = await many_removeRelationshipFromAnotherObject(previousValue, currentDocument)
if (removedValued) {
updatedDocuments.push(removedValued)
}
updatedDocuments.push(await many_addRelationShipToAnotherObject(field, currentValue, currentDocument))
updatedDocuments.push(await many_addRelationshipToAnotherObject(field, currentValue, currentDocument))
}
}
if ((previousValue && typeof currentValue === "string") || (previousValue && !currentValue)) {
if (fieldType === "singleToSingleRelationship") {
updatedDocuments.push(await single_removeRelationShipFromAnotherObject(previousValue))
updatedDocuments.push(await single_removeRelationshipFromAnotherObject(previousValue))
}
if (fieldType === "singleToManyRelationship") {
const removedValued = await many_removeRelationShipFromAnotherObject(previousValue, currentDocument)
const removedValued = await many_removeRelationshipFromAnotherObject(previousValue, currentDocument)
if (removedValued) {
updatedDocuments.push(removedValued)
}
@ -58,7 +58,7 @@ export const single_changeRelationshipToAnotherObject = async (
return updatedDocuments
}
export const single_addRelationShipToAnotherObject = async (
export const single_addRelationshipToAnotherObject = async (
field: I_ExtraDocumentFields,
currentValue: I_FieldRelationship,
currentDocument: I_OpenedDocument
@ -66,8 +66,9 @@ export const single_addRelationShipToAnotherObject = async (
const typeToFind = currentValue.type
const idToFind = currentValue._id
const PairedObjectDB = new PouchDB(typeToFind)
let pairedDocument = await PairedObjectDB.get(idToFind) as I_OpenedDocument
window.FA_dbs[typeToFind] = new PouchDB(typeToFind)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
let pairedDocument = await window.FA_dbs[typeToFind].get(idToFind) as I_OpenedDocument
const pairedField = currentValue.pairedField
let pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
@ -76,7 +77,8 @@ export const single_addRelationShipToAnotherObject = async (
// Fix non-existant fields
if (!targetPairedField) {
await addFieldToDocument(pairedDocument._id, pairedField, typeToFind)
pairedDocument = await PairedObjectDB.get(idToFind) as I_OpenedDocument
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
pairedDocument = await window.FA_dbs[typeToFind].get(idToFind) as I_OpenedDocument
pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
targetPairedField = pairedDocument.extraFields[pairedFieldIndex]
}
@ -90,35 +92,31 @@ export const single_addRelationShipToAnotherObject = async (
value: currentDocument._id,
type: currentDocument.type,
url: `/project/display-content/${currentDocument.type}/${currentDocument._id}`,
label: currentDocument.extraFields.find(e => e.id === "name")?.value,
pairedField: field.id,
isCategory: currentDocument.extraFields.find(e => e.id === "categorySwitch")?.value,
isDead: currentDocument.extraFields.find(e => e.id === "deadSwitch")?.value
pairedField: field.id
}
await PairedObjectDB.put(pairedDocument)
await PairedObjectDB.close()
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[typeToFind].put(pairedDocument)
return pairedDocument
}
export const single_removeRelationShipFromAnotherObject = async (
export const single_removeRelationshipFromAnotherObject = async (
previousValue: I_FieldRelationship
) => {
const typeToFind = previousValue.type
const idToFind = previousValue._id
const PairedObjectDB = new PouchDB(typeToFind)
const pairedDocument = await PairedObjectDB.get(idToFind) as I_OpenedDocument
window.FA_dbs[typeToFind] = new PouchDB(typeToFind)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const pairedDocument = await window.FA_dbs[typeToFind].get(idToFind) as I_OpenedDocument
const pairedField = previousValue.pairedField
const pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
pairedDocument.extraFields[pairedFieldIndex].value = { value: "", addedValues: "" }
await PairedObjectDB.put(pairedDocument)
await PairedObjectDB.close()
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[typeToFind].put(pairedDocument)
return pairedDocument
}
@ -126,7 +124,8 @@ export const single_removeRelationShipFromAnotherObject = async (
export const many_changeRelationshipToAnotherObject = async (
field: I_ExtraDocumentFields,
currentDocument:I_OpenedDocument,
previouDocument: I_OpenedDocument) => {
previouDocument: I_OpenedDocument
) => {
const currentValue: I_FieldRelationship[] = (field.value?.value && typeof field.value?.value !== "string") ? field.value.value : []
const previousValue: I_FieldRelationship[] = (previouDocument?.extraFields?.find(e => e.id === field.id))?.value?.value || []
@ -141,36 +140,38 @@ export const many_changeRelationshipToAnotherObject = async (
for (const addedValue of addedValues) {
if (fieldType === "manyToManyRelationship") {
updatedDocuments.push(await many_addRelationShipToAnotherObject(field, addedValue, currentDocument))
updatedDocuments.push(await many_addRelationshipToAnotherObject(field, addedValue, currentDocument))
}
if (fieldType === "manyToSingleRelationship") {
updatedDocuments.push(await single_addRelationShipToAnotherObject(field, addedValue, currentDocument))
updatedDocuments.push(await single_addRelationshipToAnotherObject(field, addedValue, currentDocument))
}
}
for (const removedValue of removedValues) {
if (fieldType === "manyToManyRelationship") {
const removedValued = await many_removeRelationShipFromAnotherObject(removedValue, currentDocument)
const removedValued = await many_removeRelationshipFromAnotherObject(removedValue, currentDocument)
if (removedValued) {
updatedDocuments.push(removedValued)
}
}
if (fieldType === "manyToSingleRelationship") {
const removedValued = await single_removeRelationShipFromAnotherObject(removedValue)
const removedValued = await single_removeRelationshipFromAnotherObject(removedValue)
if (removedValued) {
updatedDocuments.push(removedValued)
}
}
}
// console.log(updatedDocuments)
await BlueprintsDB.close()
return updatedDocuments
}
export const many_addRelationShipToAnotherObject = async (
export const many_addRelationshipToAnotherObject = async (
field: I_ExtraDocumentFields,
currentValue: I_FieldRelationship,
currentDocument: I_OpenedDocument
@ -178,17 +179,22 @@ export const many_addRelationShipToAnotherObject = async (
const typeToFind = currentValue.type
const idToFind = currentValue._id
const PairedObjectDB = new PouchDB(typeToFind)
let pairedDocument = await PairedObjectDB.get(idToFind) as I_OpenedDocument
window.FA_dbs[typeToFind] = new PouchDB(typeToFind)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
let pairedDocument = await window.FA_dbs[typeToFind].get(idToFind) as I_OpenedDocument
const pairedField = currentValue.pairedField
let pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
let targetPairedField = pairedDocument.extraFields[pairedFieldIndex]
console.log(currentValue)
console.log(pairedField)
// Fix non-existant fields
if (!targetPairedField) {
await addFieldToDocument(pairedDocument._id, pairedField, typeToFind)
pairedDocument = await PairedObjectDB.get(idToFind) as I_OpenedDocument
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
pairedDocument = await window.FA_dbs[typeToFind].get(idToFind) as I_OpenedDocument
pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
targetPairedField = pairedDocument.extraFields[pairedFieldIndex]
}
@ -200,10 +206,7 @@ export const many_addRelationShipToAnotherObject = async (
value: currentDocument._id,
type: currentDocument.type,
url: `/project/display-content/${currentDocument.type}/${currentDocument._id}`,
label: currentDocument.extraFields.find(e => e.id === "name")?.value,
pairedField: field.id,
isCategory: currentDocument.extraFields.find(e => e.id === "categorySwitch")?.value,
isDead: currentDocument.extraFields.find(e => e.id === "deadSwitch")?.value
pairedField: field.id
}
pairedFieldValue = (Array.isArray(pairedFieldValue)) ? pairedFieldValue : []
@ -211,6 +214,7 @@ export const many_addRelationShipToAnotherObject = async (
const valueExistsAlready = (pairedFieldValue.find(e => e._id === newValue._id))
if (!valueExistsAlready) {
// @ts-ignore
pairedFieldValue.push(newValue)
}
@ -220,14 +224,13 @@ export const many_addRelationShipToAnotherObject = async (
pairedDocument.extraFields[pairedFieldIndex].value.value = pairedFieldValue
await PairedObjectDB.put(pairedDocument)
await PairedObjectDB.close()
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[typeToFind].put(pairedDocument)
return pairedDocument
}
export const many_removeRelationShipFromAnotherObject = async (
export const many_removeRelationshipFromAnotherObject = async (
previousValue: I_FieldRelationship,
currentDocument: I_OpenedDocument
) => {
@ -255,7 +258,5 @@ export const many_removeRelationShipFromAnotherObject = async (
await PairedObjectDB.put(pairedDocument)
await PairedObjectDB.close()
return pairedDocument
}

View file

@ -85,6 +85,10 @@ export const exportProject = (projectName: string, Loading: any, loadingSetup: a
for (const db of DBnames) {
const CurrentDB = new PouchDB(db)
if (!fs.existsSync(`${folderPath}`)) {
fs.mkdirSync(`${folderPath}`)
}
if (!fs.existsSync(`${folderPath}/${projectName}`)) {
fs.mkdirSync(`${folderPath}/${projectName}`)
}
@ -195,6 +199,7 @@ export const importExistingProject = (vueRouter: any, Loading: any, loadingSetup
})
vueInstance.SSET_resetDocuments()
vueInstance.SSET_resetAllDocuments()
/* eslint-enable */
}).catch(err => {
console.log(err)
@ -267,6 +272,8 @@ export const mergeExistingProject = (vueRouter: any, Loading: any, loadingSetup:
})
vueInstance.SSET_resetDocuments()
vueInstance.SSET_resetAllDocuments()
/* eslint-enable */
}).catch(err => {
console.log(err)

View file

@ -283,6 +283,13 @@ export const advancedDocumentFilter = (inputString: string, currentDocumentList:
currentDocumentList = currentDocumentList.filter(doc => {
let foundSwitch = false
if (switchSearch === "c") {
const field = doc.extraFields.find(e => e.id === "categorySwitch")
if (field && field.value === true) {
foundSwitch = true
}
}
if (switchSearch === "d") {
const field = doc.extraFields.find(e => e.id === "deadSwitch")
if (field && field.value === true) {

View file

@ -1,29 +1,18 @@
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[]) => {
export const tagListBuildFromBlueprints = (allDocuments: I_ShortenedDocument[]) => {
let allTags: string[] = []
for (const blueprint of blueprintList) {
const CurrentObjectDB = new PouchDB(blueprint._id)
let 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
const docsTagsArray = allDocuments.map(singleDocument => {
const tags: string[] = singleDocument.extraFields.find(e => e.id === "tags")?.value
return (tags) || []
})
return (tags) || []
})
// @ts-ignore
allTags = [...allTags, ...docsTagsArray] as unknown as string[]
// @ts-ignore
dbDocuments = null
await CurrentObjectDB.close()
}
allTags = [...allTags, ...docsTagsArray] as unknown as string[]
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call

View file

@ -3,7 +3,7 @@
* Toggles dev tools in the current window
*/
export const tipsTricks: string[] = [
"It is possible to search through all documents and all of their fields at once using the following in either the Quick search popup or any of the relationship searches: \" %:whatever-you-need\"",
"It is possible to search through all documents and all of their fields at once using the following in either the Quick search popup or any of the relationship searches: \"%:whatever-you-need\"",
"There is a whole list of really helpful keybinds that can make your use of FA a lot quicker and easier!",
"The settings menu contains a whole assortment of both big and small tweaks to tailor the app to your needs!",
"FA has a Dark Mode that is no mere afterthought and is fully serviceable!",

View file

@ -7,6 +7,7 @@ import Vuex from "vuex"
import blueprintsModule from "./module-blueprints"
import openedDocumentsModule from "./module-openedDocuments"
import allDocumentsModule from "./module-allDocuments"
import keybindsModule from "./module-keybinds"
import dialogsModule from "./module-dialogs"
import optionsModule from "./module-options"
@ -31,6 +32,7 @@ export default store(function ({ Vue }) {
modules: {
blueprintsModule,
openedDocumentsModule,
allDocumentsModule,
keybindsModule,
dialogsModule,
optionsModule,

View file

@ -0,0 +1,33 @@
import { ActionTree } from "vuex"
import { StateInterface } from "../index"
import { AllDocumentsStateInterface } from "./state"
const actions: ActionTree<AllDocumentsStateInterface, StateInterface> = {
markAsNonFirstRun (state) {
state.commit("markAsNonFirstRun")
},
addDocument (state, input) {
state.commit("addDocument", input)
},
updateDocument (state, input) {
state.commit("updateDocument", input)
},
removeDocument (state, input) {
state.commit("removeDocument", input)
},
mapNewDocumentType (state, input) {
state.commit("mapNewDocumentType", input)
},
resetDocuments (state) {
state.commit("resetDocuments")
}
}
export default actions

View file

@ -0,0 +1,33 @@
import { GetterTree } from "vuex"
import { StateInterface } from "../index"
import { AllDocumentsStateInterface } from "./state"
const getters: GetterTree<AllDocumentsStateInterface, StateInterface> = {
getFirstRunState (context) {
return context.firstTime
},
getDocument: (state) => (id: string) => {
return state.docs.docs.find(doc => doc._id === id)
},
getAllDocuments (context) {
return context.docs
},
getAllDocumentsWithoutCategories (context) {
return context.docsWithoutCategories
},
getDocumentsByType: (state) => (id: string) => {
return state.docByType.find(type => type.id === id)
},
getDocumentsByTypeWithoutCategories: (state) => (id: string) => {
return state.docbyTypeWithoutCategories.find(type => type.id === id)
}
}
export default getters

View file

@ -0,0 +1,16 @@
import { Module } from "vuex"
import { StateInterface } from "../index"
import state, { AllDocumentsStateInterface } from "./state"
import actions from "./actions"
import getters from "./getters"
import mutations from "./mutations"
const allDocumentsModule: Module<AllDocumentsStateInterface, StateInterface> = {
namespaced: true,
actions,
getters,
mutations,
state
}
export default allDocumentsModule

View file

@ -0,0 +1,163 @@
import { MutationTree } from "vuex"
import { AllDocumentsStateInterface } from "./state"
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { uid } from "quasar"
const mutation: MutationTree<AllDocumentsStateInterface> = {
markAsNonFirstRun (state: AllDocumentsStateInterface) {
state.firstTime = false
},
addDocument (state: AllDocumentsStateInterface, input: {
doc: I_ShortenedDocument,
}) {
const timestamp = uid()
// Docs
const toAddIndexDocs = state.docs.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
if (!toAddIndexDocs) {
state.docs.docs.push(input.doc)
state.docs.timestamp = timestamp
}
// Docs, no cat
const toAddIndexDocsWithoutCategory = state.docsWithoutCategories.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
if (!toAddIndexDocsWithoutCategory) {
state.docsWithoutCategories.docs.push(input.doc)
state.docsWithoutCategories.timestamp = timestamp
}
// Docs each cat
const typeIndex = state.docByType.findIndex(type => type.id === input.doc.type)
const toAddTypeIndexDocs = state.docByType[typeIndex].docs.findIndex(doc => doc._id === input.doc._id)
if (!toAddTypeIndexDocs) {
state.docByType[typeIndex].docs.push(input.doc)
state.docByType[typeIndex].timestamp = timestamp
}
// Docs each cat, no cat
const typeIndexWithoutCats = state.docbyTypeWithoutCategories.findIndex(type => type.id === input.doc.type)
const toAddTypeIndexDocsWithoutCats = state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.findIndex(doc => doc._id === input.doc._id)
if (!toAddTypeIndexDocsWithoutCats) {
state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.push(input.doc)
state.docbyTypeWithoutCategories[typeIndex].timestamp = timestamp
}
},
updateDocument (state: AllDocumentsStateInterface, input: {
doc: I_ShortenedDocument,
}) {
const timestamp = uid()
const isCategory = input.doc.extraFields.find(e => e.id === "categorySwitch")?.value
// Docs
const toUpdateIndexDocs = state.docs.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
state.docs.docs[toUpdateIndexDocs] = input.doc
state.docs.timestamp = timestamp
// Docs, no cat
const toUpdateIndexDocsWithoutCategory = state.docsWithoutCategories.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
if (!isCategory) {
state.docsWithoutCategories.docs[toUpdateIndexDocsWithoutCategory] = input.doc
}
else {
state.docsWithoutCategories.docs.splice(toUpdateIndexDocsWithoutCategory, 1)
}
state.docsWithoutCategories.timestamp = timestamp
// Docs each cat
const typeIndex = state.docByType.findIndex(type => type.id === input.doc.type)
const toUpdateTypeIndexDocs = state.docByType[typeIndex].docs.findIndex(doc => doc._id === input.doc._id)
state.docByType[typeIndex].docs[toUpdateTypeIndexDocs] = input.doc
state.docByType[typeIndex].timestamp = timestamp
// Docs each cat, no cat
const typeIndexWithoutCats = state.docbyTypeWithoutCategories.findIndex(type => type.id === input.doc.type)
const toUpdateTypeIndexDocsWithoutCats = state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.findIndex(doc => doc._id === input.doc._id)
if (!isCategory) {
state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs[toUpdateTypeIndexDocsWithoutCats] = input.doc
}
else {
state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.splice(toUpdateTypeIndexDocsWithoutCats, 1)
}
state.docbyTypeWithoutCategories[typeIndex].timestamp = timestamp
},
removeDocument (state: AllDocumentsStateInterface, input: {
doc: I_ShortenedDocument
}) {
const timestamp = uid()
// Docs
const toRemoveIndexDocs = state.docs.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
state.docs.docs.splice(toRemoveIndexDocs, 1)
state.docs.timestamp = timestamp
// Docs, no cat
const toRemoveIndexDocsWithoutCategory = state.docsWithoutCategories.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
state.docsWithoutCategories.docs.splice(toRemoveIndexDocsWithoutCategory, 1)
state.docsWithoutCategories.timestamp = timestamp
// Docs each cat
const typeIndex = state.docByType.findIndex(type => type.id === input.doc.type)
const toRemoveTypeIndexDocs = state.docByType[typeIndex].docs.findIndex(doc => doc._id === input.doc._id)
state.docByType[typeIndex].docs.splice(toRemoveTypeIndexDocs, 1)
state.docByType[typeIndex].timestamp = timestamp
// Docs each cat, no cat
const typeIndexWithoutCats = state.docbyTypeWithoutCategories.findIndex(type => type.id === input.doc.type)
const toRemoveTypeIndexDocsWithoutCats = state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.findIndex(doc => doc._id === input.doc._id)
state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.splice(toRemoveTypeIndexDocsWithoutCats, 1)
state.docbyTypeWithoutCategories[typeIndex].timestamp = timestamp
},
mapNewDocumentType (state: AllDocumentsStateInterface, input:{
id: string,
timestamp: string
docs: I_ShortenedDocument[]
}) {
const timestamp = uid()
input.timestamp = timestamp
// Docs each cat
state.docByType.push(input)
// Docs each cat, no cat
const docsWithoutCats = {
id: input.id,
timestamp: timestamp,
docs: input.docs.filter(doc => !doc.extraFields.find(e => e.id === "categorySwitch")?.value)
}
state.docbyTypeWithoutCategories.push(docsWithoutCats)
// Docs
state.docs.docs = [...state.docs.docs, ...input.docs]
state.docs.timestamp = timestamp
// Docs, no cat
state.docsWithoutCategories.docs = [...state.docsWithoutCategories.docs, ...docsWithoutCats.docs]
state.docsWithoutCategories.timestamp = timestamp
},
resetDocuments (state: AllDocumentsStateInterface) {
state.firstTime = true
// Docs
state.docs.docs = []
state.docs.timestamp = uid()
// Docs, no cat
state.docsWithoutCategories.docs = []
state.docsWithoutCategories.timestamp = uid()
// Docs each cat
state.docByType = []
// Docs each cat, no cat
state.docbyTypeWithoutCategories = []
}
}
export default mutation

View file

@ -0,0 +1,41 @@
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
export interface AllDocumentsStateInterface {
firstTime: boolean
docs: {
timestamp: string,
docs: I_ShortenedDocument[],
}
docsWithoutCategories:{
timestamp: string,
docs: I_ShortenedDocument[],
}
docByType: {
id: string
timestamp: string,
docs: I_ShortenedDocument[],
}[]
docbyTypeWithoutCategories: {
id: string
timestamp: string,
docs: I_ShortenedDocument[],
}[]
}
function state (): AllDocumentsStateInterface {
return {
firstTime: true,
docs: {
timestamp: "",
docs: []
},
docsWithoutCategories: {
timestamp: "",
docs: []
},
docByType: [],
docbyTypeWithoutCategories: []
}
}
export default state