fantasia-archive/src/scripts/databaseManager/documentManager.ts
2021-05-15 01:35:18 +02:00

428 lines
14 KiB
TypeScript

import { single_changeRelationshipToAnotherObject, many_changeRelationshipToAnotherObject } from "src/scripts/databaseManager/relationshipManager"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_Blueprint, I_ExtraFields } from "src/interfaces/I_Blueprint"
import PouchDB from "pouchdb"
import { Loading, QSpinnerGears, extend } from "quasar"
/**
* Saves the given project and handles all the needed procedures
*/
export const saveDocument = async (
document: I_OpenedDocument,
allOpenedDocuments: I_OpenedDocument[],
allDocuments: I_ShortenedDocument[],
editModeAfterSave: boolean,
vueInstance: any,
disableLoading = false
) => {
const loadingSetup = {
message: "<h4>Saving document...</h4>",
spinnerColor: "primary",
messageColor: "cultured",
spinnerSize: 120,
backgroundColor: "dark",
// @ts-ignore
spinner: QSpinnerGears
}
// Time for cases when people want to auto-generate A LOT of documents
const saveTimeout = setTimeout(() => {
if (!disableLoading) {
// @ts-ignore
Loading.show(loadingSetup)
}
}, 750)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const currentBlueprint: {extraFields: I_ExtraFields[]} = vueInstance.SGET_blueprint(document.type)
window.FA_dbs[document.type] = new PouchDB(document.type)
let currentDocument = false as unknown as I_OpenedDocument
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
currentDocument = await window.FA_dbs[document.type].get(document._id)
}
catch (error) {
// console.log("Creating new document")
}
let documentCopy = {} as unknown as I_OpenedDocument
if (currentDocument) {
documentCopy = extend(true, {}, document)
documentCopy._rev = currentDocument?._rev
}
else {
documentCopy = extend(true, {}, document)
}
allOpenedDocuments = allOpenedDocuments.filter(doc => doc._id !== document._id)
const listOfNewDocuments: {
name: string
id: string
type: string
}[] = []
// Handle single document autogeneration
const single_relationshipTypesAutoGeneration = ["singleToNoneRelationship", "singleToSingleRelationship", "singleToManyRelationship"]
const single_allRelationshipFieldsAutoGeneration = documentCopy.extraFields.filter(field => {
const currentField = currentBlueprint.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
return (currentField && single_relationshipTypesAutoGeneration.includes(currentField.type))
})
// Update single fields autogeneration
for (const field of single_allRelationshipFieldsAutoGeneration) {
const fieldValue = field.value?.value
if (fieldValue?.isAutoGenerated) {
// Check if the document already exists
const alreadyCreated = listOfNewDocuments.find(e => {
return (e.name === fieldValue.label && e.type === fieldValue.type)
})
// If new document
if (!alreadyCreated) {
listOfNewDocuments.push({
name: fieldValue.label,
id: fieldValue.id,
type: fieldValue.type
})
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const pairedBlueprint: I_Blueprint = vueInstance.SGET_blueprint(fieldValue.type)
const newDocument = {
bgColor: undefined,
color: undefined,
extraFields: [
{
id: "name",
value: fieldValue.label
},
{
id: "parentDoc",
value: ""
},
{
id: "documentColor",
value: ""
},
{
id: "documentBackgroundColor",
value: ""
},
{
id: "finishedSwitch",
value: ""
},
{
id: "minorSwitch",
value: ""
},
{
id: "deadSwitch",
value: ""
},
{
id: "categorySwitch",
value: ""
},
{
id: "order",
value: ""
},
{
id: "tags",
value: []
},
{
id: "categoryDescription",
value: ""
},
{
id: "otherNames",
value: []
}
],
hierarchicalPath: pairedBlueprint.namePlural,
icon: pairedBlueprint.icon,
id: fieldValue.id,
type: fieldValue.type,
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
url: `/project/display-content/${fieldValue.type}/${fieldValue.id}`,
_id: fieldValue.id
}
// @ts-ignore
window.FA_dbs[newDocument.type] = new PouchDB(newDocument.type)
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[newDocument.type].put(newDocument)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
vueInstance.SSET_addDocument({ doc: vueInstance.mapShortDocument(newDocument, vueInstance.SGET_allDocumentsByType(newDocument.type).docs) })
}
// If already created document
else {
fieldValue.id = alreadyCreated.id
fieldValue._id = alreadyCreated.id
}
delete (fieldValue.isAutoGenerated)
}
}
// Handle relationship single 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
return (currentField && single_relationshipTypes.includes(currentField.type))
})
// Update single fields
for (const field of single_allRelationshipFields) {
const single_updatedDocuments: I_OpenedDocument[] = await single_changeRelationshipToAnotherObject(field, documentCopy, currentDocument)
const pairedFieldID = currentBlueprint.extraFields.find(e => e.id === field.id)?.relationshipSettings?.connectedField
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
filteredOpenedDocuments.forEach(doc => {
const toUpdateIndex = doc.extraFields.findIndex(e => e.id === pairedFieldID)
if (toUpdateIndex) {
const matchingDoc = allOpenedDocuments.find(subDoc => subDoc._id === doc._id)
if (matchingDoc) {
matchingDoc.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
}
}
})
// 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]
}
}
})
}
// Handle relationship many fields
const many_relationshipTypes = ["manyToSingleRelationship", "manyToManyRelationship"]
const many_allRelationshipFields = documentCopy.extraFields.filter(field => {
const currentField = currentBlueprint.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
return (currentField && many_relationshipTypes.includes(currentField.type))
})
// Handle many document autogeneration
const many_relationshipTypesAutoGeneration = ["manyToNoneRelationship", "manyToSingleRelationship", "manyToManyRelationship"]
const many_allRelationshipFieldsAutoGeneration = documentCopy.extraFields.filter(field => {
const currentField = currentBlueprint.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
return (currentField && many_relationshipTypesAutoGeneration.includes(currentField.type))
})
// Update many fields autogeneration
for (const field of many_allRelationshipFieldsAutoGeneration) {
const fieldArray = field.value?.value
if (Array.isArray(fieldArray)) {
for (const fieldValue of fieldArray) {
if (fieldValue?.isAutoGenerated) {
// Check if the document already exists
const alreadyCreated = listOfNewDocuments.find(e => {
return (e.name === fieldValue.label && e.type === fieldValue.type)
})
// If new document
if (!alreadyCreated) {
listOfNewDocuments.push({
name: fieldValue.label,
id: fieldValue.id,
type: fieldValue.type
})
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const pairedBlueprint: I_Blueprint = vueInstance.SGET_blueprint(fieldValue.type)
const newDocument = {
bgColor: undefined,
color: undefined,
extraFields: [
{
id: "name",
value: fieldValue.label
},
{
id: "parentDoc",
value: ""
},
{
id: "documentColor",
value: ""
},
{
id: "documentBackgroundColor",
value: ""
},
{
id: "finishedSwitch",
value: ""
},
{
id: "minorSwitch",
value: ""
},
{
id: "deadSwitch",
value: ""
},
{
id: "categorySwitch",
value: ""
},
{
id: "order",
value: ""
},
{
id: "tags",
value: []
},
{
id: "categoryDescription",
value: ""
}
],
hierarchicalPath: pairedBlueprint.namePlural,
icon: pairedBlueprint.icon,
id: fieldValue.id,
type: fieldValue.type,
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
url: `/project/display-content/${fieldValue.type}/${fieldValue.id}`,
_id: fieldValue.id
}
// @ts-ignore
window.FA_dbs[newDocument.type] = new PouchDB(newDocument.type)
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[newDocument.type].put(newDocument)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
vueInstance.SSET_addDocument({ doc: vueInstance.mapShortDocument(newDocument, vueInstance.SGET_allDocumentsByType(newDocument.type).docs) })
}
// If already created document
else {
fieldValue.id = alreadyCreated.id
fieldValue._id = alreadyCreated.id
}
delete (fieldValue.isAutoGenerated)
}
}
}
}
// Update many fields
for (const field of many_allRelationshipFields) {
const many_updatedDocuments: I_OpenedDocument[] = await many_changeRelationshipToAnotherObject(field, documentCopy, currentDocument)
const pairedFieldID = currentBlueprint.extraFields.find(e => e.id === field.id)?.relationshipSettings?.connectedField
const filteredDocuments = many_updatedDocuments.filter(doc => {
return allOpenedDocuments.find(subDoc => {
return subDoc._id === doc._id
})
})
// Update the particular field in each currently opened document
filteredDocuments.forEach(doc => {
const toUpdateIndex = doc.extraFields.findIndex(e => e.id === pairedFieldID)
if (toUpdateIndex) {
const matchingDoc = allOpenedDocuments.find(subDoc => subDoc._id === doc._id)
if (matchingDoc) {
matchingDoc.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
}
}
})
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
documentCopy.hasEdits = false
documentCopy.editMode = false
if (documentCopy.scrollDistance) {
delete (documentCopy.scrollDistance)
}
// Save the document
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[document.type].put(documentCopy)
// Set edit mode for frontend
documentCopy.editMode = editModeAfterSave
clearTimeout(saveTimeout)
if (!disableLoading) {
Loading.hide()
}
return { documentCopy, allOpenedDocuments }
}
export const addFieldToDocument = async (targetDocumentID: string, fieldID: string, blueprintID: string) => {
const BlueprintsDB = new PouchDB("blueprints")
const currentBlueprint: {extraFields: I_ExtraFields[], _id: string} = await BlueprintsDB.get(blueprintID)
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: ""
}
targetDocument.extraFields.push(newField)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await window.FA_dbs[currentBlueprint._id].put(targetDocument)
}