0.1.5 - Added context menus and document actions, various fixes

This commit is contained in:
Elvanos 2021-04-10 02:22:31 +02:00
parent 51e8df56c1
commit 1cfd078a21
22 changed files with 911 additions and 63 deletions

View file

@ -74,8 +74,11 @@ function createWindow () {
})
)
}
menu.popup()
console.log(params.dictionarySuggestions)
console.log(params.misspelledWord)
if((params.dictionarySuggestions && params.dictionarySuggestions.length) || params.misspelledWord){
menu.popup()
}
})
}

View file

@ -302,6 +302,11 @@ export default class BaseClass extends Vue {
treeAction: boolean
}) => void
@OpenedDocuments.Action("closeAllDocuments") SSET_closeAllDocuments!: () => void
@OpenedDocuments.Action("forceCloseAllDocuments") SSET_forceCloseAllDocuments!: () => void
@OpenedDocuments.Action("closeAllButCurrentDocuments") SSET_closeAllButCurrentDocuments!: (input: I_OpenedDocument) => void
@OpenedDocuments.Action("forceCloseAllButCurrentDocuments") SSET_forceCloseAllButCurrentDocuments!: (input: I_OpenedDocument) => void
@OpenedDocuments.Action("triggerTreeAction") SSET_triggerTreeAction!: () => void
@OpenedDocuments.Action("resetDocuments") SSET_resetDocuments!: () => void
@OpenedDocuments.Action("resetRemoveIndex") SSET_resetRemoveIndex!: () => void

View file

@ -197,6 +197,23 @@
</q-tooltip>
</q-btn>
<q-btn
icon="mdi-content-copy"
color="primary"
outline
@click="copyTargetDocument"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
>
<q-tooltip
:delay="500"
max-width="500px"
anchor="bottom left"
self="top middle"
>
Copy current document
</q-tooltip>
</q-btn>
<q-separator vertical inset color="accent"
v-if="!currentlyNew && SGET_allOpenedDocuments.docs.length > 0"
/>
@ -240,6 +257,8 @@ import tipsTricksTriviaDialog from "src/components/dialogs/TipsTricksTrivia.vue"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import { extend, Loading, QSpinnerGears } from "quasar"
import { saveDocument } from "src/scripts/databaseManager/documentManager"
import { createNewWithParent } from "src/scripts/documentActions/createNewWithParent"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
import { retrieveCurrentProjectName, exportProject } from "src/scripts/projectManagement/projectManagent"
@ -311,6 +330,12 @@ export default class DocumentControl extends BaseClass {
await this.sleep(100)
this.addNewUnderParent()
}
// Add new under parent - CTRL + ALT + C
if (this.determineKeyBind("copyDocument") && !this.currentlyNew && this.SGET_allOpenedDocuments.docs.length > 0 && !this.SGET_getDialogsState) {
await this.sleep(100)
this.copyTargetDocument()
}
}
/****************************************************************/
@ -414,15 +439,36 @@ export default class DocumentControl extends BaseClass {
// 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)
const currentDoc = this.findRequestedOrActiveDocument() as I_OpenedDocument
createNewWithParent(currentDoc, this)
}
/****************************************************************/
// Document copy
/****************************************************************/
documentPass = null as unknown as I_OpenedDocument
copyTargetDocument () {
this.documentPass = extend(true, {}, this.findRequestedOrActiveDocument())
const newDocument = copyDocument(this.documentPass, this.generateUID())
const dataPass = {
doc: newDocument,
treeAction: false
}
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
this.$router.push({
path: newDocument.url
}).catch((e: {name: string}) => {
const errorName : string = e.name
if (errorName === "NavigationDuplicated") {
return
}
console.log(e)
})
}
/****************************************************************/

View file

