mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-06-23 08:30:20 +12:00
0.1.6 - DEV - 4
This commit is contained in:
parent
5687f047f0
commit
14834a6a54
|
@ -83,6 +83,12 @@
|
|||
@trigger-dialog-close="licenseDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Repair project dialog -->
|
||||
<repairProjectDialog
|
||||
:dialog-trigger="repairProjectDialogTrigger"
|
||||
@trigger-dialog-close="repairProjectDialogClose"
|
||||
/>
|
||||
|
||||
<q-btn-group
|
||||
flat
|
||||
class="AppControl__buttons"
|
||||
|
@ -237,6 +243,35 @@
|
|||
|
||||
<q-separator dark />
|
||||
|
||||
<q-item clickable>
|
||||
<q-item-section>Advanced project tools</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="keyboard_arrow_right" />
|
||||
</q-item-section>
|
||||
<q-menu anchor="top end" self="top start">
|
||||
<q-list class="bg-gunmetal text-accent">
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
active
|
||||
active-class="bg-gunmetal-light text-cultured"
|
||||
class="noHigh"
|
||||
@click="repairProjectAssignUID"
|
||||
:disable="!projectExists"
|
||||
>
|
||||
<q-item-section>Repair legacy project</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="mdi-folder-open-outline" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-item>
|
||||
|
||||
<q-separator dark />
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
|
@ -424,6 +459,7 @@ import keybindCheatsheetDialog from "src/components/dialogs/KeybindCheatsheet.vu
|
|||
import importProjectCheckDialog from "src/components/dialogs/ImportProjectCheck.vue"
|
||||
import mergeProjectCheckDialog from "src/components/dialogs/MergeProjectCheck.vue"
|
||||
import newProjectCheckDialog from "src/components/dialogs/NewProjectCheck.vue"
|
||||
import repairProjectDialog from "src/components/dialogs/RepairProject.vue"
|
||||
import aboutAppDialog from "src/components/dialogs/AboutApp.vue"
|
||||
import changeLogDialog from "src/components/dialogs/ChangeLog.vue"
|
||||
import programSettingsDialog from "src/components/dialogs/ProgramSettings.vue"
|
||||
|
@ -453,7 +489,8 @@ import appLogo from "src/assets/appLogo.png"
|
|||
newDocumentDialog,
|
||||
existingDocumentDialog,
|
||||
tipsTricksTriviaDialog,
|
||||
licenseDialog
|
||||
licenseDialog,
|
||||
repairProjectDialog
|
||||
}
|
||||
})
|
||||
export default class AppControl extends BaseClass {
|
||||
|
@ -726,6 +763,19 @@ export default class AppControl extends BaseClass {
|
|||
licenseAssignUID () {
|
||||
this.licenseDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Repair project dialog
|
||||
/****************************************************************/
|
||||
|
||||
repairProjectDialogTrigger: string | false = false
|
||||
repairProjectDialogClose () {
|
||||
this.repairProjectDialogTrigger = false
|
||||
}
|
||||
|
||||
repairProjectAssignUID () {
|
||||
this.repairProjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@
|
|||
Prevent auto-scrolling
|
||||
<q-icon name="mdi-help-circle" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
Determines if the documents will recall their scroll distances and auto-scroll on switching ot not.
|
||||
Determines if the documents will recall their scroll distances and auto-scroll on switching or not.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
|
|
259
src/components/dialogs/RepairProject.vue
Normal file
259
src/components/dialogs/RepairProject.vue
Normal file
|
@ -0,0 +1,259 @@
|
|||
<template>
|
||||
<q-dialog
|
||||
v-model="dialogModel"
|
||||
@hide="triggerDialogClose"
|
||||
no-route-dismiss
|
||||
:persistent="repairOngoing || repairFinished"
|
||||
>
|
||||
<q-card v-if="!repairOngoing && !repairFinished" dark class="documentCloseDialog">
|
||||
<q-card-section class="row justify-center">
|
||||
<h6 class="text-center q-my-sm">Repair legacy project</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="row justify-center q-mx-xl">
|
||||
<div>
|
||||
If you are working with project created (or added via Merge) before version 0.1.6, this process might significantly improve your performance.
|
||||
<br>
|
||||
<br>
|
||||
However, before proceeding, please export your current project first to prevent a <span class="text-bold text-secondary">POSSIBLE CORRUPTION</span> of your current project data!
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="around" class="q-mx-xl q-mt-lg q-mb-md">
|
||||
<q-btn
|
||||
flat
|
||||
label="Cancel"
|
||||
color="accent"
|
||||
v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Export project"
|
||||
color="primary"
|
||||
@click="commenceExport"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
label="Repair project"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="repairProject" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
<q-card v-if="repairOngoing && !repairFinished" dark class="documentCloseDialog">
|
||||
<q-card-section class="row justify-center">
|
||||
<h6 class="text-center q-my-sm">Repairing...</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="row justify-center q-mx-xl">
|
||||
<div>
|
||||
<b>Processing document types: <span class="text-primary">{{processedBlueprints}}/{{blueprintCount}}</span></b>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="row justify-center q-mx-xl">
|
||||
<div>
|
||||
<b><span class="text-primary">{{currectDocumentType}}</span></b>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="row justify-center q-mx-xl q-mb-lg">
|
||||
<q-linear-progress stripe round dark size="20px" :value="progressCounter" color="primary" class="q-mt-sm">
|
||||
<div class="absolute-full flex flex-center">
|
||||
<q-badge text-color="accent" color="dark" :label="`${processedDocument}/${documentCount}`" />
|
||||
</div>
|
||||
</q-linear-progress>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
<q-card v-if="!repairOngoing && repairFinished" dark class="documentCloseDialog">
|
||||
<q-card-section class="row justify-center">
|
||||
<h6 class="text-center q-my-sm">Project succesfully repaired!</h6>
|
||||
</q-card-section>
|
||||
<q-card-actions align="around" class="q-mx-xl q-mt-lg q-mb-md">
|
||||
<q-btn
|
||||
flat
|
||||
label="Reload Fantasia Archive"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="reloadFA" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { remote } from "electron"
|
||||
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
|
||||
import DialogBase from "src/components/dialogs/_DialogBase"
|
||||
import { retrieveCurrentProjectName, exportProject } from "src/scripts/projectManagement/projectManagent"
|
||||
import { Loading, QSpinnerGears } from "quasar"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_Blueprint } from "src/interfaces/I_Blueprint"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class RepairProjectDialog extends DialogBase {
|
||||
/**
|
||||
* React to dialog opening request
|
||||
*/
|
||||
@Watch("dialogTrigger")
|
||||
checkForOpenedProject (val: string|false) {
|
||||
if (val) {
|
||||
this.openDialog()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the the dialog if project is present on the window
|
||||
*/
|
||||
openDialog () {
|
||||
if (this.SGET_getDialogsState) {
|
||||
return
|
||||
}
|
||||
this.repairOngoing = false
|
||||
this.repairFinished = false
|
||||
this.SSET_setDialogState(true)
|
||||
this.dialogModel = true
|
||||
}
|
||||
|
||||
processedBlueprints = 0
|
||||
blueprintCount = 0
|
||||
processedDocument = 0
|
||||
documentCount = 0
|
||||
currectDocumentType = ""
|
||||
|
||||
get progressCounter () {
|
||||
return (this.processedDocument / this.documentCount)
|
||||
}
|
||||
|
||||
repairFinished = false
|
||||
repairOngoing = false
|
||||
|
||||
/**
|
||||
* Repair a new project
|
||||
*/
|
||||
async repairProject () {
|
||||
this.repairOngoing = true
|
||||
|
||||
this.processedBlueprints = 0
|
||||
this.blueprintCount = this.SGET_allBlueprints.length
|
||||
|
||||
for (const blueprint of this.SGET_allBlueprints) {
|
||||
this.processedBlueprints++
|
||||
|
||||
// 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)
|
||||
|
||||
this.documentCount = dbDocuments.length
|
||||
this.processedDocument = 0
|
||||
this.currectDocumentType = blueprint.namePlural
|
||||
|
||||
await this.sleep(800)
|
||||
|
||||
for (let document of dbDocuments) {
|
||||
document = await this.remapDocument(document, blueprint)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
await window.FA_dbs[blueprint._id].put(document)
|
||||
}
|
||||
|
||||
await this.sleep(600)
|
||||
}
|
||||
|
||||
this.repairOngoing = false
|
||||
this.repairFinished = true
|
||||
}
|
||||
|
||||
async remapDocument (document: I_ShortenedDocument, blueprint: I_Blueprint) {
|
||||
const allSingleToNoneFields = blueprint.extraFields.filter(e => e.type === "singleToNoneRelationship")
|
||||
const allSingleToSingleFields = blueprint.extraFields.filter(e => e.type === "singleToSingleRelationship")
|
||||
const allSingleToManyFields = blueprint.extraFields.filter(e => e.type === "singleToManyRelationship")
|
||||
|
||||
const allManyToNoneFields = blueprint.extraFields.filter(e => e.type === "manyToNoneRelationship")
|
||||
const allManyToSingleFields = blueprint.extraFields.filter(e => e.type === "manyToSingleRelationship")
|
||||
const allManyToManyFields = blueprint.extraFields.filter(e => e.type === "manyToManyRelationship")
|
||||
|
||||
for (const field of document.extraFields) {
|
||||
// Single field remap
|
||||
if (allSingleToNoneFields.find(e => e.id === field.id) ||
|
||||
allSingleToSingleFields.find(e => e.id === field.id) ||
|
||||
allSingleToManyFields.find(e => e.id === field.id)) {
|
||||
if (field.value && field.value.value) {
|
||||
const blueprintField = blueprint.extraFields.find(e => e.id === field.id)
|
||||
field.value.value = {
|
||||
_id: field.value.value._id,
|
||||
id: field.value.value._id,
|
||||
type: field.value.value.type,
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
url: `/project/display-content/${field.value.value.type}/${field.value.value._id}`,
|
||||
pairedField: (blueprintField?.relationshipSettings?.connectedField) || ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Many field remap
|
||||
if (allManyToNoneFields.find(e => e.id === field.id) ||
|
||||
allManyToSingleFields.find(e => e.id === field.id) ||
|
||||
allManyToManyFields.find(e => e.id === field.id)) {
|
||||
if (field.value && field.value.value) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
for (const [i, subValue] of field.value.value.entries()) {
|
||||
const blueprintField = blueprint.extraFields.find(e => e.id === field.id)
|
||||
field.value.value[i] = {
|
||||
_id: subValue._id,
|
||||
id: subValue._id,
|
||||
type: subValue.type,
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
url: `/project/display-content/${subValue.type}/${subValue._id}`,
|
||||
pairedField: (blueprintField?.relationshipSettings?.connectedField) || ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.processedDocument++
|
||||
|
||||
await this.sleep(25)
|
||||
|
||||
return document
|
||||
}
|
||||
|
||||
reloadFA () {
|
||||
remote.getCurrentWindow().reload()
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the current project
|
||||
*/
|
||||
async commenceExport () {
|
||||
const projectName = await retrieveCurrentProjectName()
|
||||
const setup = {
|
||||
message: "<h4>Exporting current project...</h4>",
|
||||
spinnerColor: "primary",
|
||||
messageColor: "cultured",
|
||||
spinnerSize: 120,
|
||||
backgroundColor: "dark",
|
||||
// @ts-ignore
|
||||
spinner: QSpinnerGears
|
||||
}
|
||||
exportProject(projectName, Loading, setup, this.$q)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.documentCloseDialog {
|
||||
min-width: 600px;
|
||||
}
|
||||
</style>
|
|
@ -479,10 +479,11 @@ export default class Field_MultiRelationship extends FieldBase {
|
|||
* Also reload the local object list
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue?.value) ? this.inputDataValue.value : []
|
||||
reactToInputChanges (val : I_RelationshipPair) {
|
||||
const localCopy: I_RelationshipPair = extend(true, {}, val)
|
||||
this.localInput = (localCopy?.value) ? localCopy.value : []
|
||||
|
||||
const notes = (!this.inputDataValue?.addedValues) ? [] : this.inputDataValue.addedValues
|
||||
const notes = (!localCopy?.addedValues) ? [] : localCopy.addedValues
|
||||
this.inputNotes = notes.filter(single => this.localInput.find(e => single.pairedId === e._id))
|
||||
|
||||
this.checkNotes()
|
||||
|
@ -615,30 +616,41 @@ export default class Field_MultiRelationship extends FieldBase {
|
|||
// 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 : []
|
||||
|
||||
this.localInput.forEach((s, index) => {
|
||||
const toRemoveIndexList: number[] = []
|
||||
|
||||
for (const [index] of this.localInput.entries()) {
|
||||
// Proceed only if the local input is properly set up
|
||||
if (s._id) {
|
||||
if (this.localInput[index]._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 (!allDbObjects.docs.find(e => e._id === s._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput.splice(index, 1)
|
||||
|
||||
if (!allDbObjects.docs.find(e => e._id === this.localInput[index]._id)) {
|
||||
allDbObjects.docs.forEach(e => {
|
||||
if (e._id === this.localInput[index]._id) {
|
||||
console.log(extend(true, {}, this.localInput[index]))
|
||||
console.log(extend(true, {}, e))
|
||||
}
|
||||
})
|
||||
toRemoveIndexList.push(index)
|
||||
}
|
||||
// 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 = allDbObjects.docs.find(e => e._id === s._id)
|
||||
|
||||
if (matchedFieldContent && (
|
||||
this.localInput[index].label !== matchedFieldContent.label ||
|
||||
this.localInput[index]?.isDead !== matchedFieldContent.extraFields.find(e => e.id === "deadSwitch")?.value)
|
||||
) {
|
||||
const matchedFieldContent = allDbObjects.docs.find(e => e._id === this.localInput[index]._id)
|
||||
if (matchedFieldContent) {
|
||||
this.localInput[index].label = matchedFieldContent.label
|
||||
this.localInput[index].isDead = matchedFieldContent.extraFields.find(e => e.id === "deadSwitch")?.value
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.allTypeDocuments = allDbObjects.docs
|
||||
|
||||
if (toRemoveIndexList.length > 0) {
|
||||
toRemoveIndexList.forEach((e, i) => {
|
||||
this.localInput.splice(i, 1)
|
||||
})
|
||||
this.signalInput(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -692,7 +704,7 @@ export default class Field_MultiRelationship extends FieldBase {
|
|||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
signalInput (isSilent = false) {
|
||||
this.checkNotes()
|
||||
this.inputNotes = this.inputNotes.filter(single => this.localInput.find(e => single.pairedId === e._id))
|
||||
|
||||
|
@ -706,7 +718,8 @@ export default class Field_MultiRelationship extends FieldBase {
|
|||
pairedField: (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
|
||||
}
|
||||
}),
|
||||
addedValues: this.inputNotes
|
||||
addedValues: this.inputNotes,
|
||||
isSilent: isSilent
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -578,7 +578,6 @@ export default class Field_SingleRelationship extends FieldBase {
|
|||
])]
|
||||
}
|
||||
})
|
||||
|
||||
// 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 never existed
|
||||
|
|
|
@ -7,19 +7,18 @@
|
|||
|
||||
### Known issues
|
||||
|
||||
- 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
|
||||
|
||||
- Massive overhaul of how data is being handles across the app!
|
||||
- **Massive overhaul of how data is being handles across the app!**
|
||||
- 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
|
||||
- Fixed app starting in mutliple windows when ran multiple times.
|
||||
- FIxed more typos across the app
|
||||
|
||||
### New features
|
||||
|
||||
|
|
|
@ -632,8 +632,7 @@ 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
|
||||
if (inputData.isSilent) {
|
||||
dataPass.doc.hasEdits = false
|
||||
}
|
||||
|
||||
|
|
|
@ -169,8 +169,6 @@ export const addFieldToDocument = async (targetDocumentID: string, fieldID: stri
|
|||
|
||||
targetDocument.extraFields.push(newField)
|
||||
|
||||
console.log(newField)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
await window.FA_dbs[currentBlueprint._id].put(targetDocument)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ export const createNewProject = async (projectName: string, vueRouter: any, quas
|
|||
message: `New project succesfully created`
|
||||
})
|
||||
vueInstance.SSET_resetDocuments()
|
||||
vueInstance.SSET_resetAllDocuments()
|
||||
/* eslint-enable */
|
||||
|
||||
await ProjectDB.close()
|
||||
|
|
|
@ -14,6 +14,7 @@ const mutation: MutationTree<AllDocumentsStateInterface> = {
|
|||
doc: I_ShortenedDocument,
|
||||
}) {
|
||||
const timestamp = uid()
|
||||
const isCategory = input.doc.extraFields.find(e => e.id === "categorySwitch")?.value
|
||||
|
||||
// Docs
|
||||
const toAddIndexDocs = state.docs.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
|
||||
|
@ -24,7 +25,7 @@ const mutation: MutationTree<AllDocumentsStateInterface> = {
|
|||
|
||||
// Docs, no cat
|
||||
const toAddIndexDocsWithoutCategory = state.docsWithoutCategories.docs.findIndex(doc => doc.type === input.doc.type && doc._id === input.doc._id)
|
||||
if (toAddIndexDocsWithoutCategory < 0) {
|
||||
if (toAddIndexDocsWithoutCategory < 0 && !isCategory) {
|
||||
state.docsWithoutCategories.docs.push(input.doc)
|
||||
state.docsWithoutCategories.timestamp = timestamp
|
||||
}
|
||||
|
@ -40,7 +41,7 @@ const mutation: MutationTree<AllDocumentsStateInterface> = {
|
|||
// 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 < 0) {
|
||||
if (toAddTypeIndexDocsWithoutCats < 0 && !isCategory) {
|
||||
state.docbyTypeWithoutCategories[typeIndexWithoutCats].docs.push(input.doc)
|
||||
state.docbyTypeWithoutCategories[typeIndex].timestamp = timestamp
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue