mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-06-02 02:14:47 +12:00
0.1.7-DEV-8: Added export support (MD for now)
This commit is contained in:
parent
a68a8cc2c5
commit
470c0001a1
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "fantasiaarchive",
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -8980,6 +8980,11 @@
|
|||
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||
"dev": true
|
||||
},
|
||||
"indento": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/indento/-/indento-1.1.13.tgz",
|
||||
"integrity": "sha512-YZWk3mreBEM7sBPddsiQnW9Z8SGg/gNpFfscJq00HCDS7pxcQWWWMSVKJU7YkTRyDu1Zv2s8zaK8gQWKmCXHlg=="
|
||||
},
|
||||
"indexes-of": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
|
||||
|
@ -9643,6 +9648,14 @@
|
|||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"json2md": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/json2md/-/json2md-1.10.0.tgz",
|
||||
"integrity": "sha512-Rq7mx1wnLZIKn4vb4hrVUMVxHYNRzMVoG3PwYzx6uRlGGjcgjqIS7J0h553Ri5mbLq8zX61jVP+eL8rGZ68zSA==",
|
||||
"requires": {
|
||||
"indento": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"json3": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"apexcharts": "^3.26.0",
|
||||
"axios": "^0.18.1",
|
||||
"core-js": "^3.6.5",
|
||||
"json2md": "^1.10.0",
|
||||
"katex": "^0.12.0",
|
||||
"lodash": "^4.17.20",
|
||||
"mermaid": "^8.8.4",
|
||||
|
@ -81,4 +82,4 @@
|
|||
"npm": ">= 6.13.4",
|
||||
"yarn": ">= 1.21.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,8 +562,8 @@ export default class BaseClass extends Vue {
|
|||
const parentDocInDB = (list.find(p => p._id === parentDoc?._id))
|
||||
|
||||
if (!parentDoc || (parentDoc && !parentDocInDB)) {
|
||||
const singleBlueprintName = this.SGET_allBlueprints.find(e => e._id === document.type)?.nameSingular
|
||||
hierarchicalString += singleBlueprintName
|
||||
const pluralBlueprintName = this.SGET_allBlueprints.find(e => e._id === document.type)?.namePlural
|
||||
hierarchicalString += pluralBlueprintName
|
||||
return hierarchicalString
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,13 @@
|
|||
@trigger-dialog-close="tipsTricksDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Export project dialog -->
|
||||
<exportProjectDialog
|
||||
:dialog-trigger="exportProjectDialogTrigger"
|
||||
:prepicked-ids="[prepickedID]"
|
||||
@trigger-dialog-close="exportProjectDialogClose"
|
||||
/>
|
||||
|
||||
<q-page-sticky position="top-right"
|
||||
class="documentControl bg-dark"
|
||||
:class="{'fullScreen': hideHierarchyTree}"
|
||||
|
@ -294,6 +301,35 @@
|
|||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator vertical inset color="accent"
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
:color="(!hasEdits) ? 'secondary' : 'primary'"
|
||||
icon="mdi-database-export-outline"
|
||||
@click="commenceExport"
|
||||
outline
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Export current project
|
||||
<span class="text-secondary" v-if="!hasEdits">
|
||||
<br>
|
||||
<br>
|
||||
Document has active edits.
|
||||
<br>
|
||||
These will not be exported.
|
||||
<br>
|
||||
Please save first.
|
||||
</span>
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator vertical inset color="accent"
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0 && this.$route.path !== '/project'"
|
||||
/>
|
||||
|
@ -333,6 +369,7 @@ import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentChec
|
|||
import advancedSearchGuideDialog from "src/components/dialogs/AdvancedSearchGuide.vue"
|
||||
import keybindCheatsheetDialog from "src/components/dialogs/KeybindCheatsheet.vue"
|
||||
import tipsTricksTriviaDialog from "src/components/dialogs/TipsTricksTrivia.vue"
|
||||
import exportProjectDialog from "src/components/dialogs/ExportProject.vue"
|
||||
|
||||
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { extend, Loading, QSpinnerGears } from "quasar"
|
||||
|
@ -349,7 +386,8 @@ import { retrieveCurrentProjectName, saveProject } from "src/scripts/projectMana
|
|||
deleteDocumentCheckDialog,
|
||||
advancedSearchGuideDialog,
|
||||
keybindCheatsheetDialog,
|
||||
tipsTricksTriviaDialog
|
||||
tipsTricksTriviaDialog,
|
||||
exportProjectDialog
|
||||
}
|
||||
})
|
||||
export default class DocumentControl extends BaseClass {
|
||||
|
@ -398,8 +436,13 @@ export default class DocumentControl extends BaseClass {
|
|||
this.deleteObjectAssignUID()
|
||||
}
|
||||
|
||||
// Export document - NONE
|
||||
if (this.determineKeyBind("exportDocument") && this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
|
||||
this.commenceExport()
|
||||
}
|
||||
|
||||
// Edit document - CTRL + E
|
||||
if (this.determineKeyBind("editDocument") && this.currentyEditable && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
|
||||
if (this.determineKeyBind("editDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState && this.$route.path !== "/project") {
|
||||
this.toggleEditMode()
|
||||
}
|
||||
|
||||
|
@ -489,6 +532,19 @@ export default class DocumentControl extends BaseClass {
|
|||
this.deleteObjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Export project dialog
|
||||
/****************************************************************/
|
||||
|
||||
exportProjectDialogTrigger: string | false = false
|
||||
exportProjectDialogClose () {
|
||||
this.exportProjectDialogTrigger = false
|
||||
}
|
||||
|
||||
exportProjectAssignUID () {
|
||||
this.exportProjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// New document dialog
|
||||
/****************************************************************/
|
||||
|
@ -774,6 +830,16 @@ export default class DocumentControl extends BaseClass {
|
|||
this.SSET_updateDocument({ doc: this.mapShortDocument(doc, this.SGET_allDocumentsByType(doc.type).docs) })
|
||||
}
|
||||
}
|
||||
|
||||
prepickedID = ""
|
||||
|
||||
commenceExport () {
|
||||
const currentDocument = this.findRequestedOrActiveDocument()
|
||||
// @ts-ignore
|
||||
this.prepickedID = currentDocument._id
|
||||
|
||||
this.exportProjectAssignUID()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@
|
|||
@trigger-dialog-close="repairProjectDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Export project dialog -->
|
||||
<exportProjectDialog
|
||||
:dialog-trigger="exportProjectDialogTrigger"
|
||||
@trigger-dialog-close="exportProjectDialogClose"
|
||||
/>
|
||||
|
||||
<q-btn-group
|
||||
flat
|
||||
class="AppControl__buttons"
|
||||
|
@ -241,21 +247,6 @@
|
|||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
active
|
||||
active-class="bg-gunmetal-light text-cultured"
|
||||
class="noHigh"
|
||||
@click="mergeProjectAssignUID"
|
||||
:disable="!projectExists"
|
||||
>
|
||||
<q-item-section>Merge another project into the current one</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="mdi-folder-plus-outline" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator dark />
|
||||
|
||||
<q-item clickable>
|
||||
|
@ -266,6 +257,38 @@
|
|||
<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="mergeProjectAssignUID"
|
||||
:disable="!projectExists"
|
||||
>
|
||||
<q-item-section>Merge another project into the current one</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="mdi-folder-plus-outline" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
active
|
||||
active-class="bg-gunmetal-light text-cultured"
|
||||
class="noHigh"
|
||||
@click="exportProjectAssignUID"
|
||||
:disable="!projectExists"
|
||||
>
|
||||
<q-item-section>Export project/documents</q-item-section>
|
||||
<q-item-section avatar>
|
||||
<q-icon name="mdi-database-export-outline" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator dark />
|
||||
|
||||
<q-item
|
||||
v-close-popup
|
||||
clickable
|
||||
|
@ -483,6 +506,7 @@ import newDocumentDialog from "src/components/dialogs/NewDocument.vue"
|
|||
import existingDocumentDialog from "src/components/dialogs/ExistingDocument.vue"
|
||||
import tipsTricksTriviaDialog from "src/components/dialogs/TipsTricksTrivia.vue"
|
||||
import licenseDialog from "src/components/dialogs/License.vue"
|
||||
import exportProjectDialog from "src/components/dialogs/ExportProject.vue"
|
||||
|
||||
import { Loading, QSpinnerGears } from "quasar"
|
||||
import { retrieveCurrentProjectName, saveProject } from "src/scripts/projectManagement/projectManagent"
|
||||
|
@ -505,7 +529,8 @@ import appLogo from "src/assets/appLogo.png"
|
|||
existingDocumentDialog,
|
||||
tipsTricksTriviaDialog,
|
||||
licenseDialog,
|
||||
repairProjectDialog
|
||||
repairProjectDialog,
|
||||
exportProjectDialog
|
||||
}
|
||||
})
|
||||
export default class AppControl extends BaseClass {
|
||||
|
@ -659,6 +684,19 @@ export default class AppControl extends BaseClass {
|
|||
this.mergeProjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Export project dialog
|
||||
/****************************************************************/
|
||||
|
||||
exportProjectDialogTrigger: string | false = false
|
||||
exportProjectDialogClose () {
|
||||
this.exportProjectDialogTrigger = false
|
||||
}
|
||||
|
||||
exportProjectAssignUID () {
|
||||
this.exportProjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// New project dialog
|
||||
/****************************************************************/
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
class="existingDocumentPopup"
|
||||
>
|
||||
|
||||
<q-card-section class="row items-center">
|
||||
<q-card-section class="row items-center">
|
||||
<h6 class="text-center q-my-sm">Open existing document</h6>
|
||||
</q-card-section>
|
||||
|
||||
|
|
834
src/components/dialogs/ExportProject.vue
Normal file
834
src/components/dialogs/ExportProject.vue
Normal file
|
@ -0,0 +1,834 @@
|
|||
<template>
|
||||
|
||||
<q-dialog
|
||||
v-model="dialogModel"
|
||||
@before-hide="triggerDialogClose"
|
||||
:persistent="exportOngoing"
|
||||
|
||||
>
|
||||
<q-card
|
||||
v-if="!exportOngoing"
|
||||
class="exportDialog"
|
||||
dark
|
||||
>
|
||||
<q-card-section class="row justify-center text-center">
|
||||
<h6 class="text-center q-my-sm">Export project/documents</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<div class="row justify-center">
|
||||
<div class="col-4">
|
||||
<div class="q-mx-lg">
|
||||
<q-select
|
||||
class="exportTypeSelect"
|
||||
dark
|
||||
popup-content-class="menuResizer"
|
||||
:options="exportFormats"
|
||||
label="Export file format"
|
||||
filled
|
||||
input-debounce="0"
|
||||
v-model="selectedExportFormat"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
class="q-mt-lg"
|
||||
dark color="primary"
|
||||
v-model="exportWholeProject"
|
||||
label="Export whole project?"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
class="q-mt-lg"
|
||||
dark color="primary"
|
||||
v-model="includeTags"
|
||||
label="Include tags in the export?"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
class="q-mt-lg"
|
||||
dark color="primary"
|
||||
v-model="includeHierarchyPath"
|
||||
label="Include hierarchical path in the export?"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
class="q-mt-lg"
|
||||
dark color="primary"
|
||||
v-model="includeIsDead"
|
||||
label="Include dead/gone/destroyed documents in the export?"
|
||||
/>
|
||||
|
||||
<q-checkbox
|
||||
v-if="includeIsDead"
|
||||
class="q-mt-lg"
|
||||
dark color="primary"
|
||||
v-model="hideDeadInformation"
|
||||
label="Hide dead/gone/destroyed status in the exported documents?"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-8">
|
||||
<div
|
||||
style="height: 100%;"
|
||||
class="q-mx-lg"
|
||||
>
|
||||
<div
|
||||
style="height: 100%; line-height: 2;"
|
||||
class="column justify-center items-center"
|
||||
v-if="exportWholeProject"
|
||||
>
|
||||
Please note that:
|
||||
<span class="text-bold text-secondary">
|
||||
The more documents, the slower export.
|
||||
</span>
|
||||
<span>
|
||||
FA currently needs to generate individual files for <span class="text-bold text-primary">{{SGET_allDocuments.docs.length}} </span> documents.
|
||||
</span>
|
||||
</div>
|
||||
<q-select
|
||||
ref="ref_exportDocument"
|
||||
class="exportDocumentSelect"
|
||||
dark
|
||||
popup-content-class="menuResizer"
|
||||
v-if="!exportWholeProject"
|
||||
menu-anchor="bottom middle"
|
||||
menu-self="top middle"
|
||||
:options="filteredExistingInput"
|
||||
use-input
|
||||
multiple
|
||||
use-chips
|
||||
filled
|
||||
label="Selected documents"
|
||||
input-debounce="500"
|
||||
v-model="exportDocumentsModel"
|
||||
@filter="filterExistingSelect"
|
||||
>
|
||||
<template v-slot:append v-if="!hideAdvSearchCheatsheetButton">
|
||||
<q-btn round dense flat icon="mdi-help-rhombus" @click.stop.prevent="SSET_setAdvSearchWindowVisible"
|
||||
>
|
||||
<q-tooltip :delay="500">
|
||||
Open search cheatsheet
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</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="`color: ${opt.color}; background-color: ${opt.bgColor}`"
|
||||
@mouseleave="setDocumentPreviewClose"
|
||||
>
|
||||
<documentPreview
|
||||
:document-id="opt._id"
|
||||
:external-close-trigger="documentPreviewClose"
|
||||
:special-z-index="999999999"
|
||||
:custom-anchor="'top end'"
|
||||
:custom-self="'center left'"
|
||||
:custom-delay="1200"
|
||||
/>
|
||||
<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>
|
||||
<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"
|
||||
v-html="`${input}`"
|
||||
>
|
||||
</q-chip>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
removable
|
||||
dense
|
||||
@remove="removeInput(scope)"
|
||||
:tabindex="scope.tabindex"
|
||||
:color="(scope.opt.isAutoGenerated) ? 'teal-3' : 'accent'"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
|
||||
<div
|
||||
class="relationShipChipOverlay"
|
||||
@mouseleave="setDocumentPreviewClose"
|
||||
/>
|
||||
|
||||
<div class="relationShipChipContent">
|
||||
<template v-if="scope.opt.isDead">
|
||||
†
|
||||
</template>
|
||||
{{ stripTags(scope.opt.label) }}
|
||||
</div>
|
||||
<documentPreview
|
||||
:special-z-index="999999999"
|
||||
:custom-delay="1200"
|
||||
:document-id="scope.opt._id"
|
||||
:external-close-trigger="documentPreviewClose"
|
||||
/>
|
||||
|
||||
</q-chip>
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right" class="q-mb-lg q-mr-xl">
|
||||
<q-btn flat label="Cancel" color="accent" v-close-popup class="q-mr-lg" />
|
||||
<q-btn
|
||||
:flat="!exportWholeProject && exportDocumentsModel.length === 0"
|
||||
:outline="exportWholeProject || exportDocumentsModel.length > 0"
|
||||
label="Export"
|
||||
color="primary"
|
||||
:disable="!exportWholeProject && exportDocumentsModel.length === 0"
|
||||
@click="exportDocuments"
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
|
||||
<q-card v-if="exportOngoing" dark class="exportDialog">
|
||||
<q-card-section class="row justify-center">
|
||||
<h6 class="text-center q-my-sm">Exporting...</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="row justify-center q-mx-xl">
|
||||
<div>
|
||||
Current document: {{currentDocName}}
|
||||
</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="`${exportedDocuments}/${exportList.length}`" />
|
||||
</div>
|
||||
</q-linear-progress>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { Component, Watch, Prop } from "vue-property-decorator"
|
||||
import { remote } from "electron"
|
||||
import { retrieveCurrentProjectName } from "src/scripts/projectManagement/projectManagent"
|
||||
// @ts-ignore
|
||||
import json2md from "json2md/lib/index.js"
|
||||
import DialogBase from "src/components/dialogs/_DialogBase"
|
||||
import { uid, extend } from "quasar"
|
||||
import fs from "fs-extra"
|
||||
import documentPreview from "src/components/DocumentPreview.vue"
|
||||
|
||||
import { I_ExportObject } from "src/interfaces/I_ExportObject"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_Blueprint } from "src/interfaces/I_Blueprint"
|
||||
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
documentPreview
|
||||
}
|
||||
})
|
||||
export default class ExportProject extends DialogBase {
|
||||
/**
|
||||
* React to dialog opening request
|
||||
*/
|
||||
@Watch("dialogTrigger")
|
||||
openDialog (val: string|false) {
|
||||
if (val) {
|
||||
if (this.SGET_getDialogsState) {
|
||||
return
|
||||
}
|
||||
this.SSET_setDialogState(true)
|
||||
this.dialogModel = true
|
||||
|
||||
this.resetLocalData()
|
||||
this.reloadOptions()
|
||||
this.populateExportObjectDialog()
|
||||
|
||||
if (this.prepickedIds.length > 0) {
|
||||
// @ts-ignore
|
||||
this.exportDocumentsModel = this.SGET_allDocuments.docs.filter(doc => {
|
||||
return this.prepickedIds.includes(doc._id)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetLocalData () {
|
||||
this.selectedExportFormat = "Markdown - MD"
|
||||
this.exportWholeProject = false
|
||||
this.includeTags = false
|
||||
this.includeHierarchyPath = false
|
||||
this.hideDeadInformation = false
|
||||
this.includeIsDead = true
|
||||
this.exportDocumentsModel = []
|
||||
this.exportOngoing = false
|
||||
this.exportList = []
|
||||
}
|
||||
|
||||
@Prop(({
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
})) readonly prepickedIds!: string[]
|
||||
|
||||
exportFormats = [
|
||||
"Markdown - MD"
|
||||
// "Adobe Reader - PDF",
|
||||
// "Open office document - ODT",
|
||||
// "MS Word document - DOCX"
|
||||
]
|
||||
|
||||
selectedExportFormat = "Markdown - MD"
|
||||
|
||||
exportWholeProject = false
|
||||
|
||||
includeTags = false
|
||||
|
||||
includeHierarchyPath = false
|
||||
|
||||
hideDeadInformation = false
|
||||
|
||||
includeIsDead = true
|
||||
|
||||
setDocumentPreviewClose () {
|
||||
this.documentPreviewClose = uid()
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads local options
|
||||
*/
|
||||
reloadOptions () {
|
||||
this.textShadow = this.SGET_options.textShadow
|
||||
this.hideDeadCrossThrough = this.SGET_options.hideDeadCrossThrough
|
||||
this.hideAdvSearchCheatsheetButton = this.SGET_options.hideAdvSearchCheatsheetButton
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the advanced search cheatsheet help button in relationship type fields.
|
||||
*/
|
||||
hideAdvSearchCheatsheetButton = false
|
||||
|
||||
/**
|
||||
* Determines if the "dead" document type should have a cross-text decoration or not
|
||||
*/
|
||||
hideDeadCrossThrough = false
|
||||
|
||||
/**
|
||||
* Determines if text shadow will be shows for accesiblity reasons or not
|
||||
*/
|
||||
textShadow = false
|
||||
|
||||
documentPreviewClose = ""
|
||||
|
||||
/**
|
||||
* Currently being opened document
|
||||
*/
|
||||
exportDocumentsModel = []
|
||||
|
||||
/**
|
||||
* Pre-filtered list based on the category inclussion or exlcussion
|
||||
*/
|
||||
existingObjectsFullList = [] as I_ShortenedDocument[]
|
||||
|
||||
/**
|
||||
* All currently loaded blueprints
|
||||
*/
|
||||
allDocumentBluePrints = [] as I_Blueprint[]
|
||||
|
||||
/**
|
||||
* Filtered list of items
|
||||
*/
|
||||
filteredExistingInput = null as unknown as I_ShortenedDocument[]
|
||||
|
||||
/**
|
||||
* Local list copty for filtering in order to not mess up the original list
|
||||
*/
|
||||
listCopy: I_ShortenedDocument[] = []
|
||||
|
||||
/**
|
||||
* Refocuses the first value in the selct upon filtering for intuitive keyboard control
|
||||
*/
|
||||
async refocusSelect () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
// @ts-ignore
|
||||
this.$refs.ref_exportDocument.setOptionIndex(-1)
|
||||
// @ts-ignore
|
||||
this.$refs.ref_exportDocument.moveOptionSelection(1, true)
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the pre-filtered list
|
||||
*/
|
||||
filterExistingSelect (val: string, update: (e: () => void) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
this.filteredExistingInput = this.existingObjectsFullList.filter((obj) => !obj.isMinor)
|
||||
if (this.$refs.ref_existingDocument && this.filteredExistingInput.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
update(() => {
|
||||
const needle = val.toLowerCase()
|
||||
this.listCopy = extend(true, [], this.existingObjectsFullList)
|
||||
this.filteredExistingInput = advancedDocumentFilter(needle, this.listCopy, this.allDocumentBluePrints, this.existingObjectsFullList)
|
||||
|
||||
if (this.$refs.ref_existingDocument && this.filteredExistingInput.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up up all data in to the dialog on popup load
|
||||
*/
|
||||
populateExportObjectDialog () {
|
||||
this.allDocumentBluePrints = this.SGET_allBlueprints
|
||||
|
||||
this.existingObjectsFullList = this.SGET_allDocuments.docs
|
||||
}
|
||||
|
||||
async removeInput (scope: {
|
||||
index: number
|
||||
removeAtIndex: (index: number) => void
|
||||
}) {
|
||||
scope.removeAtIndex(scope.index)
|
||||
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
// @ts-ignore
|
||||
this.$refs.ref_exportDocument.hidePopup()
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
exportOngoing = false
|
||||
|
||||
exportList:I_ShortenedDocument[] = []
|
||||
|
||||
exportedDocuments = 0
|
||||
|
||||
currentDocName = ""
|
||||
|
||||
get progressCounter () {
|
||||
return (this.exportedDocuments / this.exportList.length)
|
||||
}
|
||||
|
||||
exportDocuments () {
|
||||
remote.dialog.showOpenDialog({
|
||||
properties: ["openDirectory"]
|
||||
}).then(async (result) => {
|
||||
const folderPath = result.filePaths[0]
|
||||
|
||||
if (!folderPath) {
|
||||
return
|
||||
}
|
||||
|
||||
const projectName: string = await retrieveCurrentProjectName()
|
||||
|
||||
const exportPath = `${folderPath}/${projectName} - Export`
|
||||
|
||||
if (!fs.existsSync(exportPath)) {
|
||||
fs.mkdirSync(exportPath)
|
||||
}
|
||||
|
||||
this.exportOngoing = true
|
||||
this.exportedDocuments = 0
|
||||
this.exportList = (this.exportWholeProject) ? this.SGET_allDocuments.docs : this.exportDocumentsModel
|
||||
|
||||
if (!this.includeIsDead) {
|
||||
this.exportList = this.exportList.filter(doc => {
|
||||
return doc.extraFields.find(e => e.id === "deadSwitch")?.value !== true
|
||||
})
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.exportList = this.exportList.map(doc => {
|
||||
return this.SGET_allDocuments.docs.find(subDoc => subDoc._id === doc._id)
|
||||
})
|
||||
|
||||
for (const document of this.exportList) {
|
||||
this.currentDocName = document.label
|
||||
|
||||
// Build the export data object
|
||||
const exportObject = this.buildExportObject(document)
|
||||
|
||||
// MD export
|
||||
if (this.selectedExportFormat === "Markdown - MD") {
|
||||
this.exportFile_MD(exportObject, exportPath)
|
||||
}
|
||||
|
||||
await this.sleep(10)
|
||||
this.exportedDocuments++
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
this.exportOngoing = false
|
||||
this.$q.notify({
|
||||
group: false,
|
||||
type: "positive",
|
||||
message: "Export finished"
|
||||
})
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
buildExportObject (input: I_ShortenedDocument): I_ExportObject {
|
||||
const matchingBlueprint = this.SGET_blueprint(input.type)
|
||||
|
||||
const exportObject = {
|
||||
name: input.extraFields.find(e => e.id === "name")?.value,
|
||||
documentType: matchingBlueprint.nameSingular,
|
||||
documentDirectory: matchingBlueprint.namePlural,
|
||||
isCategory: input.extraFields.find(e => e.id === "categorySwitch")?.value,
|
||||
fieldValues: this.buildFieldValues(input, matchingBlueprint)
|
||||
} as I_ExportObject
|
||||
|
||||
if (!this.hideDeadInformation && this.includeIsDead) {
|
||||
exportObject.isDead = input.extraFields.find(e => e.id === "deadSwitch")?.value
|
||||
}
|
||||
else {
|
||||
exportObject.isDead = false
|
||||
}
|
||||
|
||||
if (this.includeTags) {
|
||||
exportObject.tags = input.extraFields.find(e => e.id === "tags")?.value
|
||||
}
|
||||
if (this.includeHierarchyPath) {
|
||||
// @ts-ignore
|
||||
exportObject.hierarchicalPath = this.getDocumentHieararchicalPath(input, this.SGET_allDocuments.docs)
|
||||
}
|
||||
|
||||
return exportObject
|
||||
}
|
||||
|
||||
buildFieldValues (input: I_ShortenedDocument, blueprint: I_Blueprint) {
|
||||
const catIgnoreList = ["breakDocumentSettings", "name", "documentColor", "documentBackgroundColor", "parentDoc", "order", "categorySwitch", "minorSwitch", "deadSwitch", "finishedSwitch", "tags", "otherNames", "categoryDescription"]
|
||||
|
||||
// Filter and map all fields
|
||||
const mappedFields = blueprint.extraFields
|
||||
.filter(field => field.type !== "tags")
|
||||
.filter(field => field.type !== "switch")
|
||||
.filter(field => field.id !== "name")
|
||||
.filter(field => field.id !== "order")
|
||||
.filter(field => field.id !== "deadSwitch")
|
||||
.filter(field => field.id !== "categorySwitch")
|
||||
.filter(field => field.id !== "parentDoc")
|
||||
.filter(field => field.id !== "documentColor")
|
||||
.filter(field => field.id !== "documentBackgroundColor")
|
||||
.filter(field => field.id !== "breakDocumentSettings")
|
||||
.filter(field => !field.isLegacy)
|
||||
.filter(field => {
|
||||
if (input.extraFields.find(e => e.id === "categorySwitch")?.value) {
|
||||
if (catIgnoreList.includes(field.id)) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
.map(field => {
|
||||
const matchedField = input.extraFields.find(sub => sub.id === field.id)
|
||||
let returnValue = matchedField?.value
|
||||
|
||||
// Convert numbers to strings
|
||||
if (field.type === "number" && typeof returnValue === "number") {
|
||||
returnValue = returnValue.toString()
|
||||
}
|
||||
|
||||
// Build string out of lists
|
||||
if (field.type === "list" && Array.isArray(returnValue)) {
|
||||
if (!field.predefinedListExtras) {
|
||||
returnValue = returnValue.map((e: {value: string}) => `${e.value}`)
|
||||
}
|
||||
else {
|
||||
returnValue = (field.predefinedListExtras?.reverse)
|
||||
? returnValue.map((e: {value: string, affix: string}) => `${e.affix} (${e.value})`)
|
||||
: returnValue.map((e: {value: string, affix: string}) => `${e.value}: ${e.affix}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Build string out of single-relationship
|
||||
if ((
|
||||
field.type === "singleToManyRelationship" ||
|
||||
field.type === "singleToSingleRelationship" ||
|
||||
field.type === "singleToNoneRelationship"
|
||||
) && returnValue && returnValue.value
|
||||
) {
|
||||
const valueToMap = Array.isArray(returnValue.value) ? returnValue.value[0] : returnValue.value
|
||||
|
||||
// @ts-ignore
|
||||
const matchingDocument = this.SGET_allDocuments.docs.find(doc => doc.id === valueToMap._id)
|
||||
|
||||
if (matchingDocument) {
|
||||
// @ts-ignore
|
||||
let localReturnValue = matchingDocument.extraFields.find(e => e.id === "name")?.value as string
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
const matchedNote = returnValue?.addedValues
|
||||
if (matchedNote?.value?.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
localReturnValue = `${localReturnValue} (${matchedNote.value})`
|
||||
}
|
||||
|
||||
returnValue = localReturnValue
|
||||
}
|
||||
else {
|
||||
returnValue = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Build string out of multi-relationship
|
||||
if ((
|
||||
field.type === "manyToManyRelationship" ||
|
||||
field.type === "manyToSingleRelationship" ||
|
||||
field.type === "manyToNoneRelationship"
|
||||
) && returnValue && returnValue.value
|
||||
) {
|
||||
const valuesToMap = returnValue.value as {_id: string, type: string}[]
|
||||
|
||||
const mappedValues = valuesToMap
|
||||
.filter(value => {
|
||||
return value.type === field?.relationshipSettings?.connectedObjectType
|
||||
})
|
||||
.map(value => {
|
||||
// @ts-ignore
|
||||
const matchingDocument = this.SGET_allDocuments.docs.find(doc => doc.id === value._id)
|
||||
if (matchingDocument) {
|
||||
// @ts-ignore
|
||||
let localReturnValue = matchingDocument.extraFields.find(e => e.id === "name")?.value as string
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
const matchedNote = returnValue?.addedValues?.find((e: {pairedId: string}) => e.pairedId === value._id)
|
||||
if (matchedNote?.value?.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
localReturnValue = `${localReturnValue} (${matchedNote.value})`
|
||||
}
|
||||
|
||||
return localReturnValue
|
||||
}
|
||||
return " "
|
||||
})
|
||||
.filter(e => e !== " ")
|
||||
|
||||
console.log(valuesToMap)
|
||||
console.log(mappedValues)
|
||||
returnValue = mappedValues
|
||||
}
|
||||
|
||||
// Fix all missing values that slipped through
|
||||
if (returnValue === undefined) {
|
||||
returnValue = ""
|
||||
}
|
||||
|
||||
const returnValueFormat = returnValue as string
|
||||
|
||||
const name = field.name
|
||||
|
||||
return {
|
||||
label: name,
|
||||
value: returnValueFormat,
|
||||
type: field.type,
|
||||
id: field.id
|
||||
}
|
||||
})
|
||||
.filter(field => field.value.length > 0 || field.type === "break")
|
||||
|
||||
// Map empty breaks
|
||||
const idsToRemove = []
|
||||
for (let index = 0; index < mappedFields.length; index++) {
|
||||
const field = mappedFields[index]
|
||||
|
||||
if (field.type === "break" && mappedFields[index + 1]?.type === "break") {
|
||||
idsToRemove.push(field.id)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty breaks
|
||||
idsToRemove.forEach(id => {
|
||||
const indexToRemove = mappedFields.findIndex(field => field.id === id)
|
||||
|
||||
if (indexToRemove > -1) {
|
||||
mappedFields.splice(indexToRemove, 1)
|
||||
}
|
||||
})
|
||||
|
||||
// Check for last, hanging break field
|
||||
if (mappedFields[mappedFields.length - 1]?.type === "break") {
|
||||
mappedFields.splice(mappedFields.length - 1, 1)
|
||||
}
|
||||
|
||||
return mappedFields
|
||||
}
|
||||
|
||||
exportFile_MD (input: I_ExportObject, exportPath: string) {
|
||||
// Build the proper JSON file for export
|
||||
const JSONExport: any[] = []
|
||||
|
||||
// Name/Title
|
||||
JSONExport.push({ h1: input.name })
|
||||
if (input.isCategory) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
JSONExport[0] = `${JSONExport[0]} - Category`
|
||||
}
|
||||
|
||||
// Document type
|
||||
JSONExport.push({ h2: "Document type" })
|
||||
JSONExport.push({ ul: [input.documentType] })
|
||||
|
||||
// Document type
|
||||
if (!this.hideDeadInformation) {
|
||||
JSONExport.push({ h2: "Status" })
|
||||
JSONExport.push({ ul: [(input.isDead) ? "Dead/Gone/Destroyed" : "Active/Alive"] })
|
||||
}
|
||||
|
||||
// Hierarchy path
|
||||
if (this.includeHierarchyPath) {
|
||||
JSONExport.push({ h2: "Hierarchical path" })
|
||||
JSONExport.push({ ul: [input.hierarchicalPath] })
|
||||
}
|
||||
|
||||
// Tags
|
||||
if (this.includeTags) {
|
||||
JSONExport.push({ h2: "Tags" })
|
||||
JSONExport.push({ ul: (Array.isArray(input.tags) ? input.tags : []) })
|
||||
}
|
||||
|
||||
// Other fields
|
||||
input.fieldValues.forEach(field => {
|
||||
if (field.type === "break") {
|
||||
JSONExport.push({ hr: "" })
|
||||
JSONExport.push({ h1: field.label })
|
||||
}
|
||||
else if (field.type === "wysiwyg") {
|
||||
JSONExport.push({ h2: field.label })
|
||||
JSONExport.push({ p: field.value })
|
||||
}
|
||||
else {
|
||||
JSONExport.push({ h2: field.label })
|
||||
if (Array.isArray(field.value)) {
|
||||
JSONExport.push({ ul: field.value })
|
||||
}
|
||||
else {
|
||||
JSONExport.push({ ul: [field.value] })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
let mdContent: string = json2md(JSONExport)
|
||||
|
||||
const reservedCharacterList = [
|
||||
"/",
|
||||
">",
|
||||
"<",
|
||||
"|",
|
||||
":",
|
||||
"&",
|
||||
"\\",
|
||||
"-",
|
||||
"[",
|
||||
"]",
|
||||
"{",
|
||||
"}",
|
||||
"*",
|
||||
"?",
|
||||
"'",
|
||||
"\"",
|
||||
"#",
|
||||
"%",
|
||||
"$",
|
||||
"!",
|
||||
"@"
|
||||
]
|
||||
|
||||
let exportFileDirectory = input.documentDirectory
|
||||
reservedCharacterList.forEach(char => {
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
exportFileDirectory = exportFileDirectory.replace(char, "-")
|
||||
})
|
||||
const documentDirectory = `${exportPath}/${exportFileDirectory}`
|
||||
|
||||
// Create directory
|
||||
if (!fs.existsSync(documentDirectory)) {
|
||||
fs.mkdirSync(documentDirectory)
|
||||
}
|
||||
|
||||
// Fix invalid characters in document file name
|
||||
let exportFileName = input.name
|
||||
reservedCharacterList.forEach(char => {
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
exportFileName = exportFileName.replace(char, "-")
|
||||
})
|
||||
|
||||
if (input.isCategory) {
|
||||
exportFileName = `_${exportFileName}`
|
||||
}
|
||||
|
||||
// Fix double-empty lines
|
||||
var EOL = mdContent.match(/\r\n/gm) ? "\r\n" : "\n"
|
||||
var regExp = new RegExp("(" + EOL + "){3,}", "gm")
|
||||
mdContent = mdContent.replace(regExp, EOL + EOL)
|
||||
|
||||
// Write the file
|
||||
fs.writeFileSync(`${documentDirectory}/${exportFileName}.md`, mdContent)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.exportDialog {
|
||||
width: 1000px;
|
||||
max-width: calc(100vw - 100px) !important;
|
||||
margin-top: 100px;
|
||||
align-self: flex-start;
|
||||
|
||||
h6 {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -118,7 +118,12 @@ export default class NewProjectCheck extends DialogBase {
|
|||
"*",
|
||||
"?",
|
||||
"'",
|
||||
"\""
|
||||
"\"",
|
||||
"#",
|
||||
"%",
|
||||
"$",
|
||||
"!",
|
||||
"@"
|
||||
]
|
||||
|
||||
get isInvalid () {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
If you are working with project created (or added via Merge) before version 0.1.7, 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!
|
||||
However, before proceeding, please save 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>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Export project"
|
||||
label="Save project"
|
||||
color="primary"
|
||||
@click="commenceSave"
|
||||
/>
|
||||
|
@ -298,12 +298,12 @@ export default class RepairProjectDialog extends DialogBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Export the current project
|
||||
* Save the current project
|
||||
*/
|
||||
async commenceSave () {
|
||||
const projectName = await retrieveCurrentProjectName()
|
||||
const setup = {
|
||||
message: "<h4>Exporting current project...</h4>",
|
||||
message: "<h4>Saving current project...</h4>",
|
||||
spinnerColor: "primary",
|
||||
messageColor: "cultured",
|
||||
spinnerSize: 120,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<span v-html="toolTip"/>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="16px" class="documentLabelExtra" color="amber-14">
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="17px" class="documentLabelExtra" color="amber-14">
|
||||
<q-tooltip :delay="500" v-if="!disableDocumentToolTips">
|
||||
This is a one-way relationship. <br> Editing this value <span class="text-secondary">WILL NOT</span> have any effect on the connected document/s.
|
||||
<br>
|
||||
|
@ -20,7 +20,7 @@
|
|||
Middle-clicking the linked document in non-edit mode will open it in new tab and not focus on it.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="16px" class="documentLabelExtra" color="teal-14">
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="17px" class="documentLabelExtra" color="teal-14">
|
||||
<q-tooltip :delay="500" v-if="!disableDocumentToolTips">
|
||||
This is a two-way relationship. <br> Editing this value <span class="text-secondary">WILL</span> also affect the connected document/s.
|
||||
<br>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<span v-html="toolTip"/>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="16px" class="documentLabelExtra" color="amber-14">
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="17px" class="documentLabelExtra" color="amber-14">
|
||||
<q-tooltip :delay="500" v-if="!disableDocumentToolTips">
|
||||
This is a one-way relationship. <br> Editing this value <span class="text-secondary">WILL NOT</span> have any effect on the connected document/s.
|
||||
<br>
|
||||
|
@ -20,7 +20,7 @@
|
|||
Middle-clicking the linked document in non-edit mode will open it in new tab and not focus on it.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="16px" class="documentLabelExtra" color="teal-14">
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="17px" class="documentLabelExtra" color="teal-14">
|
||||
<q-tooltip :delay="500" v-if="!disableDocumentToolTips">
|
||||
This is a two-way relationship. <br> Editing this value <span class="text-secondary">WILL</span> also affect the connected document/s.
|
||||
<br>
|
||||
|
|
|
@ -11,7 +11,11 @@ export default class FieldBase extends BaseClass {
|
|||
/**
|
||||
* Blueprint data for the specific field
|
||||
*/
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
@Prop({
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
/**
|
||||
* Determines if the document is curently in edit mode or not
|
||||
|
|
|
@ -303,7 +303,8 @@ a {
|
|||
}
|
||||
|
||||
.existingDocumentPopup,
|
||||
.newDocumentPopup {
|
||||
.newDocumentPopup,
|
||||
.exportDialog {
|
||||
.q-checkbox__bg {
|
||||
border-color: #d4d0c9 !important;
|
||||
background: transparent !important;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
### New features
|
||||
|
||||
- **Added export support for Markdown**
|
||||
- **Added on-the-fly relationship documents generation**
|
||||
- **Added stat/attribute support for multiple RPG systems**
|
||||
- **Added option to search through the `Other names` field via `@` modifier**
|
||||
|
@ -41,8 +42,10 @@
|
|||
- Updated the legacy project repair tool to also transfer old stat fields into the new setup
|
||||
- Added an checker tool for removal of legacy fields for the user
|
||||
- Added both keybind and a button for mass-saving of documents with edits
|
||||
- Added export option into the app menu
|
||||
- Added a keybind: "Save active document and mark it as finished"
|
||||
- Added a keybind: "Toggle Developer tools"
|
||||
- Added a keybind: "Export document"
|
||||
|
||||
### QoL adjustments
|
||||
|
||||
|
|
15
src/interfaces/I_ExportObject.ts
Normal file
15
src/interfaces/I_ExportObject.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
export interface I_ExportObject{
|
||||
name: string
|
||||
documentType: string
|
||||
documentDirectory: string
|
||||
isCategory: boolean
|
||||
isDead?: boolean,
|
||||
hierarchicalPath?: string
|
||||
tags?: string[]
|
||||
fieldValues: {
|
||||
label: string,
|
||||
type: string
|
||||
id: string
|
||||
value?: string | string[]
|
||||
}[]
|
||||
}
|
|
@ -15,6 +15,13 @@
|
|||
@trigger-dialog-close="deleteObjectDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Export project dialog -->
|
||||
<exportProjectDialog
|
||||
:dialog-trigger="exportProjectDialogTrigger"
|
||||
:prepicked-ids="[currentData._id]"
|
||||
@trigger-dialog-close="exportProjectDialogClose"
|
||||
/>
|
||||
|
||||
<div class="row justify-start q-col-gutter-x-xl">
|
||||
|
||||
<div
|
||||
|
@ -108,6 +115,46 @@
|
|||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator
|
||||
vertical
|
||||
inset
|
||||
:color="(isDarkMode) ? 'accent' : 'black'"
|
||||
class="q-mr-md"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
:color="(hasEdits) ? 'secondary' : 'primary'"
|
||||
icon="mdi-database-export-outline"
|
||||
@click="exportProjectAssignUID"
|
||||
:outline="isDarkMode"
|
||||
class="q-mr-md"
|
||||
v-if="!currentData.isNew"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Export current project
|
||||
<span class="text-secondary" v-if="hasEdits">
|
||||
<br>
|
||||
<br>
|
||||
Document has active edits.
|
||||
<br>
|
||||
These will not be exported.
|
||||
<br>
|
||||
Please save first.
|
||||
</span>
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator
|
||||
vertical
|
||||
inset
|
||||
:color="(isDarkMode) ? 'accent' : 'black'"
|
||||
class="q-mr-md"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
color="secondary"
|
||||
icon="mdi-text-box-remove-outline"
|
||||
|
@ -126,7 +173,7 @@
|
|||
</div>
|
||||
|
||||
<div class="col-12 q-mt-xl justify-end" v-if="showDocumentID">
|
||||
<q-input style="width: 100%;" readonly outlined label="Document ID" stack-label @click="copyID" ref="idCopy" v-model="currentData._id">
|
||||
<q-input style="width: 375px;" readonly outlined label="Document ID" stack-label @click="copyID" ref="idCopy" v-model="currentData._id">
|
||||
</q-input>
|
||||
</div>
|
||||
|
||||
|
@ -290,6 +337,7 @@ import { copyDocument } from "src/scripts/documentActions/copyDocument"
|
|||
|
||||
import { saveDocument } from "src/scripts/databaseManager/documentManager"
|
||||
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
|
||||
import exportProjectDialog from "src/components/dialogs/ExportProject.vue"
|
||||
|
||||
import Field_Break from "src/components/fields/Field_Break.vue"
|
||||
import Field_Text from "src/components/fields/Field_Text.vue"
|
||||
|
@ -319,6 +367,7 @@ import Field_Tags from "src/components/fields/Field_Tags.vue"
|
|||
Field_Wysiwyg,
|
||||
Field_Tags,
|
||||
|
||||
exportProjectDialog,
|
||||
deleteDocumentCheckDialog
|
||||
}
|
||||
})
|
||||
|
@ -899,6 +948,19 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
this.deleteObjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Export project dialog
|
||||
/****************************************************************/
|
||||
|
||||
exportProjectDialogTrigger: string | false = false
|
||||
exportProjectDialogClose () {
|
||||
this.exportProjectDialogTrigger = false
|
||||
}
|
||||
|
||||
exportProjectAssignUID () {
|
||||
this.exportProjectDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// ADD NEW DOCUMENT UNDER PARENT
|
||||
/****************************************************************/
|
||||
|
|
|
@ -220,6 +220,17 @@ export const defaultKeybinds = [
|
|||
tooltip: "Edit active document"
|
||||
},
|
||||
|
||||
// Export document - NONE
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
which: false,
|
||||
editable: true,
|
||||
id: "exportDocument",
|
||||
tooltip: "Export current document"
|
||||
},
|
||||
|
||||
// Add a new document with current as parent - CTRL + SHIFT + N
|
||||
{
|
||||
altKey: false,
|
||||
|
|
|
@ -2,7 +2,7 @@ import { I_Blueprint } from "../../../interfaces/I_Blueprint"
|
|||
export const cultureBlueprint: I_Blueprint = {
|
||||
_id: "culture",
|
||||
order: 320,
|
||||
namePlural: "Cultures/Art",
|
||||
namePlural: "Cultures/Arts",
|
||||
nameSingular: "Culture/Art",
|
||||
icon: "fas fa-archway",
|
||||
category: "World",
|
||||
|
|
|
@ -282,7 +282,7 @@ export const locationsBlueprint: I_Blueprint = {
|
|||
name: "Common Occupations/Classes",
|
||||
type: "manyToManyRelationship",
|
||||
icon: "fab fa-pied-piper-hat",
|
||||
sizing: 4,
|
||||
sizing: 6,
|
||||
relationshipSettings: {
|
||||
connectedObjectType: "professions",
|
||||
connectedField: "connectedLocations"
|
||||
|
@ -293,18 +293,29 @@ export const locationsBlueprint: I_Blueprint = {
|
|||
name: "Local Resources/Materials",
|
||||
type: "manyToManyRelationship",
|
||||
icon: "mdi-gold",
|
||||
sizing: 4,
|
||||
sizing: 6,
|
||||
relationshipSettings: {
|
||||
connectedObjectType: "resources",
|
||||
connectedField: "connectedLocations"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "neighbourLocations",
|
||||
name: "Neighbouring Locations",
|
||||
type: "manyToManyRelationship",
|
||||
icon: "mdi-map-marker-radius",
|
||||
sizing: 6,
|
||||
relationshipSettings: {
|
||||
connectedObjectType: "locations",
|
||||
connectedField: "neighbourLocations"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "connectedLocations",
|
||||
name: "Other connected Locations",
|
||||
type: "manyToManyRelationship",
|
||||
icon: "mdi-map-marker-radius",
|
||||
sizing: 4,
|
||||
sizing: 6,
|
||||
relationshipSettings: {
|
||||
connectedObjectType: "locations",
|
||||
connectedField: "connectedLocations"
|
||||
|
|
|
@ -3,7 +3,7 @@ export const loreNotesBlueprint: I_Blueprint = {
|
|||
_id: "loreNotes",
|
||||
order: 440,
|
||||
namePlural: "Lore notes/Other notes",
|
||||
nameSingular: "Lore notes/Other note",
|
||||
nameSingular: "Lore note/Other note",
|
||||
icon: "mdi-script-text-outline",
|
||||
category: "Story/Lore",
|
||||
extraFields: [
|
||||
|
|
|
@ -4,7 +4,7 @@ export const racesBlueprint: I_Blueprint = {
|
|||
_id: "races",
|
||||
order: 340,
|
||||
namePlural: "Species/Races/Flora/Fauna",
|
||||
nameSingular: "Species/Races/Flora/Fauna",
|
||||
nameSingular: "Species/Race/Flora/Fauna",
|
||||
icon: "fas fa-dragon",
|
||||
category: "World",
|
||||
extraFields: [
|
||||
|
|
|
@ -106,6 +106,7 @@ export const advancedDocumentFilter = (inputString: string, currentDocumentList:
|
|||
.filter(field => field.type !== "switch")
|
||||
.filter(field => field.id !== "name")
|
||||
.filter(field => field.id !== "parentDoc")
|
||||
.filter(field => !field.isLegacy)
|
||||
.map(field => {
|
||||
const matchedField = doc.extraFields.find(sub => sub.id === field.id)
|
||||
let returnValue = matchedField?.value
|
||||
|
|
Loading…
Reference in a new issue