@ -1,6 +1,15 @@
<template>
<span>
<!-- Delele document dialog -->
<deleteDocumentCheckDialog
:dialog-trigger="deleteObjectDialogTrigger"
:document-id="toDeleteID"
:document-type="toDeleteType"
@trigger-dialog-close="deleteObjectDialogClose"
/>
<div
class="treeSearchWrapper"
:class="{'fullWidth': disableDocumentControlBar}"
@ -65,7 +74,7 @@
:name="prop.node.icon"
class="q-mr-sm self-center" />
<span v-if="prop.node.isDead" class="documentLabel__isDeadMarker"></span>
<span class="documentLabel__content">
<span :class="{'documentLabel__content': !hideDeadCrossThrough}">
{{ prop.node.label }}
</span>
@ -86,7 +95,7 @@
<q-badge
class="treeBadge"
:class="{'noChilden': prop.node.children.length === 0}"
v-if="prop.node.sticker"
v-if="prop.node.sticker && !hideTreeOrderNumbers"
color="primary"
outline
floating
@ -125,7 +134,7 @@
dense
color="dark"
class="z-1 q-ml-sm treeButton treeButton--add"
icon="mdi-plus"
icon="mdi-file-tree"
size="10px"
@click.stop.prevent="processNodeNewDocumentButton(prop.node)"
>
@ -136,6 +145,89 @@
</q-tooltip>
</q-btn>
</div>
<q-menu
touch-position
context-menu
>
<q-list class="bg-gunmetal-light" v-if="!prop.node.isTag">
<template v-if="prop.node.isRoot || prop.node.children.length > 0">
<q-item clickable v-close-popup @click="recursivelyExpandNodeDownwards(prop.node.key)">
<q-item-section>Expand all</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-expand-all-outline" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="collapseAllNodesForce(prop.node)">
<q-item-section>Collapse all</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-collapse-all-outline" />
</q-item-section>
</q-item>
</template>
<template v-if="prop.node.isRoot">
<q-separator />
<q-item clickable v-close-popup @click="addNewObjectRoute(prop.node)">
<q-item-section>Add new document of type: {{prop.node.label}}</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-plus" />
</q-item-section>
</q-item>
</template>
<template v-if="!prop.node.isRoot">
<q-separator />
<q-item clickable v-close-popup @click="copyName(prop.node)">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="copyTextColor(prop.node)">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="copyBackgroundColor(prop.node)">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator />
<q-item clickable v-close-popup @click="openExistingDocumentRoute(prop.node)">
<q-item-section>Open document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-pencil" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="addNewUnderParent(prop.node)">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="copyTargetDocument(prop.node)">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-content-copy" />
</q-item-section>
</q-item>
<q-separator />
<q-item clickable v-close-popup @click="deleteTabDocument(prop.node)">
<q-item-section class="text-secondary"><b>Delete this document</b></q-item-section>
<q-item-section avatar class="text-secondary">
<q-icon name="mdi-text-box-remove-outline" />
</q-item-section>
</q-item>
</template>
</q-list>
</q-menu>
</div>
</div>
@ -175,15 +267,20 @@ import { Component, Watch } from "vue-property-decorator"
import BaseClass from "src/BaseClass"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import PouchDB from "pouchdb"
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
import { engageBlueprints, retrieveAllBlueprints } from "src/scripts/databaseManager/blueprintManager"
// import { cleanDatabases } from "src/scripts/databaseManager/cleaner"
import { I_Blueprint } from "src/interfaces/I_Blueprint"
import { extend, colors } from "quasar"
import { tagListBuildFromBlueprints } from "src/scripts/utilities/tagListBuilder"
import { retrieveCurrentProjectName } from "src/scripts/projectManagement/projectManagent"
import { createNewWithParent } from "src/scripts/documentActions/createNewWithParent"
import { copyDocumentName, copyDocumentTextColor, copyDocumentBackgroundColor } from "src/scripts/documentActions/uniqueFieldCopy"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
@Component({
components: { }
components: { deleteDocumentCheckDialog }
})
export default class ObjectTree extends BaseClass {
/****************************************************************/
@ -234,6 +331,8 @@ export default class ObjectTree extends BaseClass {
compactDocumentCount = false
invertCategoryPosition = false
doubleDashDocCount = false
hideDeadCrossThrough = false
hideTreeOrderNumbers = false
@Watch("SGET_options", { immediate: true, deep: true })
onSettingsChange () {
@ -250,6 +349,9 @@ export default class ObjectTree extends BaseClass {
this.compactDocumentCount = options.compactDocumentCount
this.invertCategoryPosition = options.invertCategoryPosition
this.doubleDashDocCount = options.doubleDashDocCount
this.hideDeadCrossThrough = options.hideDeadCrossThrough
this.hideTreeOrderNumbers = options.hideTreeOrderNumbers
this.buildCurrentObjectTree().catch((e) => {
console.log(e)
})
@ -696,11 +798,11 @@ export default class ObjectTree extends BaseClass {
newDocsSnapshot = null
expandIDs.forEach(s => {
this.recursivelyExpandNode(s)
this.recursivelyExpandNodeUpwards(s)
})
}
recursivelyExpandNode (nodeID: string) {
recursivelyExpandNodeUpwards (nodeID: string) {
const treeDOM = this.$refs.tree as unknown as {
setExpanded: (key:string, state: boolean)=> void
getNodeByKey: (key:string)=> void
@ -716,7 +818,37 @@ export default class ObjectTree extends BaseClass {
// Dig into the upper hierarchy
if (currentTreeNode?.parentDoc) {
this.recursivelyExpandNode(currentTreeNode.parentDoc)
this.recursivelyExpandNodeUpwards(currentTreeNode.parentDoc)
}
// If we are at the top of the tree, expand the top category
else if (currentTreeNode?.type) {
// @ts-ignore
this.expandedTreeNodes = [...new Set([
...this.expandedTreeNodes,
currentTreeNode.type
])]
}
}
recursivelyExpandNodeDownwards (nodeID: string) {
const treeDOM = this.$refs.tree as unknown as {
setExpanded: (key:string, state: boolean)=> void
getNodeByKey: (key:string)=> void
}
// @ts-ignore
this.expandedTreeNodes = [...new Set([
...this.expandedTreeNodes,
nodeID
])]
const currentTreeNode = (treeDOM.getNodeByKey(nodeID)) as unknown as {children: any[], type: string}
// Dig into the upper hierarchy
if (currentTreeNode?.children && currentTreeNode?.children.length > 0) {
for (const child of currentTreeNode.children) {
this.recursivelyExpandNodeDownwards(child.key)
}
}
// If we are at the top of the tree, expand the top category
else if (currentTreeNode?.type) {
@ -805,6 +937,19 @@ export default class ObjectTree extends BaseClass {
}
}
collapseAllNodesForce (node: {key: string, children: []}) {
if (node.children) {
for (const child of node.children) {
if (this.expandedTreeNodes.includes(node.key)) {
this.collapseAllNodesForce(child)
}
}
}
if (this.expandedTreeNodes.includes(node.key)) {
this.expandedTreeNodes = this.expandedTreeNodes.filter(n => n !== node.key)
}
}
determineCatyegoryString (node: {
documentCount: string
categoryCount: string
@ -824,6 +969,80 @@ export default class ObjectTree extends BaseClass {
return `(<span class="docCount">${node.documentCount}</span>&nbsp;|${extraDivider}&nbsp;<span class="catCount">${node.categoryCount}</span>)`
}
}
/****************************************************************/
// Document field copying
/****************************************************************/
copyName (currentDoc: I_OpenedDocument) {
copyDocumentName(currentDoc)
}
copyTextColor (currentDoc: I_OpenedDocument) {
copyDocumentTextColor(currentDoc)
}
copyBackgroundColor (currentDoc: I_OpenedDocument) {
copyDocumentBackgroundColor(currentDoc)
}
/****************************************************************/
// Document copy
/****************************************************************/
documentPass = null as unknown as I_OpenedDocument
copyTargetDocument (currentDoc: I_OpenedDocument) {
this.documentPass = extend(true, {}, currentDoc)
const newDocument = copyDocument(this.documentPass, this.generateUID())
const dataPass = {
doc: newDocument,
treeAction: false
}
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
this.$router.push({
path: newDocument.url
}).catch((e: {name: string}) => {
const errorName : string = e.name
if (errorName === "NavigationDuplicated") {
return
}
console.log(e)
})
}
/****************************************************************/
// Add new document under parent
/****************************************************************/
addNewUnderParent (currentDoc: I_OpenedDocument) {
createNewWithParent(currentDoc, this)
}
/****************************************************************/
// Delete dialog
/****************************************************************/
deleteObjectDialogTrigger: string | false = false
deleteObjectDialogClose () {
this.deleteObjectDialogTrigger = false
}
deleteObjectAssignUID () {
this.deleteObjectDialogTrigger = this.generateUID()
}
toDeleteID = ""
toDeleteType = ""
deleteTabDocument (targetDocument: I_OpenedDocument) {
this.toDeleteID = targetDocument._id
this.toDeleteType = targetDocument.type
this.deleteObjectAssignUID()
}
}
</script>

View file

@ -8,6 +8,14 @@
@trigger-dialog-close="closeDocumentCheckDialogClose"
/>
<!-- Delele document dialog -->
<deleteDocumentCheckDialog
:dialog-trigger="deleteObjectDialogTrigger"
:document-id="toDeleteID"
:document-type="toDeleteType"
@trigger-dialog-close="deleteObjectDialogClose"
/>
<q-tabs
v-if="localDocuments.length > 0"
:class="{'hasTextShadow': textShadow}"
@ -33,7 +41,10 @@
:to="`/project/display-content/${document.type}/${document._id}`"
:key="document.type+document._id"
:icon="(retrieveFieldValue(document,'categorySwitch') ? 'fas fa-folder-open' : document.icon)"
:style="`color: ${retrieveFieldValue(document,'documentColor')}; background-color: ${retrieveFieldValue(document,'documentBackgroundColor')}; filter: ${(retrieveFieldValue(document,'minorSwitch') ? 'grayscale(100) brightness(0.7)' : '')}`"
:style="`
color: ${retrieveFieldValue(document,'documentColor')};
background-color: ${retrieveFieldValue(document,'documentBackgroundColor')};
filter: ${(retrieveFieldValue(document,'minorSwitch') ? 'grayscale(100) brightness(0.7)' : '')}`"
:class="[
{'isBold':
(
@ -51,7 +62,7 @@
</span>
<div
class="q-tab__label"
:class="{'isDead': retrieveFieldValue(document,'deadSwitch')}">
:class="{'isDead': (retrieveFieldValue(document,'deadSwitch') && !hideDeadCrossThrough)}">
{{retrieveFieldValue(document,'name')}}
</div>
<q-tooltip
@ -75,6 +86,86 @@
style="color: #fff;"
@click.stop.prevent="tryCloseTab(document)"
/>
<q-menu
touch-position
context-menu
>
<q-list class="bg-gunmetal-light">
<q-item clickable v-close-popup @click="copyName(document)">
<q-item-section>Copy name</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-text-recognition" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="copyTextColor(document)">
<q-item-section>Copy text color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-eyedropper" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="copyBackgroundColor(document)">
<q-item-section>Copy background color</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-format-color-fill" />
</q-item-section>
</q-item>
<q-separator />
<q-item v-if="!document.isNew" clickable v-close-popup @click="addNewUnderParent(document)">
<q-item-section>Create new document with this document as parent</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-file-tree" />
</q-item-section>
</q-item>
<q-item clickable v-if="!document.isNew" v-close-popup @click="copyTargetDocument(document)">
<q-item-section>Copy this document</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-content-copy" />
</q-item-section>
</q-item>
<q-separator v-if="!document.isNew" />
<q-item clickable v-close-popup @click="tryCloseTab(document)">
<q-item-section>Close this tab</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-close" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="SSET_closeAllButCurrentDocuments(document)">
<q-item-section>Close all tabs without changes except for this</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-close-box-outline" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="SSET_closeAllDocuments">
<q-item-section>Close all tabs without changes</q-item-section>
<q-item-section avatar>
<q-icon name="mdi-close-box-multiple-outline" />
</q-item-section>
</q-item>
<q-separator />
<q-item clickable v-close-popup @click="SSET_forceCloseAllButCurrentDocuments(document)">
<q-item-section>Force close all tabs except for this</q-item-section>
<q-item-section avatar class="text-secondary">
<q-icon name="mdi-close-box" />
</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="SSET_forceCloseAllDocuments">
<q-item-section>Force close all tabs</q-item-section>
<q-item-section avatar class="text-secondary">
<q-icon name="mdi-close-box-multiple" />
</q-item-section>
</q-item>
<q-separator />
<q-item clickable v-close-popup @click="deleteTabDocument(document)">
<q-item-section class="text-secondary"><b>Delete this document</b></q-item-section>
<q-item-section avatar class="text-secondary">
<q-icon name="mdi-text-box-remove-outline" />
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-route-tab>
</transition-group>
@ -89,12 +180,20 @@
import BaseClass from "src/BaseClass"
import { Component, Watch } from "vue-property-decorator"
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import closeDocumentCheckDialog from "src/components/dialogs/CloseDocumentCheck.vue"
import { createNewWithParent } from "src/scripts/documentActions/createNewWithParent"
import { copyDocumentName, copyDocumentTextColor, copyDocumentBackgroundColor } from "src/scripts/documentActions/uniqueFieldCopy"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
import { extend } from "quasar"
@Component({
components: { closeDocumentCheckDialog }
components: {
closeDocumentCheckDialog,
deleteDocumentCheckDialog
}
})
export default class TopTabs extends BaseClass {
/****************************************************************/
@ -106,6 +205,11 @@ export default class TopTabs extends BaseClass {
*/
textShadow = false
/**
* Determines if the "dead" document type should have a cross-text decoration or not
*/
hideDeadCrossThrough = false
/**
* Watch changes on options
*/
@ -113,6 +217,7 @@ export default class TopTabs extends BaseClass {
onSettingsChange () {
const options = this.SGET_options
this.textShadow = options.textShadow
this.hideDeadCrossThrough = options.hideDeadCrossThrough
}
/****************************************************************/
@ -138,6 +243,28 @@ export default class TopTabs extends BaseClass {
if (this.determineKeyBind("previousTab") && this.localDocuments.length > 0 && !this.SGET_getDialogsState) {
this.goToPreviousTab()
}
// Close all tabs without changes except for this - CTRL + ALT + SHIFT + W
if (this.determineKeyBind("closeAllTabsWithoutChangesButThis") && this.localDocuments.length > 0 && !this.SGET_getDialogsState) {
const currentDoc = this.findRequestedOrActiveDocument() as I_OpenedDocument
this.SSET_closeAllButCurrentDocuments(currentDoc)
}
// Close all tabs without changes - CTRL + SHIFT + W
if (this.determineKeyBind("closeAllTabsWithoutChanges") && this.localDocuments.length > 0 && !this.SGET_getDialogsState) {
this.SSET_closeAllDocuments()
}
// Force close all tabs except for this - NONE
if (this.determineKeyBind("forceCloseAllTabsButThis") && this.localDocuments.length > 0 && !this.SGET_getDialogsState) {
const currentDoc = this.findRequestedOrActiveDocument() as I_OpenedDocument
this.SSET_forceCloseAllButCurrentDocuments(currentDoc)
}
// Force close all tabs - NONE
if (this.determineKeyBind("forceCloseAllTabs") && this.localDocuments.length > 0 && !this.SGET_getDialogsState) {
this.SSET_forceCloseAllDocuments()
}
}
/****************************************************************/
@ -231,6 +358,58 @@ export default class TopTabs extends BaseClass {
}
}
/****************************************************************/
// Document field copying
/****************************************************************/
copyName (currentDoc: I_OpenedDocument) {
copyDocumentName(currentDoc)
}
copyTextColor (currentDoc: I_OpenedDocument) {
copyDocumentTextColor(currentDoc)
}
copyBackgroundColor (currentDoc: I_OpenedDocument) {
copyDocumentBackgroundColor(currentDoc)
}
/****************************************************************/
// Document copy
/****************************************************************/
documentPass = null as unknown as I_OpenedDocument
copyTargetDocument (currentDoc: I_OpenedDocument) {
this.documentPass = extend(true, {}, currentDoc)
const newDocument = copyDocument(this.documentPass, this.generateUID())
const dataPass = {
doc: newDocument,
treeAction: false
}
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
this.$router.push({
path: newDocument.url
}).catch((e: {name: string}) => {
const errorName : string = e.name
if (errorName === "NavigationDuplicated") {
return
}
console.log(e)
})
}
/****************************************************************/
// Add new document under parent
/****************************************************************/
addNewUnderParent (currentDoc: I_OpenedDocument) {
createNewWithParent(currentDoc, this)
}
/****************************************************************/
// Close document dialog
/****************************************************************/
@ -243,6 +422,28 @@ export default class TopTabs extends BaseClass {
closeDocumentCheckDialogAssignUID () {
this.closeDocumentCheckDialogTrigger = this.generateUID()
}
/****************************************************************/
// Delete dialog
/****************************************************************/
deleteObjectDialogTrigger: string | false = false
deleteObjectDialogClose () {
this.deleteObjectDialogTrigger = false
}
deleteObjectAssignUID () {
this.deleteObjectDialogTrigger = this.generateUID()
}
toDeleteID = ""
toDeleteType = ""
deleteTabDocument (targetDocument: I_OpenedDocument) {
this.toDeleteID = targetDocument._id
this.toDeleteType = targetDocument.type
this.deleteObjectAssignUID()
}
}
</script>

View file

@ -28,6 +28,7 @@
v-close-popup />
<q-btn
outline
:disable="!retrieveFieldValue(currentDocument, 'name')"
label="Delete document"
color="secondary"
@click="deleteDocument()" />
@ -38,7 +39,7 @@
<script lang="ts">
import { Component, Watch } from "vue-property-decorator"
import { Component, Watch, Prop } from "vue-property-decorator"
import DialogBase from "src/components/dialogs/_DialogBase"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
@ -53,18 +54,34 @@ export default class DeleteDocumentCheckDialog extends DialogBase {
*/
@Watch("dialogTrigger")
async openDialog (val: string|false) {
if (val && this.SGET_allOpenedDocuments.docs.length > 0) {
if (val && (this.SGET_allOpenedDocuments.docs.length > 0 || (this.documentType.length > 0 && this.documentId.length > 0))) {
if (this.SGET_getDialogsState) {
return
}
this.SSET_setDialogState(true)
this.dialogModel = true
const CurrentObjectDB = new PouchDB(this.$route.params.type)
this.currentDocument = await CurrentObjectDB.get(this.$route.params.id)
const documentType = (this.documentType.length > 0) ? this.documentType : this.$route.params.type
const documentID = (this.documentId.length > 0) ? this.documentId : this.$route.params.id
const CurrentObjectDB = new PouchDB(documentType)
this.currentDocument = await CurrentObjectDB.get(documentID)
await CurrentObjectDB.close()
}
}
/**
* OPTIONAL
* Type of the document to delete
*/
@Prop({ default: "" }) readonly documentType!: ""
/**
* OPTIONAL
* ID of the document to delete
*/
@Prop({ default: "" }) readonly documentId!: ""
/**
* Current document for deletion
*/
@ -74,7 +91,8 @@ export default class DeleteDocumentCheckDialog extends DialogBase {
* Delete the document
*/
async deleteDocument () {
const CurrentObjectDB = new PouchDB(this.$route.params.type)
const documentType = (this.documentType.length > 0) ? this.documentType : this.$route.params.type
const CurrentObjectDB = new PouchDB(documentType)
// @ts-ignore
await CurrentObjectDB.remove(this.currentDocument)

View file

@ -58,7 +58,7 @@
<span class="isDeadIndicator" v-if="opt.isDead">
</span>
<span :class="{'isDead': opt.isDead}" v-html="opt.label">
<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>
@ -82,7 +82,7 @@
dark
color="primary"
class="z-1 q-ml-md"
icon="mdi-plus"
icon="mdi-file-tree"
size="md"
@click.stop.prevent="addNewItemUnderSelected(opt)"
>
@ -92,6 +92,24 @@
Add a new document belonging under {{ stripTags(opt.label) }}
</q-tooltip>
</q-btn>
<q-btn
tabindex="-1"
round
flat
dense
dark
color="accent"
class="z-1 q-ml-sm"
icon="mdi-content-copy"
size="md"
@click.stop.prevent="copyTargetDocument(opt)"
>
<q-tooltip
:delay="300"
>
Make a copy of {{ stripTags(opt.label) }}
</q-tooltip>
</q-btn>
</q-item>
</template>
</q-select>
@ -110,10 +128,11 @@
<script lang="ts">
import { Component, Watch } from "vue-property-decorator"
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { I_OpenedDocument, I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
import { extend } from "quasar"
import PouchDB from "pouchdb"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
import DialogBase from "src/components/dialogs/_DialogBase"
import { I_Blueprint } from "src/interfaces/I_Blueprint"
@ -164,8 +183,14 @@ export default class ExistingDocumentDialog extends DialogBase {
this.disableCloseAftertSelectQuickSearch = this.SGET_options.disableCloseAftertSelectQuickSearch
this.includeCategories = !this.SGET_options.disableQuickSearchCategoryPrecheck
this.textShadow = this.SGET_options.textShadow
this.hideDeadCrossThrough = this.SGET_options.hideDeadCrossThrough
}
/**
* Determines if the "dead" document type should have a cross-text decoration or not
*/
hideDeadCrossThrough = false
/**
* Determines if the popup shouldnt close after a document is selected from the dropdown list
*/
@ -383,6 +408,31 @@ export default class ExistingDocumentDialog extends DialogBase {
// @ts-ignore
this.addNewObjectRoute(routeObject)
}
documentPass = null as unknown as I_OpenedDocument
copyTargetDocument (currentDoc: I_OpenedDocument) {
this.documentPass = extend(true, {}, currentDoc)
const newDocument = copyDocument(this.documentPass, this.generateUID())
const dataPass = {
doc: newDocument,
treeAction: false
}
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
this.$router.push({
path: newDocument.url
}).catch((e: {name: string}) => {
const errorName : string = e.name
if (errorName === "NavigationDuplicated") {
return
}
console.log(e)
})
}
}
</script>

View file

@ -74,16 +74,17 @@ export default class KeybindCheatsheet extends DialogBase {
// Remap the cheetcheet based on available input settings
this.localCheatSheet = this.SGET_getCurrentKeyBindData.defaults.map((bind, index) => {
const userKb = this.SGET_getCurrentKeyBindData.userKeybinds.find(userKb => userKb.id === bind.id)
const mappedKeybind = (
this.SGET_getCurrentKeyBindData.userKeybinds[index] &&
this.SGET_getCurrentKeyBindData.userKeybinds[index].which
userKb &&
userKb.which
)
// If user keybind
? {
altKey: this.SGET_getCurrentKeyBindData.userKeybinds[index].altKey,
ctrlKey: this.SGET_getCurrentKeyBindData.userKeybinds[index].ctrlKey,
shiftKey: this.SGET_getCurrentKeyBindData.userKeybinds[index].shiftKey,
which: this.SGET_getCurrentKeyBindData.userKeybinds[index].which,
altKey: userKb.altKey,
ctrlKey: userKb.ctrlKey,
shiftKey: userKb.shiftKey,
which: userKb.which,
id: bind.id,
tooltip: bind.tooltip,
note: bind.note

View file

@ -101,6 +101,21 @@
/>
</div>
<div class="col-4 optionWrapper">
<div class="optionTitle">
Accessibility - Hide strike-through
<q-icon name="mdi-help-circle" size="16px" class="q-ml-md">
<q-tooltip :delay="500">
This setting hides the strike through effect on dead/gone/destroyed documents in order to increase visibility.
</q-tooltip>
</q-icon>
</div>
<q-toggle
v-model="options.hideDeadCrossThrough"
/>
</div>
<div class="col-4 optionWrapper">
<div class="optionTitle">
Hide Welcome screen social links
@ -414,6 +429,21 @@
/>
</div>
<div class="col-4 optionWrapper">
<div class="optionTitle">
Hide order numbers
<q-icon name="mdi-help-circle" size="16px" class="q-ml-md">
<q-tooltip :delay="500">
This option disabled showing of the custom order numbers left of the names.
</q-tooltip>
</q-icon>
</div>
<q-toggle
v-model="options.hideTreeOrderNumbers"
/>
</div>
</div>
</q-scroll-area>
</q-tab-panel>
@ -655,6 +685,7 @@ export default class ProgramSettings extends DialogBase {
darkMode: false,
textShadow: false,
doubleDashDocCount: false,
hideDeadCrossThrough: false,
tagsAtTop: false,
noTags: false,
compactTags: false,
@ -674,6 +705,7 @@ export default class ProgramSettings extends DialogBase {
hideWelcomeScreenSocials: false,
hideTooltipsStart: false,
hideTooltipsProject: false,
hideTreeOrderNumbers: false,
userKeybindList: []
}
@ -895,7 +927,7 @@ export default class ProgramSettings extends DialogBase {
id: keybind.id,
editable: keybind.editable,
defaultKeybind: keybind,
userKeybind: (this.options.userKeybindList[index]) || ""
userKeybind: (this.options.userKeybindList.find(userKb => userKb.id === keybind.id)) || ""
}
})
}

View file

@ -49,7 +49,7 @@
<span class="isDeadIndicator" v-if="single.isDead">
</span>
<span :class="{'isDead': single.isDead}">
<span :class="{'isDead': (single.isDead && !hideDeadCrossThrough)}">
{{stripTags(single.label)}}
</span>
</span>
@ -147,7 +147,7 @@
<span class="isDeadIndicator" v-if="opt.isDead">
</span>
<span :class="{'isDead': opt.isDead}" v-html="opt.label">
<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>

View file

@ -46,7 +46,7 @@
<span class="isDeadIndicator" v-if="localInput.isDead">
</span>
<span :class="{'isDead': localInput.isDead}">
<span :class="{'isDead': (localInput.isDead && !hideDeadCrossThrough)}">
{{stripTags(localInput.label)}}
</span>
</span>
@ -145,7 +145,7 @@
<span class="isDeadIndicator" v-if="opt.isDead">
</span>
<span :class="{'isDead': opt.isDead}" v-html="opt.label">
<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>

View file

@ -44,8 +44,14 @@ export default class FieldBase extends BaseClass {
this.isDarkMode = this.SGET_options.darkMode
this.disableDocumentToolTips = this.SGET_options.disableDocumentToolTips
this.textShadow = this.SGET_options.textShadow
this.hideDeadCrossThrough = this.SGET_options.hideDeadCrossThrough
}
/**
* Determines if the "dead" document type should have a cross-text decoration or not
*/
hideDeadCrossThrough = false
/**
* Determines if the text has shadows or not
*/

View file

@ -16,22 +16,61 @@
- Fixed a bug that was causing the relationship dropdowns sometimes not be clickable and instead caused dragging of the app window when shown over the top of the drag-bar at the top of the app
- Updated advanced search guide with missing information about full-text search
- Changes a small bug when the `New Object` dialog wasn't respecting option changes being done in the same session of the program being opened
- Fixed a bug that was sometimes showing improper values inside the user defined keybinds both in the key settings and the cheatsheet
- Fixed tag groups in hierarchical tree not respecting custom order and alphabetical order
- Fixed a rather peculiar recuring bug that could cause the database to endlessly attempt to update a document while constantly throwing errors
- Fixed a bug that was causing an "Empty" checkbox popping up at irrelevant places on right click
- Managed to fix or at least mitigate multiple memory-leaks across the app
- Optimized multiple parts of the code to run smoother
- Fixed wrong icons in some fields in some document types
- Fixed a bug that was allowing for an attempted deletion of a document while the document data was still being retrieved. This resulted in an error that both made a mess of a UI and didn't delete the desider document
### New features
- Added context menu support and multiple actions (right click) for top tabs and hierarchical tree
- New action for **Top Tabs**
- Copy name
- Copy text color
- Copy background color
- Create new document with this document as parent
- Copy this document
- Close this tab
- Close all tabs without changes except for this
- Close all tabs without changes
- Force close all tabs except for this
- Force close all tabs
- Delete document
- New action for **Hiearachical Tree**
- Add new document type: `DOCUMENT TYPE`
- Only available in the root-categories
- Expand all
- Collapse all
- Copy name
- Copy text color
- Copy background color
- Open document
- Create new document with this document as parent
- Copy this document
- Delete document
- Added support for default empty keybinds
- Added a dedicated button that opens the connected documents straight from the little chips in relationship fields while in edit mode
- Added support for background color for documents
- Added support for "Minor document" mode switch for better organization and visual representation of documents
- Added support for "Dead/Gone/Destroyed" mode switch for better organization and visual representation of documents
- Added option: Accessibility - Hide strike-through
- Added option: Accessibility - Hide order numbers
- Added functionality to copy existing documents along with all their contents
- Added keybind: Close all tabs without changes except for this
- Added keybind: Close all tabs without changes
- Added keybind: Force close all tabs except for this
- Added keybind: Force close all tabs
- Added keybind: Copy active document
### QoL adjustments
- Changed focusing of the hierarchy tree search input from CTRL + SHIFT + W to CTRL + SHIFT +T
- Updated fullscreen editor looks to work more like a proper document editor
- Unified icons for same actions across the app
- Reordered the basic document settings inside the app and separated them from the document content
- Adjusted maximum width of switch fields to make them look like spaggeti
- Updated the Advanced search guide with new additions and added one new Trivia popup text concerning it

View file

@ -73,6 +73,23 @@
</q-tooltip>
</q-btn>
<q-btn
color="primary"
icon="mdi-content-copy"
@click="copyTargetDocument"
:outline="isDarkMode"
class="q-mr-md"
v-if="!currentData.isNew"
>
<q-tooltip
:delay="500"
anchor="bottom middle"
self="top middle"
>
Copy current document
</q-tooltip>
</q-btn>
<q-btn
color="secondary"
icon="mdi-text-box-remove-outline"
@ -234,6 +251,7 @@ import { I_Blueprint, I_ExtraFields } from "src/interfaces/I_Blueprint"
import PouchDB from "pouchdb"
import { extend } from "quasar"
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
import { copyDocument } from "src/scripts/documentActions/copyDocument"
import { saveDocument } from "src/scripts/databaseManager/documentManager"
import deleteDocumentCheckDialog from "src/components/dialogs/DeleteDocumentCheck.vue"
@ -766,6 +784,34 @@ export default class PageDocumentDisplay extends BaseClass {
}
}
/****************************************************************/
// `DOCUMENT COPY
/****************************************************************/
documentPass = null as unknown as I_OpenedDocument
copyTargetDocument () {
this.documentPass = extend(true, {}, this.findRequestedOrActiveDocument())
const newDocument = copyDocument(this.documentPass, this.generateUID())
const dataPass = {
doc: newDocument,
treeAction: false
}
// @ts-ignore
this.SSET_addOpenedDocument(dataPass)
this.$router.push({
path: newDocument.url
}).catch((e: {name: string}) => {
const errorName : string = e.name
if (errorName === "NavigationDuplicated") {
return
}
console.log(e)
})
}
/****************************************************************/
// DOCUMENT ACTIONS
/****************************************************************/

View file

@ -55,12 +55,12 @@ export const defaultKeybinds = [
tooltip: "Focus search field in the left hierarchical tree"
},
// Clear input in the left tree search - CTRL + SHIFT + W
// Clear input in the left tree search - CTRL + SHIFT + T
{
altKey: false,
ctrlKey: true,
shiftKey: true,
which: 87,
which: 84,
editable: true,
id: "clearInputHierarchicalTree",
tooltip: "Clear any input in the search field in the left hierarchical tree"
@ -77,6 +77,50 @@ export const defaultKeybinds = [
tooltip: "Close active document"
},
// Close all tabs without changes except for this - CTRL + ALT + SHIFT + W
{
altKey: true,
ctrlKey: true,
shiftKey: true,
which: 87,
editable: true,
id: "closeAllTabsWithoutChangesButThis",
tooltip: "Close all tabs without changes except for this"
},
// Close all tabs without changes - CTRL + SHIFT + W
{
altKey: false,
ctrlKey: true,
shiftKey: true,
which: 87,
editable: true,
id: "closeAllTabsWithoutChanges",
tooltip: "Close all tabs without changes"
},
// Force close all tabs except for this - NONE
{
altKey: false,
ctrlKey: false,
shiftKey: false,
which: false,
editable: true,
id: "forceCloseAllTabsButThis",
tooltip: "Force close all tabs except for this"
},
// Force close all tabs - NONE
{
altKey: false,
ctrlKey: false,
shiftKey: false,
which: false,
editable: true,
id: "forceCloseAllTabs",
tooltip: "Force close all tabs"
},
// Next tab - ALT + RIGHT ARROW
{
altKey: true,
@ -121,7 +165,7 @@ export const defaultKeybinds = [
tooltip: "Edit active document"
},
// Edit document - CTRL + SHIFT + N
// Add a new document with current as parent - CTRL + SHIFT + N
{
altKey: false,
ctrlKey: true,
@ -132,6 +176,17 @@ export const defaultKeybinds = [
tooltip: "Add a new document with the currently opened one as the parent"
},
// Copy document - CTRL + ALT + C
{
altKey: true,
ctrlKey: true,
shiftKey: false,
which: 67,
editable: true,
id: "copyDocument",
tooltip: "Copy active document"
},
// Delete document - CTRL + D
{
altKey: false,

View file

@ -0,0 +1,18 @@
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
export const copyDocument = (currentDoc: I_OpenedDocument, newDocumentID: string) : I_OpenedDocument => {
currentDoc._id = newDocumentID
currentDoc.isNew = true
currentDoc.editMode = true
currentDoc.hasEdits = false
currentDoc.url = `/project/display-content/${currentDoc.type}/${newDocumentID}`
delete (currentDoc._rev)
const documentNameIndex = currentDoc.extraFields.findIndex(e => e.id === "name")
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
currentDoc.extraFields[documentNameIndex].value = `Copy of - ${currentDoc.extraFields[documentNameIndex].value}`
return currentDoc
}

View file

@ -0,0 +1,15 @@
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
/**
* Toggles dev tools in the current window
*/
export const createNewWithParent = (currentDoc: I_OpenedDocument, callingComponent: any) => {
if (currentDoc) {
const routeObject = {
_id: currentDoc.type,
parent: currentDoc._id
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
callingComponent.addNewObjectRoute(routeObject)
}
}

View file

@ -0,0 +1,34 @@
import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
export const copyDocumentName = (targetDocument: I_OpenedDocument) => {
const returnValue = targetDocument.extraFields.find(e => e.id === "name")?.value
const el = document.createElement("textarea")
el.value = returnValue
document.body.appendChild(el)
el.select()
document.execCommand("copy")
document.body.removeChild(el)
}
export const copyDocumentTextColor = (targetDocument: I_OpenedDocument) => {
const returnValue = targetDocument.extraFields.find(e => e.id === "documentColor")?.value
const el = document.createElement("textarea")
el.value = (returnValue) || ""
document.body.appendChild(el)
el.select()
document.execCommand("copy")
document.body.removeChild(el)
}
export const copyDocumentBackgroundColor = (targetDocument: I_OpenedDocument) => {
const returnValue = targetDocument.extraFields.find(e => e.id === "documentBackgroundColor")?.value
const el = document.createElement("textarea")
el.value = (returnValue) || ""
document.body.appendChild(el)
el.select()
document.execCommand("copy")
document.body.removeChild(el)
}

View file

@ -36,6 +36,38 @@ const actions: ActionTree<OpenDocumentsStateInterface, StateInterface> = {
}, 200)
},
closeAllDocuments (state) {
state.commit("closeAllDocuments")
setTimeout(() => {
state.commit("resetTreeAction")
}, 200)
},
forceCloseAllDocuments (state) {
state.commit("forceCloseAllDocuments")
setTimeout(() => {
state.commit("resetTreeAction")
}, 200)
},
closeAllButCurrentDocuments (state, input) {
state.commit("closeAllButCurrentDocuments", input)
setTimeout(() => {
state.commit("resetTreeAction")
}, 200)
},
forceCloseAllButCurrentDocuments (state, input) {
state.commit("forceCloseAllButCurrentDocuments", input)
setTimeout(() => {
state.commit("resetTreeAction")
}, 200)
},
triggerTreeAction (state) {
state.commit("triggerTreeAction")

View file

@ -51,6 +51,30 @@ const mutation: MutationTree<OpenDocumentsStateInterface> = {
state.documents.treeAction = true
},
closeAllDocuments (state: OpenDocumentsStateInterface) {
state.documents.docs = state.documents.docs.filter(doc => doc.hasEdits)
state.documents.treeAction = true
state.documents.timestamp = uid()
},
forceCloseAllDocuments (state: OpenDocumentsStateInterface) {
state.documents.docs = []
state.documents.treeAction = true
state.documents.timestamp = uid()
},
closeAllButCurrentDocuments (state: OpenDocumentsStateInterface, input: I_OpenedDocument) {
state.documents.docs = state.documents.docs.filter(doc => doc.hasEdits || doc._id === input._id)
state.documents.treeAction = true
state.documents.timestamp = uid()
},
forceCloseAllButCurrentDocuments (state: OpenDocumentsStateInterface, input: I_OpenedDocument) {
state.documents.docs = state.documents.docs.filter(doc => doc._id === input._id)
state.documents.treeAction = true
state.documents.timestamp = uid()
},
resetDocuments (state: OpenDocumentsStateInterface) {
state.documents.docs = []
state.documents.treeAction = true

View file

@ -3,6 +3,7 @@ export interface OptionsStateInteface {
_rev?: string,
darkMode: boolean
textShadow: boolean
hideDeadCrossThrough: boolean
doubleDashDocCount: boolean
hideWelcomeScreenSocials: boolean
noTags: boolean
@ -23,6 +24,7 @@ export interface OptionsStateInteface {
invertCategoryPosition: boolean
hideTooltipsStart: boolean
hideTooltipsProject: boolean
hideTreeOrderNumbers: boolean
userKeybindList: any[]
treeWidth?: number
@ -33,6 +35,7 @@ function state (): OptionsStateInteface {
_id: "settings",
darkMode: false,
textShadow: false,
hideDeadCrossThrough: false,
doubleDashDocCount: false,
hideWelcomeScreenSocials: false,
noTags: false,
@ -53,6 +56,7 @@ function state (): OptionsStateInteface {
invertCategoryPosition: false,
hideTooltipsStart: false,
hideTooltipsProject: false,
hideTreeOrderNumbers: false,
treeWidth: 374,
userKeybindList: []
}

View file

@ -1,37 +1,36 @@
- Add "Related notes"
- Add "Predecessors", "Successors", "Date of start", "Date of end" and "How long it lasted" fields to locations and all other groups
- Switch field: Template (sigh... maybe???)
- Save scroll distance when switching tabs (consider some auto-scroll when opening edit mode)
- Mass tag rename
- Add "Related notes"
- Add "Predecessors", "Successors", "Date of start", "Date of end" and "How long it lasted" fields to locations and all other groups
- Add advanced search capabilities to the hierarchical tree
- "Save all" keybind and "Save all and exit" option on the exiting
- Add support for dates in "custom order"... reee
- Add safeguard to escape closing of settings only after something actually got modified
- Add hover/on-demand document preview to relationships
- Floating notes corkboard
- Export for MD/PDF
- Add intelligent responsive design to the left tree and document body (maybe button to pull the left bar in and out?)
- Context menu: Expand all
- Context menu: Collapse all
- Context menu: Copy color (text and BG)
- Context menu: Duplicate
- Context menu: Copy name
- Context menu: Delete
- Context menu: Edit/Open
- Context menu: Create new doc with parent of THIS
- Context menu: Pin tab
- Context menu: Unpin tab
- Pinned tabs (save through program closing)
- Add "Open all search matches" button in the Quick-search that opens a new page with a list of items
- Custom order document types
- Option: Retain opened tabs and their edited contents through sessions
- Option: Single tab option coupled with pinned tabs
- Option: Periodical backup (how many, how often, include files or not)
### Project settings
- Custom order document types
- Pinned tabs (save through program closing)
- Option: Periodical backup (how many, how often, include files or not)
- Add Colors, Renaming and Hiding to default document types per project settings
- Option: Retain opened tabs and their edited contents through sessions
- Option: Single tab option coupled with pinned tabs
- Add safeguard to escape closing of settings only after something actually got modified
- Context menu: Pin tab
- Context menu: Unpin tab
- Add support for dates in "custom order"... reee
- Tag management (coloring)
- Simple data imports (maybe?)
@ -40,7 +39,7 @@
- Add on-the-fly generation of non-existent 2-way relationships
- Automatic thumnail generation AND re-checking based on date
- Automatic thumbnail generation AND re-checking based on date
- Option: Custom background for project
- Check fonts offered in the WYSIWYG and add new
@ -55,5 +54,6 @@
- Allow/Disallow default document types
- Timeline/Calendar support
- AFMG support
- Better color pasting to documents via context menu
- Add printing support
- Add % bar graphs in tree (pinned in #general, idea by popoto)