mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-06-27 02:20:32 +12:00
1.3.0 release candidate (lacking text manual for advanced search and updated changelog)
This commit is contained in:
parent
a6aa75532d
commit
0635be823a
13
changelog.md
13
changelog.md
|
@ -3,19 +3,22 @@
|
|||
## 0.1.3
|
||||
|
||||
TODO
|
||||
move doc buttons to the top bar
|
||||
add delete document dialog to dialog system
|
||||
ADD TOOLTIPS TO SEACH!!!!
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Fixed the "Name" field disappearing upon full deletion of text
|
||||
- Fixed a bug with single/multi select fields working unintuitively for adding new values (eg: Character personality traits field or Sex field)
|
||||
- Added an auto-remover of no longer existing relationships filled in within single and mutli-fields
|
||||
|
||||
### New features
|
||||
|
||||
- Added a safeguard dialog for new project creation in case an opened project exists
|
||||
- Added a safeguard dialog for project importing in case an opened project exists
|
||||
- New control bar added for documents and project control
|
||||
- Added automatic redirecting to the project screen upon importing an existing project or creating a new one (better transition effect will be added later)
|
||||
- Added a "Advanced search guide" dialog with manual on how to use the advanced search
|
||||
- Added "About Fantasia Archive" dialog showing current app version (more details will be added in the future)
|
||||
- New control bar added for documents and project control along with more intelligent button redesign
|
||||
- A new logo added to the app (better visibility of the logo in small scales and icons)
|
||||
- Massive overhaul of the search engine used by the Quick opening existing document and single/multi relationship fields (now supports tags, categories, document types, inteligent filtering and inteligent sorting via importance of the found values)
|
||||
- Added color support to single/multi relationship fields
|
||||
|
@ -28,8 +31,10 @@ add delete document dialog to dialog system
|
|||
|
||||
- Lightly modified the app color-scheme to offer better readability of contrast
|
||||
- Changed icon for the button triggering quick-adding of new documents
|
||||
- Changed the looks of tooltips to go well with the current app looks
|
||||
- Changed the looks of tooltips, relationship fields and selects to go well with the current app looks
|
||||
- Adjusted tab-list width to allow for more content to show
|
||||
- Added a tooptip showing how many of the object in the hierarchical tree are documents and how many are categoriesE
|
||||
- Hierarchical tree search bar is now attached on the top of the tree and no longer scrolls along with the rest of the content of the tree in order to allow better useability. The search now also expands to full app width on focus via user's interaction. The search icon was moved to right and the field reset icon as moved to the left.
|
||||
- Modified selected and active indicators for already selected/active items in dropdown lists in order to not clash with the highlighting from the filter results
|
||||
- Slightly modified the scrollbar visuals to be less intrusive
|
||||
- Added a light golden tint to the background of the app to go easy on user's eyes before dark mode is added
|
||||
|
|
|
@ -307,4 +307,8 @@ export default class BaseClass extends Vue {
|
|||
sleep (ms:number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
stripTags (input: string) {
|
||||
return (input) ? input.replace(/<[^>]+>/g, "") : input
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
@trigger-dialog-close="deleteObjectDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Advanced search guide dialog -->
|
||||
<advancedSearchGuideDialog
|
||||
:dialog-trigger="advancedSearchGuideDialogTrigger"
|
||||
@trigger-dialog-close="advancedSearchGuideDialogClose"
|
||||
/>
|
||||
|
||||
<!-- Keybind dialog -->
|
||||
<keybindCheatsheetDialog
|
||||
:dialog-trigger="keybindsDialogTrigger"
|
||||
@trigger-dialog-close="keybindsDialogClose"
|
||||
/>
|
||||
|
||||
<q-page-sticky position="top-right" class="documentControl">
|
||||
|
||||
<div class="documentControl__blocker"></div>
|
||||
|
@ -28,6 +40,38 @@
|
|||
|
||||
<div class="documentControl__left">
|
||||
|
||||
<q-btn
|
||||
icon="mdi-keyboard-settings"
|
||||
color="primary"
|
||||
outline
|
||||
@click="keybindsDialogAssignUID"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Open keybinds cheatsheet
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-btn
|
||||
icon="mdi-file-question"
|
||||
color="primary"
|
||||
outline
|
||||
@click="advancedSearchGuideAssignUID"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Open advanced search guide
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator vertical inset color="accent" />
|
||||
|
||||
<q-btn
|
||||
icon="mdi-package-variant-closed"
|
||||
color="primary"
|
||||
|
@ -35,7 +79,11 @@
|
|||
:disable="!projectExists"
|
||||
@click="commenceExport"
|
||||
>
|
||||
<q-tooltip>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Export current project
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
@ -48,7 +96,11 @@
|
|||
outline
|
||||
@click="existingObjectAssignUID"
|
||||
>
|
||||
<q-tooltip>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Quick-search an existing document
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
@ -59,7 +111,11 @@
|
|||
outline
|
||||
@click="newObjectAssignUID"
|
||||
>
|
||||
<q-tooltip>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Quick-add a new document
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
@ -67,14 +123,73 @@
|
|||
</div>
|
||||
|
||||
<div class="documentControl__right">
|
||||
|
||||
<q-btn
|
||||
icon="mdi-file-document-edit"
|
||||
color="primary"
|
||||
outline
|
||||
@click="toggleEditMode"
|
||||
v-if="currentyEditable && SGET_allOpenedDocuments.docs.length > 0"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom middle"
|
||||
self="top middle"
|
||||
>
|
||||
Edit current document
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-btn
|
||||
icon="mdi-content-save"
|
||||
color="primary"
|
||||
outline
|
||||
@click="saveCurrentDocument"
|
||||
v-if="!currentyEditable && SGET_allOpenedDocuments.docs.length > 0"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom left"
|
||||
self="top middle"
|
||||
>
|
||||
Save current document
|
||||
</q-tooltip>
|
||||
|
||||
</q-btn>
|
||||
|
||||
<q-btn
|
||||
icon="mdi-file-tree"
|
||||
color="primary"
|
||||
outline
|
||||
@click="addNewUnderParent"
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
|
||||
>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
max-width="500px"
|
||||
anchor="bottom left"
|
||||
self="top middle"
|
||||
>
|
||||
Add new document with the current one as parent
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-separator vertical inset color="accent"
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
icon="mdi-text-box-remove-outline"
|
||||
color="secondary"
|
||||
outline
|
||||
@click="deleteObjectAssignUID"
|
||||
:disable="SGET_allOpenedDocuments.docs.length < 1"
|
||||
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
|
||||
>
|
||||
<q-tooltip>
|
||||
<q-tooltip
|
||||
:delay="500"
|
||||
anchor="bottom left"
|
||||
self="top middle"
|
||||
>
|
||||
Delete current document
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
@ -95,6 +210,12 @@ import BaseClass from "src/BaseClass"
|
|||
import newDocumentDialog from "src/components/dialogs/NewDocument.vue"
|
||||
import existingDocumentDialog from "src/components/dialogs/ExistingDocument.vue"
|
||||
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
|
||||
import advancedSearchGuideDialog from "src/components/dialogs/AdvancedSearchGuide.vue"
|
||||
import keybindCheatsheetDialog from "src/components/dialogs/KeybindCheatsheet.vue"
|
||||
|
||||
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { extend } from "quasar"
|
||||
import { saveDocument } from "src/scripts/databaseManager/documentManager"
|
||||
|
||||
import { retrieveCurrentProjectName, exportProject } from "src/scripts/projectManagement/projectManagent"
|
||||
|
||||
|
@ -102,7 +223,9 @@ import { retrieveCurrentProjectName, exportProject } from "src/scripts/projectMa
|
|||
components: {
|
||||
newDocumentDialog,
|
||||
existingDocumentDialog,
|
||||
deleteDocumentCheckDialog
|
||||
deleteDocumentCheckDialog,
|
||||
advancedSearchGuideDialog,
|
||||
keybindCheatsheetDialog
|
||||
}
|
||||
})
|
||||
export default class DocumentControl extends BaseClass {
|
||||
|
@ -137,6 +260,42 @@ export default class DocumentControl extends BaseClass {
|
|||
if (this.determineKeyBind("deleteDocument")) {
|
||||
this.deleteObjectAssignUID()
|
||||
}
|
||||
|
||||
// Edit document - CTRL + E
|
||||
if (this.determineKeyBind("editDocument") && this.currentyEditable) {
|
||||
this.toggleEditMode()
|
||||
}
|
||||
|
||||
// Save document
|
||||
if (this.determineKeyBind("saveDocument") && !this.currentyEditable) {
|
||||
this.saveCurrentDocument().catch(e => console.log(e))
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Advanced search guide dialog
|
||||
/****************************************************************/
|
||||
|
||||
advancedSearchGuideDialogTrigger: string | false = false
|
||||
advancedSearchGuideDialogClose () {
|
||||
this.advancedSearchGuideDialogTrigger = false
|
||||
}
|
||||
|
||||
advancedSearchGuideAssignUID () {
|
||||
this.advancedSearchGuideDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Keybings cheatsheet dialog
|
||||
/****************************************************************/
|
||||
|
||||
keybindsDialogTrigger: string | false = false
|
||||
keybindsDialogClose () {
|
||||
this.keybindsDialogTrigger = false
|
||||
}
|
||||
|
||||
keybindsDialogAssignUID () {
|
||||
this.keybindsDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
|
@ -189,6 +348,98 @@ export default class DocumentControl extends BaseClass {
|
|||
const projectName = await retrieveCurrentProjectName()
|
||||
this.exportProject(projectName)
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Add new document under parent
|
||||
/****************************************************************/
|
||||
addNewUnderParent () {
|
||||
const currentDoc = this.findRequestedOrActiveDocument()
|
||||
if (currentDoc) {
|
||||
const routeObject = {
|
||||
_id: currentDoc.type,
|
||||
parent: currentDoc._id
|
||||
}
|
||||
// @ts-ignore
|
||||
this.addNewObjectRoute(routeObject)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Toggle edit mode & Save document
|
||||
/****************************************************************/
|
||||
toggleEditMode () {
|
||||
const currentDoc = this.findRequestedOrActiveDocument()
|
||||
if (currentDoc && !currentDoc.editMode) {
|
||||
const dataCopy: I_OpenedDocument = extend(true, {}, currentDoc)
|
||||
dataCopy.editMode = true
|
||||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
}
|
||||
|
||||
async saveCurrentDocument () {
|
||||
const currentDoc = this.findRequestedOrActiveDocument()
|
||||
|
||||
const allDocuments = this.SGET_allOpenedDocuments
|
||||
|
||||
const docCopy: I_OpenedDocument[] = extend(true, [], allDocuments.docs)
|
||||
|
||||
if (currentDoc) {
|
||||
// @ts-ignore
|
||||
const savedDocument: {
|
||||
documentCopy: I_OpenedDocument,
|
||||
allOpenedDocuments: I_OpenedDocument[]
|
||||
} = await saveDocument(currentDoc, docCopy)
|
||||
|
||||
// Update the opened document
|
||||
const dataPass = { doc: savedDocument.documentCopy, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
|
||||
// Update all others
|
||||
for (const doc of savedDocument.allOpenedDocuments) {
|
||||
// Update the opened document
|
||||
const dataPass = { doc: doc, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Watch("$route", { immediate: true, deep: true })
|
||||
onUrlChange () {
|
||||
this.checkEditability()
|
||||
this.checkNew()
|
||||
}
|
||||
|
||||
@Watch("SGET_allOpenedDocuments", { deep: true })
|
||||
onDocChange () {
|
||||
this.checkEditability()
|
||||
this.checkNew()
|
||||
}
|
||||
|
||||
checkEditability () {
|
||||
const currentDocument = this.findRequestedOrActiveDocument()
|
||||
|
||||
if (currentDocument && !currentDocument.editMode) {
|
||||
this.currentyEditable = true
|
||||
}
|
||||
else {
|
||||
this.currentyEditable = false
|
||||
}
|
||||
}
|
||||
|
||||
checkNew () {
|
||||
const currentDocument = this.findRequestedOrActiveDocument()
|
||||
|
||||
if (currentDocument && currentDocument.isNew) {
|
||||
this.currentlyNew = true
|
||||
}
|
||||
else {
|
||||
this.currentlyNew = false
|
||||
}
|
||||
}
|
||||
|
||||
currentyEditable = false
|
||||
currentlyNew = false
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -211,7 +462,7 @@ export default class DocumentControl extends BaseClass {
|
|||
|
||||
&__wrapper {
|
||||
width: calc(100vw - 375px);
|
||||
padding: 10px 15px;
|
||||
padding: 8.5px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
<template>
|
||||
|
||||
<span>
|
||||
<q-page-sticky position="top-left" class="treeSearchWrapper">
|
||||
|
||||
<q-input ref="treeFilter" dark filled v-model="treeFilter" label="Filter document tree...">
|
||||
<template v-slot:prepend>
|
||||
<template v-slot:append>
|
||||
<q-icon name="mdi-text-search" />
|
||||
</template>
|
||||
<template v-slot:append>
|
||||
<q-icon v-if="treeFilter !== ''" name="clear" class="cursor-pointer" @click="resetTreeFilter" />
|
||||
<template v-slot:prepend>
|
||||
<q-icon v-if="treeFilter !== ''" name="clear" class="cursor-pointer text-secondary" @click="resetTreeFilter" />
|
||||
</template>
|
||||
</q-input>
|
||||
</q-page-sticky>
|
||||
|
||||
<q-tree
|
||||
class="objectTree q-pa-sm"
|
||||
|
@ -36,7 +39,14 @@
|
|||
<span
|
||||
class="text-primary text-weight-medium q-ml-xs"
|
||||
v-if="prop.node.isRoot">
|
||||
({{prop.node.documentCount}})
|
||||
({{prop.node.allCount}})
|
||||
<q-tooltip
|
||||
:delay="1000"
|
||||
>
|
||||
Document count: <span class="text-bold text-gunmetal-bright">{{prop.node.documentCount}}</span>
|
||||
<br>
|
||||
Category count: <span class="text-bold text-gunmetal-bright">{{prop.node.categoryCount}}</span>
|
||||
</q-tooltip>
|
||||
</span>
|
||||
<q-badge
|
||||
class="treeBadge"
|
||||
|
@ -63,7 +73,7 @@
|
|||
color="dark"
|
||||
class="z-1 q-ml-sm treeButton treeButton--edit"
|
||||
icon="mdi-pencil"
|
||||
size="8px"
|
||||
size="10px"
|
||||
@click.stop.prevent="openExistingDocumentRoute(prop.node)"
|
||||
>
|
||||
<q-tooltip
|
||||
|
@ -81,7 +91,7 @@
|
|||
color="dark"
|
||||
class="z-1 q-ml-sm treeButton treeButton--add"
|
||||
icon="mdi-plus"
|
||||
size="8px"
|
||||
size="10px"
|
||||
@click.stop.prevent="processNodeNewDocumentButton(prop.node)"
|
||||
>
|
||||
<q-tooltip
|
||||
|
@ -380,6 +390,7 @@ export default class ObjectTree extends BaseClass {
|
|||
return {
|
||||
label: doc.extraFields.find(e => e.id === "name")?.value,
|
||||
icon: (isCategory) ? "fas fa-folder-open" : doc.icon,
|
||||
isCategory: !!(isCategory),
|
||||
sticker: doc.extraFields.find(e => e.id === "order")?.value,
|
||||
parentDoc: (parentDocID) ? parentDocID._id : false,
|
||||
handler: this.openExistingDocumentRoute,
|
||||
|
@ -396,7 +407,10 @@ export default class ObjectTree extends BaseClass {
|
|||
} as I_ShortenedDocument
|
||||
})
|
||||
|
||||
const documentCount = allDocumentsRows.length
|
||||
const documentCount = allDocumentsRows.filter(e => !e.isCategory).length
|
||||
const categoryCount = allDocumentsRows.filter(e => e.isCategory).length
|
||||
const allCount = allDocumentsRows.length
|
||||
|
||||
const listCopy: I_ShortenedDocument[] = extend(true, [], allDocumentsRows)
|
||||
allTreeDocuments = [...allTreeDocuments, ...listCopy]
|
||||
|
||||
|
@ -411,7 +425,9 @@ export default class ObjectTree extends BaseClass {
|
|||
handler: this.addNewObjectRoute,
|
||||
specialLabel: blueprint.nameSingular.toLowerCase(),
|
||||
isRoot: true,
|
||||
allCount: allCount,
|
||||
documentCount: documentCount,
|
||||
categoryCount: categoryCount,
|
||||
children: [
|
||||
...hierarchicalTreeContent,
|
||||
{
|
||||
|
@ -459,12 +475,18 @@ export default class ObjectTree extends BaseClass {
|
|||
})
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
|
||||
const documentCount = tagDocs.filter(e => !e.isCategory).length
|
||||
const categoryCount = tagDocs.filter(e => e.isCategory).length
|
||||
const allCount = tagDocs.length
|
||||
|
||||
const tagObject = {
|
||||
label: `${tag}`,
|
||||
icon: "mdi-tag",
|
||||
_id: `tag-${tag}`,
|
||||
key: `tag-${tag}`,
|
||||
documentCount: tagDocs.length,
|
||||
allCount: allCount,
|
||||
documentCount: documentCount,
|
||||
categoryCount: categoryCount,
|
||||
isRoot: true,
|
||||
isTag: true,
|
||||
children: tagDocs
|
||||
|
@ -632,12 +654,19 @@ export default class ObjectTree extends BaseClass {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.objectTree {
|
||||
padding-top: 60px;
|
||||
|
||||
.q-tree__arrow {
|
||||
margin-right: 0;
|
||||
padding: 4px 4px 4px 0;
|
||||
}
|
||||
|
||||
.q-tree__node {
|
||||
padding: 0 0 0 22px;
|
||||
}
|
||||
|
||||
.q-tree__node-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -675,6 +704,27 @@ export default class ObjectTree extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
.treeSearchWrapper {
|
||||
top: -40px;
|
||||
left: -375px;
|
||||
width: 375px;
|
||||
z-index: 555;
|
||||
background-color: $dark;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
background-color: $dark;
|
||||
|
||||
&.q-field--focused {
|
||||
width: 100vw;
|
||||
max-width: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.treeButton {
|
||||
&--add {
|
||||
.q-icon {
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
@trigger-dialog-close="newProjectDialogClose"
|
||||
/>
|
||||
|
||||
<!-- About app dialog -->
|
||||
<aboutAppDialog
|
||||
:dialog-trigger="aboutAppDialogTrigger"
|
||||
@trigger-dialog-close="aboutAppDialogClose"
|
||||
/>
|
||||
|
||||
<q-btn-group
|
||||
flat
|
||||
class="AppControl__buttons"
|
||||
|
@ -156,6 +162,17 @@
|
|||
<q-item-section>Show keybind cheatsheet</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item
|
||||
@click="aboutAppDialogAssignUID"
|
||||
v-close-popup
|
||||
clickable
|
||||
active
|
||||
active-class="bg-gunmetal-light text-cultured"
|
||||
class="noHigh"
|
||||
>
|
||||
<q-item-section>About Fantasia Archive</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-separator dark />
|
||||
|
||||
<q-item
|
||||
|
@ -188,6 +205,7 @@ import projectCloseCheckDialog from "src/components/dialogs/ProjectCloseCheck.vu
|
|||
import keybindCheatsheetDialog from "src/components/dialogs/KeybindCheatsheet.vue"
|
||||
import importProjectCheckDialog from "src/components/dialogs/ImportProjectCheck.vue"
|
||||
import newProjectCheckDialog from "src/components/dialogs/NewProjectCheck.vue"
|
||||
import aboutAppDialog from "src/components/dialogs/AboutApp.vue"
|
||||
|
||||
import { retrieveCurrentProjectName, exportProject } from "src/scripts/projectManagement/projectManagent"
|
||||
|
||||
|
@ -197,7 +215,8 @@ import { toggleDevTools } from "src/scripts/utilities/devTools"
|
|||
projectCloseCheckDialog,
|
||||
keybindCheatsheetDialog,
|
||||
importProjectCheckDialog,
|
||||
newProjectCheckDialog
|
||||
newProjectCheckDialog,
|
||||
aboutAppDialog
|
||||
}
|
||||
})
|
||||
export default class AppControl extends BaseClass {
|
||||
|
@ -280,6 +299,19 @@ export default class AppControl extends BaseClass {
|
|||
keybindsDialogAssignUID () {
|
||||
this.keybindsDialogTrigger = this.generateUID()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// About app dialog
|
||||
/****************************************************************/
|
||||
|
||||
aboutAppDialogTrigger: string | false = false
|
||||
aboutAppDialogClose () {
|
||||
this.aboutAppDialogTrigger = false
|
||||
}
|
||||
|
||||
aboutAppDialogAssignUID () {
|
||||
this.aboutAppDialogTrigger = this.generateUID()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
class="z-max q-ml-auto"
|
||||
:class="{'q-mr-sm': document.hasEdits}"
|
||||
size="xs"
|
||||
|
|
62
src/components/dialogs/AboutApp.vue
Normal file
62
src/components/dialogs/AboutApp.vue
Normal file
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
|
||||
<q-dialog
|
||||
v-model="dialogModel"
|
||||
@hide="triggerDialogClose"
|
||||
>
|
||||
<q-card
|
||||
class="aboutDialog"
|
||||
dark
|
||||
>
|
||||
<q-card-section>
|
||||
<h6 class="text-center q-my-sm">About Fantasia Archive</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<div>
|
||||
Currently running Fantasia Archive version: <span class="text-bold text-primary">{{appVersion}}</span>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="around" class="q-mb-lg q-mt-md">
|
||||
<q-btn flat label="Close" color="accent" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
|
||||
import DialogBase from "src/components/dialogs/_DialogBase"
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class AboutApp extends DialogBase {
|
||||
@Watch("dialogTrigger")
|
||||
openDialog (val: string|false) {
|
||||
if (val) {
|
||||
if (this.SGET_getDialogsState) {
|
||||
return
|
||||
}
|
||||
this.SSET_setDialogState(true)
|
||||
this.dialogModel = true
|
||||
}
|
||||
}
|
||||
|
||||
appVersion = process.env.npm_package_version
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.aboutDialog {
|
||||
text-align: center;
|
||||
width: 500px;
|
||||
|
||||
h6 {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
60
src/components/dialogs/AdvancedSearchGuide.vue
Normal file
60
src/components/dialogs/AdvancedSearchGuide.vue
Normal file
|
@ -0,0 +1,60 @@
|
|||
<template>
|
||||
|
||||
<q-dialog
|
||||
v-model="dialogModel"
|
||||
@hide="triggerDialogClose"
|
||||
>
|
||||
<q-card
|
||||
class="aboutDialog"
|
||||
dark
|
||||
>
|
||||
<q-card-section>
|
||||
<h6 class="text-center q-my-sm">How to use advanced search</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<div>
|
||||
{{$t('tooltips.advancedSearch')}}
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="around" class="q-mb-lg q-mt-md">
|
||||
<q-btn flat label="Close" color="accent" v-close-popup />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
|
||||
import DialogBase from "src/components/dialogs/_DialogBase"
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class AdvancedSearchGuide extends DialogBase {
|
||||
@Watch("dialogTrigger")
|
||||
openDialog (val: string|false) {
|
||||
if (val) {
|
||||
if (this.SGET_getDialogsState) {
|
||||
return
|
||||
}
|
||||
this.SSET_setDialogState(true)
|
||||
this.dialogModel = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.aboutDialog {
|
||||
text-align: center;
|
||||
width: 500px;
|
||||
|
||||
h6 {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -74,7 +74,7 @@
|
|||
<q-tooltip
|
||||
:delay="300"
|
||||
>
|
||||
Add a new document belonging under {{ opt.label }}
|
||||
Add a new document belonging under {{ stripTags(opt.label) }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-item>
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
</q-icon>
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
This is a one-way relationship. <br> Editing this value <b>will not</b> have effect on the connected document/s.
|
||||
This is a one-way relationship. <br> Editing this value <span class="text-gunmetal-bright">will not</span> have effect on the connected document/s.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
This is a two-way relationship. <br> Editing this value <b>will</b> also effect the connected document/s.
|
||||
This is a two-way relationship. <br> Editing this value <span class="text-gunmetal-bright">will</span> also effect the connected document/s.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
class="text-primary"
|
||||
@click="openExistingDocumentRoute(single)">
|
||||
<q-item-section>
|
||||
{{single.label}}
|
||||
{{stripTags(single.label)}}
|
||||
<span class="inline-block q-ml-xs text-italic connectionNote">
|
||||
{{retrieveNoteText(single._id)}}
|
||||
</span>
|
||||
|
@ -57,8 +57,21 @@
|
|||
input-debounce="0"
|
||||
v-model="localInput"
|
||||
@filter="filterSelect"
|
||||
@input="signalInput"
|
||||
@input="signalInput(false)"
|
||||
>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
removable
|
||||
dense
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt.label) }}
|
||||
</q-chip>
|
||||
</template>
|
||||
<template v-slot:option="{ itemProps, itemEvents, opt }">
|
||||
<q-item
|
||||
v-bind="itemProps"
|
||||
|
@ -100,14 +113,14 @@
|
|||
:key="index"
|
||||
>
|
||||
<td>
|
||||
{{localInput[index].label}}
|
||||
{{stripTags(localInput[index].label)}}
|
||||
</td>
|
||||
<td>
|
||||
<q-input
|
||||
label="Note"
|
||||
v-model="singleNote.value"
|
||||
dense
|
||||
@keyup="signalInput"
|
||||
@keyup="signalInput(false)"
|
||||
outlined
|
||||
>
|
||||
</q-input>
|
||||
|
@ -154,7 +167,6 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput = [] as unknown as I_FieldRelationship[]
|
||||
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
|
@ -281,11 +293,14 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
|
||||
this.localInput = (Array.isArray(this.localInput)) ? this.localInput : []
|
||||
|
||||
let nonExistValue = false
|
||||
|
||||
this.localInput.forEach((s, index) => {
|
||||
if (s._id) {
|
||||
if (!allObjectsWithoutCurrent.find(e => e._id === s._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput.splice(index, 1)
|
||||
nonExistValue = true
|
||||
}
|
||||
else {
|
||||
const matchedFieldContent = allObjectsWithoutCurrent.find(e => e._id === s._id)
|
||||
|
@ -297,6 +312,10 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
}
|
||||
})
|
||||
|
||||
if (nonExistValue) {
|
||||
this.signalInput(true)
|
||||
}
|
||||
|
||||
const allObjectsWithoutCategories: I_FieldRelationship[] = allObjectsWithoutCurrent.filter((obj) => !obj.isCategory)
|
||||
|
||||
this.extraInput = allObjectsWithoutCategories
|
||||
|
@ -312,16 +331,13 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
|
||||
signalInput (skipSave?: boolean) {
|
||||
this.checkNotes()
|
||||
|
||||
this.inputNotes = this.inputNotes.filter(single => this.localInput.find(e => single.pairedId === e._id))
|
||||
|
||||
return {
|
||||
value: this.localInput,
|
||||
addedValues: this.inputNotes
|
||||
addedValues: this.inputNotes,
|
||||
skipSave: (skipSave)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,20 @@
|
|||
@input="signalInput"
|
||||
@keydown="signalInput"
|
||||
>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
removable
|
||||
dense
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt) }}
|
||||
</q-chip>
|
||||
</template>
|
||||
|
||||
</q-select>
|
||||
|
||||
<div class="separatorWrapper">
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
</q-icon>
|
||||
<q-icon v-if="isOneWayRelationship" name="mdi-arrow-right-bold" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
This is a one-way relationship. <br> Editing this value <b>will not</b> have effect on the connected document/s.
|
||||
This is a one-way relationship. <br> Editing this value <span class="text-gunmetal-bright">will not</span> have effect on the connected document/s.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
<q-icon v-if="!isOneWayRelationship" name="mdi-arrow-left-right-bold" size="16px" class="q-ml-md">
|
||||
<q-tooltip :delay="500">
|
||||
This is a two-way relationship. <br> Editing this value <b>will</b> also effect the connected document/s.
|
||||
This is a two-way relationship. <br> Editing this value <span class="text-gunmetal-bright">will</span> also effect the connected document/s.
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
|
@ -29,7 +29,7 @@
|
|||
class="text-primary"
|
||||
@click="openExistingDocumentRoute(localInput)">
|
||||
<q-item-section>
|
||||
{{localInput.label}}
|
||||
{{stripTags(localInput.label)}}
|
||||
<span class="inline-block q-ml-xs text-italic connectionNote">
|
||||
{{retrieveNoteText()}}
|
||||
</span>
|
||||
|
@ -45,15 +45,30 @@
|
|||
dark
|
||||
style="flex-grow: 1;"
|
||||
dense
|
||||
:ref="`singleRelationshipField${this.inputDataBluePrint.id}`"
|
||||
:ref="`singleRelationshipField${inputDataBluePrint.id}`"
|
||||
:options="filteredInput"
|
||||
use-input
|
||||
outlined
|
||||
input-debounce="0"
|
||||
v-model="localInput"
|
||||
@filter="filterSelect"
|
||||
@input="signalInput"
|
||||
@input="signalInput(false)"
|
||||
>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
v-if="scope.opt.label && scope.opt.label.length > 0"
|
||||
removable
|
||||
dense
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt.label) }}
|
||||
</q-chip>
|
||||
</template>
|
||||
|
||||
<template v-slot:option="{ itemProps, itemEvents, opt }">
|
||||
<q-item
|
||||
v-bind="itemProps"
|
||||
|
@ -92,14 +107,14 @@
|
|||
<table class="q-mt-sm" v-if="localInput && inputFieldID !== 'parentDoc'">
|
||||
<tr>
|
||||
<td>
|
||||
{{localInput.label}}
|
||||
{{stripTags(localInput.label)}}
|
||||
</td>
|
||||
<td>
|
||||
<q-input
|
||||
label="Note"
|
||||
v-model="inputNote.value"
|
||||
dense
|
||||
@keyup="signalInput"
|
||||
@keyup="signalInput(false)"
|
||||
outlined
|
||||
>
|
||||
</q-input>
|
||||
|
@ -144,7 +159,6 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput = "" as unknown as I_FieldRelationship
|
||||
|
||||
inputNote: { pairedId: string; value: string; } = {
|
||||
|
@ -282,6 +296,7 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
if (!objectsWithoutCurrent.find(e => e._id === this.localInput._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput = ""
|
||||
this.signalInput(true)
|
||||
}
|
||||
else {
|
||||
const matchedFieldContent = objectsWithoutCurrent.find(e => e._id === this.localInput._id)
|
||||
|
@ -295,13 +310,15 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
debounceTimerCheck = false
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
signalInput (skipSave?: boolean) {
|
||||
this.inputNote = (this.localInput !== null) ? this.inputNote : { pairedId: "", value: "" }
|
||||
return {
|
||||
value: this.localInput,
|
||||
addedValues: this.inputNote
|
||||
addedValues: this.inputNote,
|
||||
skipSave: (skipSave)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,21 @@
|
|||
@input="signalInput"
|
||||
@keydown="signalInput"
|
||||
>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
v-if="scope.opt && scope.opt.length > 0"
|
||||
removable
|
||||
dense
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ scope.opt }}
|
||||
</q-chip>
|
||||
</template>
|
||||
|
||||
</q-select>
|
||||
|
||||
<div class="separatorWrapper">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
>
|
||||
<q-chip
|
||||
v-for="(input,index) in localInput" :key="index"
|
||||
color="primary" text-color="white" class="text-bold">
|
||||
color="accent" text-color="dark" class="text-bold">
|
||||
{{input}}
|
||||
</q-chip>
|
||||
</div>
|
||||
|
@ -41,6 +41,19 @@
|
|||
@input="signalInput"
|
||||
@keydown="signalInput"
|
||||
>
|
||||
<template v-slot:selected-item="scope">
|
||||
<q-chip
|
||||
removable
|
||||
dense
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
text-color="dark"
|
||||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt) }}
|
||||
</q-chip>
|
||||
</template>
|
||||
</q-select>
|
||||
|
||||
<div class="separatorWrapper">
|
||||
|
|
|
@ -75,11 +75,36 @@ body {
|
|||
}
|
||||
|
||||
.q-field__input,
|
||||
.q-icon,
|
||||
.q-field__native span {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.tagSelect,
|
||||
.singleSelect,
|
||||
.multiSelect,
|
||||
.singleRelashionshipSelect,
|
||||
.multiRelashionshipSelect {
|
||||
.q-chip {
|
||||
height: inherit;
|
||||
|
||||
&--dense {
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
||||
&__content {
|
||||
white-space: normal;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&__icon--remove {
|
||||
margin-right: -0.2em;
|
||||
margin-left: 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.q-menu .q-item {
|
||||
transition: none !important;
|
||||
}
|
||||
|
@ -142,5 +167,4 @@ body .q-tooltip {
|
|||
color: $dark;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// Tip: Use the "Theme Builder" on Quasar's documentation website.
|
||||
|
||||
$primary : #d7ac47;
|
||||
$secondary : #e3173a;
|
||||
$secondary : #f72e43;
|
||||
$accent : #dde4e4;
|
||||
|
||||
$dark : #18303a;
|
||||
|
@ -28,7 +28,7 @@ $customColors: (
|
|||
'gunmetal-light': lighten(#18303a, 7.5),
|
||||
'gunmetal-bright': lighten(#18303a, 30),
|
||||
'gunmetal-shine': lighten(#18303a, 60),
|
||||
'ruby-red': #e3173a,
|
||||
'ruby-red': #f72e43,
|
||||
'satin-sheen-gold': #d7ac47,
|
||||
'gainsboro': #dde4e4,
|
||||
'cultured': #f5f5f5
|
||||
|
|
|
@ -3,5 +3,9 @@
|
|||
|
||||
export default {
|
||||
failed: "Action failed",
|
||||
success: "Action was successful"
|
||||
success: "Action was successful",
|
||||
tooltips: {
|
||||
advancedSearch: `stuff
|
||||
more stuff`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,30 +4,6 @@
|
|||
>
|
||||
<div class="row justify-start q-col-gutter-x-xl">
|
||||
|
||||
<div class="col-12 flex justify-end q-mb-lg q-mt-md">
|
||||
<q-btn
|
||||
color="primary"
|
||||
:label="`Add a new ${bluePrintData.nameSingular} belonging under ${retrieveFieldValue(currentData, 'name')}`"
|
||||
@click="addNewUnderParent"
|
||||
class="q-mr-xl"
|
||||
v-if="!currentData.isNew"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
:label="`Save ${bluePrintData.nameSingular}`"
|
||||
@click="saveDocument"
|
||||
class="q-mr-xl"
|
||||
v-if="editMode"
|
||||
/>
|
||||
<q-btn
|
||||
color="primary"
|
||||
:label="`Edit ${bluePrintData.nameSingular}`"
|
||||
@click="toggleEditMode"
|
||||
class="q-mr-xl"
|
||||
v-if="!editMode"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="`col-${field.sizing} q-mb-md`"
|
||||
v-for="field in bluePrintData.extraFields"
|
||||
|
@ -170,11 +146,10 @@ import BaseClass from "src/BaseClass"
|
|||
import { I_Blueprint, I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import PouchDB from "pouchdb"
|
||||
// import { cleanDatabases } from "src/scripts/databaseManager/cleaner"
|
||||
import { single_changeRelationshipToAnotherObject, many_changeRelationshipToAnotherObject } from "src/scripts/databaseManager/relationshipManager"
|
||||
|
||||
import { extend } from "quasar"
|
||||
|
||||
import { saveDocument } from "src/scripts/databaseManager/documentManager"
|
||||
|
||||
import Field_Break from "src/components/fields/Field_Break.vue"
|
||||
import Field_Text from "src/components/fields/Field_Text.vue"
|
||||
import Field_Number from "src/components/fields/Field_Number.vue"
|
||||
|
@ -210,7 +185,24 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
* Watches on changes of the route in order to load proper blueprint and object data
|
||||
*/
|
||||
@Watch("$route", { immediate: true, deep: true })
|
||||
async onUrlChange () {
|
||||
onUrlChange () {
|
||||
this.reloadLocalContent().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches on changes of the opened documents in order to load proper blueprint and object data
|
||||
*/
|
||||
@Watch("SGET_allOpenedDocuments", { deep: true })
|
||||
async onDocChange () {
|
||||
await this.sleep(300)
|
||||
|
||||
const matchingDoc = this.findRequestedOrActiveDocument()
|
||||
if (matchingDoc && matchingDoc._id === this.currentData._id && !matchingDoc.hasEdits) {
|
||||
this.reloadLocalContent().catch(e => console.log(e))
|
||||
}
|
||||
}
|
||||
|
||||
async reloadLocalContent () {
|
||||
// Determine the type and retrieve the right blueprint
|
||||
this.bluePrintData = this.retrieveDocumentBlueprint()
|
||||
|
||||
|
@ -251,7 +243,7 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
reactToFieldUpdate (inputData: string, field: I_ExtraFields) {
|
||||
async reactToFieldUpdate (inputData: string, field: I_ExtraFields) {
|
||||
// FIELD - Text
|
||||
if (field.type === "text") {
|
||||
this.currentData.hasEdits = true
|
||||
|
@ -356,6 +348,14 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const dataCopy: I_OpenedDocument = extend(true, {}, this.currentData)
|
||||
|
||||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
|
||||
// @ts-ignore
|
||||
if (inputData.skipSave) {
|
||||
this.currentData.extraFields[indexToUpdate].value.skipSave = false
|
||||
await this.triggerSaveDocument()
|
||||
return
|
||||
}
|
||||
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
|
@ -368,6 +368,14 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const dataCopy: I_OpenedDocument = extend(true, {}, this.currentData)
|
||||
|
||||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
|
||||
// @ts-ignore
|
||||
if (inputData.skipSave) {
|
||||
this.currentData.extraFields[indexToUpdate].value.skipSave = false
|
||||
await this.triggerSaveDocument()
|
||||
return
|
||||
}
|
||||
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
|
@ -396,129 +404,40 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
toggleEditMode () {
|
||||
this.editMode = true
|
||||
this.currentData.editMode = true
|
||||
const dataCopy: I_OpenedDocument = extend(true, {}, this.currentData)
|
||||
const dataPass = { doc: dataCopy, treeAction: false }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
async triggerSaveDocument () {
|
||||
const currentDoc = this.currentData
|
||||
|
||||
async saveDocument () {
|
||||
this.editMode = false
|
||||
this.currentData.isNew = false
|
||||
this.currentData.hasEdits = false
|
||||
this.currentData.editMode = false
|
||||
const allDocuments = this.SGET_allOpenedDocuments
|
||||
|
||||
const CurrentObjectDB = new PouchDB(this.$route.params.type)
|
||||
const docCopy: I_OpenedDocument[] = extend(true, [], allDocuments.docs)
|
||||
|
||||
let currentDocument = false as unknown as I_OpenedDocument
|
||||
try {
|
||||
currentDocument = await CurrentObjectDB.get(this.$route.params.id)
|
||||
if (currentDoc) {
|
||||
// @ts-ignore
|
||||
const savedDocument: {
|
||||
documentCopy: I_OpenedDocument,
|
||||
allOpenedDocuments: I_OpenedDocument[]
|
||||
} = await saveDocument(currentDoc, docCopy)
|
||||
|
||||
// Update the opened document
|
||||
const dataPass = { doc: savedDocument.documentCopy, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
|
||||
// Update all others
|
||||
for (const doc of savedDocument.allOpenedDocuments) {
|
||||
// Update the opened document
|
||||
const dataPass = { doc: doc, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
this.editMode = false
|
||||
this.currentData.isNew = false
|
||||
this.currentData.hasEdits = false
|
||||
this.currentData.editMode = false
|
||||
}
|
||||
catch (error) {}
|
||||
|
||||
let documentCopy = {} as unknown as I_OpenedDocument
|
||||
if (currentDocument) {
|
||||
documentCopy = extend(true, {}, this.currentData)
|
||||
documentCopy._rev = currentDocument?._rev
|
||||
}
|
||||
else {
|
||||
documentCopy = extend(true, {}, this.currentData)
|
||||
}
|
||||
|
||||
// Handle relatinship fields
|
||||
const single_relationshipTypes = ["singleToSingleRelationship", "singleToManyRelationship"]
|
||||
const single_allRelationshipFields = documentCopy.extraFields.filter(field => {
|
||||
const currentField = this.bluePrintData.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
|
||||
return (currentField && single_relationshipTypes.includes(currentField.type))
|
||||
})
|
||||
const many_relationshipTypes = ["manyToSingleRelationship", "manyToManyRelationship"]
|
||||
const many_allRelationshipFields = documentCopy.extraFields.filter(field => {
|
||||
const currentField = this.bluePrintData.extraFields.find(e => e.id === field.id) as unknown as I_ExtraFields
|
||||
return (currentField && many_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 = this.bluePrintData.extraFields.find(e => e.id === field.id)?.relationshipSettings?.connectedField
|
||||
|
||||
const filteredDocuments = single_updatedDocuments.filter(doc => {
|
||||
return this.SGET_allOpenedDocuments.docs.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 docCopy: I_OpenedDocument = extend(true, {}, this.SGET_openedDocument(doc._id))
|
||||
docCopy.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
|
||||
|
||||
// Tree action here due to how parentDoc field works
|
||||
const dataPass = { doc: docCopy, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Update many fields
|
||||
for (const field of many_allRelationshipFields) {
|
||||
const many_updatedDocuments: I_OpenedDocument[] = await many_changeRelationshipToAnotherObject(field, documentCopy, currentDocument)
|
||||
|
||||
const pairedFieldID = this.bluePrintData.extraFields.find(e => e.id === field.id)?.relationshipSettings?.connectedField
|
||||
|
||||
const filteredDocuments = many_updatedDocuments.filter(doc => {
|
||||
return this.SGET_allOpenedDocuments.docs.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 docCopy: I_OpenedDocument = extend(true, {}, this.SGET_openedDocument(doc._id))
|
||||
docCopy.extraFields[toUpdateIndex] = doc.extraFields[toUpdateIndex]
|
||||
|
||||
const dataPass = { doc: docCopy, treeAction: false }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
})
|
||||
}
|
||||
// Save the document
|
||||
await CurrentObjectDB.put(documentCopy)
|
||||
|
||||
// Update the opened document
|
||||
const dataPass = { doc: documentCopy, treeAction: true }
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
editMode = false
|
||||
|
||||
/**
|
||||
* React to keypresses
|
||||
*/
|
||||
@Watch("SGET_getCurrentKeyBindData", { deep: true })
|
||||
processKeyPush () {
|
||||
// Save document
|
||||
if (this.determineKeyBind("saveDocument") && this.editMode) {
|
||||
this.saveDocument().catch(e => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
// Edit document - CTRL + E
|
||||
if (this.determineKeyBind("editDocument") && !this.editMode) {
|
||||
this.toggleEditMode()
|
||||
}
|
||||
}
|
||||
|
||||
currentData = false as unknown as I_OpenedDocument
|
||||
|
||||
/**
|
||||
|
@ -628,15 +547,6 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const ignoredList = ["breakBasic", "name", "documentColor", "parentDoc", "order", "categorySwitch"]
|
||||
return (!isCategory || ignoredList.includes(currentFieldID))
|
||||
}
|
||||
|
||||
addNewUnderParent () {
|
||||
const routeObject = {
|
||||
_id: this.currentData.type,
|
||||
parent: this.currentData._id
|
||||
}
|
||||
// @ts-ignore
|
||||
this.addNewObjectRoute(routeObject)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
103
src/scripts/databaseManager/documentManager.ts
Normal file
103
src/scripts/databaseManager/documentManager.ts
Normal file
|
@ -0,0 +1,103 @@
|
|||
import { single_changeRelationshipToAnotherObject, many_changeRelationshipToAnotherObject } from "src/scripts/databaseManager/relationshipManager"
|
||||
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import { extend } from "quasar"
|
||||
import PouchDB from "pouchdb"
|
||||
|
||||
/**
|
||||
* Saves the given project and handles all the needed procedures
|
||||
*/
|
||||
export const saveDocument = async (document: I_OpenedDocument, allOpenedDocuments: I_OpenedDocument[]) => {
|
||||
const BlueprintsDB = new PouchDB("blueprints")
|
||||
const currentBlueprint: {extraFields: I_ExtraFields[]} = await BlueprintsDB.get(document.type)
|
||||
|
||||
const CurrentObjectDB = new PouchDB(document.type)
|
||||
|
||||
let currentDocument = false as unknown as I_OpenedDocument
|
||||
try {
|
||||
currentDocument = await CurrentObjectDB.get(document._id)
|
||||
}
|
||||
catch (error) {}
|
||||
|
||||
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)
|
||||
|
||||
// Handle relatinship 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))
|
||||
})
|
||||
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))
|
||||
})
|
||||
|
||||
// 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 filteredDocuments = single_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]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 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]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
documentCopy.isNew = false
|
||||
documentCopy.hasEdits = false
|
||||
documentCopy.editMode = false
|
||||
|
||||
// Save the document
|
||||
await CurrentObjectDB.put(documentCopy)
|
||||
|
||||
return { documentCopy, allOpenedDocuments }
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
import { I_OpenedDocument } from "./../../interfaces/I_OpenedDocument"
|
||||
|
||||
export interface OpenDocumentsStateInterface {
|
||||
documents: {
|
||||
timestamp: string,
|
||||
treeAction: boolean,
|
||||
docs: I_OpenedDocument[]
|
||||
}
|
||||
documents: InnerOpenDocumentsStateInterface
|
||||
}
|
||||
|
||||
export interface InnerOpenDocumentsStateInterface {
|
||||
timestamp: string,
|
||||
treeAction: boolean,
|
||||
docs: I_OpenedDocument[]
|
||||
}
|
||||
|
||||
function state (): OpenDocumentsStateInterface {
|
||||
|
|
Loading…
Reference in a new issue