mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-05-16 02:03:16 +12:00
reworked hierarchical tree and keybinds
This commit is contained in:
parent
bae4b18028
commit
c23cba9f60
|
@ -59,7 +59,7 @@ module.exports = {
|
|||
globals: {
|
||||
ga: false, // Google Analytics
|
||||
cordova: true,
|
||||
__statics: true,
|
||||
|
||||
process: true,
|
||||
Capacitor: true,
|
||||
chrome: true
|
||||
|
@ -72,7 +72,7 @@ module.exports = {
|
|||
// allow paren-less arrow functions
|
||||
'arrow-parens': 'off',
|
||||
'one-var': 'off',
|
||||
|
||||
'brace-style': ["error", "stroustrup"],
|
||||
'import/first': 'off',
|
||||
'import/named': 'error',
|
||||
'import/namespace': 'error',
|
||||
|
|
16
changelog.md
16
changelog.md
|
@ -1,5 +1,20 @@
|
|||
# Changelog
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Bugfixes
|
||||
|
||||
### New features
|
||||
|
||||
- Reworked hierarchical left tree
|
||||
- Added "Add under parent" button the hiearachical tree
|
||||
- Added mouse button and improved keyboard support to the hierarchical tree
|
||||
|
||||
### QoL adjustments
|
||||
|
||||
- Added middle-click closing for the tabs
|
||||
- Reversed default custom sorting for "Order" field in the left side tree
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Bugfixes
|
||||
|
@ -7,6 +22,7 @@
|
|||
- Fixed a bunch of typos
|
||||
- Fixed names not changing with single/multi relatinships if one gets name updated showing on the others properly
|
||||
- Fixed forced lower-case for notes in lists and relashionship fields
|
||||
- Fixed a bug that prevented documents with the same names properly working in the hierarchical tree
|
||||
|
||||
### New features
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ function createWindow () {
|
|||
// More info: https://quasar.dev/quasar-cli/developing-electron-apps/node-integration
|
||||
nodeIntegration: process.env.QUASAR_NODE_INTEGRATION,
|
||||
nodeIntegrationInWorker: process.env.QUASAR_NODE_INTEGRATION,
|
||||
disableBlinkFeatures: "Auxclick",
|
||||
enableRemoteModule: true
|
||||
|
||||
// More info: /quasar-cli/developing-electron-apps/electron-preload-script
|
||||
|
|
33
src/App.vue
33
src/App.vue
|
@ -7,9 +7,40 @@
|
|||
<script lang="ts">
|
||||
import BaseClass from "src/BaseClass"
|
||||
import { Component } from "vue-property-decorator"
|
||||
|
||||
import { defaultKeybinds } from "src/appSettings/defaultKeybinds"
|
||||
@Component
|
||||
export default class App extends BaseClass {
|
||||
created () {
|
||||
window.addEventListener("auxclick", this.reactToMiddleClick)
|
||||
|
||||
document.body.onmousedown = function (e) {
|
||||
if (e.button === 1) {
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
this.registerDefaultKeybinds()
|
||||
}
|
||||
|
||||
destroyed () {
|
||||
window.removeEventListener("auxclick", this.reactToMiddleClick)
|
||||
|
||||
this.deregisterDefaultKeybinds()
|
||||
}
|
||||
|
||||
reactToMiddleClick (e: {button: number, preventDefault: ()=> void}) {
|
||||
if (e.button === 1) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
registerDefaultKeybinds () {
|
||||
defaultKeybinds.forEach(e => this.SSET_registerDefaultKeybind(e))
|
||||
}
|
||||
|
||||
deregisterDefaultKeybinds () {
|
||||
defaultKeybinds.forEach(e => this.SSET_deregisterDefaultKeybind(e))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
205
src/BaseClass.ts
205
src/BaseClass.ts
|
@ -1,3 +1,4 @@
|
|||
import { KeyManagementInterface } from "./store/module-keybinds/state"
|
||||
import { I_OpenedDocument } from "./interfaces/I_OpenedDocument"
|
||||
import { Component, Vue } from "vue-property-decorator"
|
||||
import { namespace } from "vuex-class"
|
||||
|
@ -14,15 +15,120 @@ import { I_Blueprint } from "src/interfaces/I_Blueprint"
|
|||
import { I_NewObjectTrigger } from "src/interfaces/I_NewObjectTrigger"
|
||||
import { uid } from "quasar"
|
||||
import { I_FieldRelationship } from "src/interfaces/I_FieldRelationship"
|
||||
import { I_KeyPressObject } from "src/interfaces/I_KeypressObject"
|
||||
|
||||
const Blueprints = namespace("blueprintsModule")
|
||||
const OpenedDocuments = namespace("openedDocumentsModule")
|
||||
const Keybinds = namespace("keybindsModule")
|
||||
|
||||
@Component
|
||||
export default class BaseClass extends Vue {
|
||||
/****************************************************************/
|
||||
// Keybinds management
|
||||
/****************************************************************/
|
||||
|
||||
@Keybinds.Getter("getCurrentKeyBindData") SGET_getCurrentKeyBindData!: KeyManagementInterface
|
||||
|
||||
@Keybinds.Mutation("registerDefaultKeybind") SSET_registerDefaultKeybind!: (input: I_KeyPressObject) => void
|
||||
@Keybinds.Mutation("deregisterDefaultKeybind") SSET_deregisterDefaultKeybind!: (input: I_KeyPressObject) => void
|
||||
@Keybinds.Mutation("registerUserKeybind") SSET_registerUserKeybind!: (input: I_KeyPressObject) => void
|
||||
@Keybinds.Mutation("deregisterUserKeybind") SSET_deregisterUserKeybind!: (input: I_KeyPressObject) => void
|
||||
@Keybinds.Mutation("updatePressedKey") SSET_updatePressedKey!: (input: I_KeyPressObject) => void
|
||||
|
||||
/**
|
||||
* Builds a humanly redable represetation of the keybind in string form
|
||||
* @param keybindId - Keybind object to build the string out of
|
||||
*/
|
||||
retrieveKeybindString (keybind: I_KeyPressObject): string {
|
||||
let keybindString = ""
|
||||
|
||||
if (keybind.ctrlKey) {
|
||||
keybindString += "CTRL + "
|
||||
}
|
||||
|
||||
if (keybind.altKey) {
|
||||
keybindString += "ALT + "
|
||||
}
|
||||
|
||||
if (keybind.shiftKey) {
|
||||
keybindString += "SHIFT + "
|
||||
}
|
||||
|
||||
const keybinds = [37, 38, 39, 40, 9, 32, 13]
|
||||
|
||||
if (keybinds.includes(keybind.keyCode)) {
|
||||
if (keybind.keyCode === 13) {
|
||||
keybindString += "ENTER"
|
||||
}
|
||||
if (keybind.keyCode === 9) {
|
||||
keybindString += "TAB"
|
||||
}
|
||||
if (keybind.keyCode === 32) {
|
||||
keybindString += "SPACE"
|
||||
}
|
||||
if (keybind.keyCode === 37) {
|
||||
keybindString += "LEFT ARROW"
|
||||
}
|
||||
if (keybind.keyCode === 38) {
|
||||
keybindString += "UP ARROW"
|
||||
}
|
||||
if (keybind.keyCode === 39) {
|
||||
keybindString += "RIGHT ARROW"
|
||||
}
|
||||
if (keybind.keyCode === 40) {
|
||||
keybindString += "DOWN ARROW"
|
||||
}
|
||||
}
|
||||
else {
|
||||
keybindString += String.fromCharCode(keybind.keyCode)
|
||||
}
|
||||
|
||||
if (keybind.note) {
|
||||
keybindString += `<div class="text-italic keybindNote">${keybind.note}</div>`
|
||||
}
|
||||
|
||||
return keybindString
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the keybind triggered the proper condition
|
||||
* @param keybindId - ID of the keybind to determine what to match
|
||||
*/
|
||||
determineKeyBind (keybindId: string): boolean {
|
||||
const currentKeybindData = this.SGET_getCurrentKeyBindData
|
||||
|
||||
const currentKeyPress = currentKeybindData.currentKeyPress
|
||||
const pairedDefaultKeybind = currentKeybindData.defaults.find(e => e.id === keybindId)
|
||||
const pairedCustomKeybind = currentKeybindData.userKeybinds.find(e => e.id === keybindId)
|
||||
|
||||
// Kill the script if no keybind exists of this anywhere
|
||||
if (!pairedDefaultKeybind) {
|
||||
return false
|
||||
}
|
||||
|
||||
const fieldToCheck = (pairedCustomKeybind) || pairedDefaultKeybind
|
||||
|
||||
if (
|
||||
currentKeyPress.altKey === fieldToCheck.altKey &&
|
||||
currentKeyPress.ctrlKey === fieldToCheck.ctrlKey &&
|
||||
currentKeyPress.shiftKey === fieldToCheck.shiftKey &&
|
||||
currentKeyPress.keyCode === fieldToCheck.keyCode
|
||||
) {
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// Project management
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Creates a brand new project and deleted any present data avaiable right now
|
||||
* @param projectName The name of the new project
|
||||
*/
|
||||
async createNewProject (projectName: string) {
|
||||
await this.removeCurrentProject()
|
||||
|
||||
|
@ -39,18 +145,22 @@ export default class BaseClass extends Vue {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an file dialog asking the use for location where to export the project
|
||||
* @param projectName The name of the project to export
|
||||
*/
|
||||
exportProject (projectName: string) {
|
||||
/*eslint-disable */
|
||||
remote.dialog.showOpenDialog({
|
||||
properties: ["openDirectory"]
|
||||
}).then(async (result) => {
|
||||
/*eslint-disable */
|
||||
const folderPath = result.filePaths[0]
|
||||
|
||||
PouchDB.plugin(replicationStream.plugin)
|
||||
//@ts-ignore
|
||||
// @ts-ignore
|
||||
PouchDB.adapter("writableStream", replicationStream.adapters.writableStream)
|
||||
|
||||
//@ts-ignore
|
||||
// @ts-ignore
|
||||
const allDBS = await indexedDB.databases()
|
||||
|
||||
const DBnames: string[] = allDBS.map((db: {name: string}) => {
|
||||
|
@ -65,18 +175,21 @@ export default class BaseClass extends Vue {
|
|||
}
|
||||
const ws = fs.createWriteStream(`${folderPath}/${projectName}/${db}.txt`)
|
||||
|
||||
//@ts-ignore
|
||||
// @ts-ignore
|
||||
await CurrentDB.dump(ws)
|
||||
}
|
||||
/* eslint-enable */
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the current project and all its data
|
||||
*/
|
||||
async removeCurrentProject () {
|
||||
/*eslint-disable */
|
||||
//@ts-ignore
|
||||
// @ts-ignore
|
||||
const allDBS = await indexedDB.databases()
|
||||
|
||||
const DBnames: string[] = allDBS.map((db: {name: string}) => {
|
||||
|
@ -140,10 +253,17 @@ export default class BaseClass extends Vue {
|
|||
@Blueprints.Mutation("setAllBlueprints") SSET_allBlueprints!: (input: I_Blueprint[]) => void
|
||||
@Blueprints.Mutation("setBlueprint") SSET_blueprint!: (input: I_Blueprint) => void
|
||||
|
||||
addNewObjectType (e: I_NewObjectTrigger) {
|
||||
// console.log(e.id)
|
||||
/**
|
||||
* Generates a brand new route for the new object with individual ID
|
||||
* @param newObject A new object to be creared
|
||||
*/
|
||||
addNewObjectRoute (newObject: I_NewObjectTrigger) {
|
||||
const parentID = (newObject?.parent) || ""
|
||||
|
||||
this.$router.push({ path: `/project/display-content/${e._id}/${uid()}` }).catch((e: {name: string}) => {
|
||||
this.$router.push({
|
||||
path: `/project/display-content/${newObject._id}/${uid()}`,
|
||||
query: { parent: parentID }
|
||||
}).catch((e: {name: string}) => {
|
||||
const errorName : string = e.name
|
||||
if (errorName === "NavigationDuplicated") {
|
||||
return
|
||||
|
@ -152,8 +272,12 @@ export default class BaseClass extends Vue {
|
|||
})
|
||||
}
|
||||
|
||||
openExistingDocument (e:I_OpenedDocument | I_FieldRelationship) {
|
||||
this.$router.push({ path: e.url }).catch((e: {name: string}) => {
|
||||
/**
|
||||
* Open a new route for an already existing object
|
||||
* @param existingObject An already existing object passed in
|
||||
*/
|
||||
openExistingDocumentRoute (existingObject:I_OpenedDocument | I_FieldRelationship) {
|
||||
this.$router.push({ path: existingObject.url }).catch((e: {name: string}) => {
|
||||
const errorName : string = e.name
|
||||
if (errorName === "NavigationDuplicated") {
|
||||
return
|
||||
|
@ -173,43 +297,74 @@ export default class BaseClass extends Vue {
|
|||
@OpenedDocuments.Mutation("updateDocument") SSET_updateOpenedDocument!: (input: I_OpenedDocument) => void
|
||||
@OpenedDocuments.Mutation("removeDocument") SSET_removeOpenedDocument!: (input: I_OpenedDocument) => void
|
||||
|
||||
retrieveFieldValue (fieldDataWrapper: I_OpenedDocument, fieldID: string) : string | [] | false | I_FieldRelationship {
|
||||
const fieldData = fieldDataWrapper?.extraFields
|
||||
if (!fieldData) { return false }
|
||||
/**
|
||||
* Retrieves value of requested field. If the field doesn't exist, returns false instead
|
||||
* @param document - Document object that is expected to contain the field
|
||||
* @param fieldID - ID of the field to check
|
||||
*/
|
||||
retrieveFieldValue (document: I_OpenedDocument, fieldID: string) : string | number | [] | false | I_FieldRelationship {
|
||||
const fieldData = document?.extraFields
|
||||
|
||||
// Fizzle if field doesnt exist
|
||||
if (!fieldData) {
|
||||
return false
|
||||
}
|
||||
const fieldValue = fieldData.find(f => f.id === fieldID)?.value as unknown as string
|
||||
return fieldValue
|
||||
}
|
||||
|
||||
retrieveFieldLength (fieldDataWrapper: I_OpenedDocument, fieldID: string) : number | false {
|
||||
/*eslint-disable */
|
||||
const fieldData = fieldDataWrapper?.extraFields
|
||||
if (!fieldData) { return false }
|
||||
const fieldValueLength = fieldData.find(f => f.id === fieldID)?.value.length as unknown as number
|
||||
return fieldValueLength
|
||||
/* eslint-enable */
|
||||
/**
|
||||
* Retrieves array length of requested field. If the field doesn't exist or isn't array, returns false instead
|
||||
* @param document - Document object that is expected to contain the field
|
||||
* @param fieldID - ID of the field to check
|
||||
*/
|
||||
retrieveFieldLength (document: I_OpenedDocument, fieldID: string) : number | false {
|
||||
const fieldData = document?.extraFields
|
||||
|
||||
// Fizzle if field doesnt exist
|
||||
if (!fieldData) {
|
||||
return false
|
||||
}
|
||||
const fieldValue = fieldData.find(f => f.id === fieldID)?.value
|
||||
|
||||
// Fizzle if the value isn't an array
|
||||
if (!Array.isArray(fieldValue)) {
|
||||
return false
|
||||
}
|
||||
return fieldValue.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the route
|
||||
*/
|
||||
refreshRoute () {
|
||||
const remainingDocuments = this.SGET_allOpenedDocuments.docs
|
||||
|
||||
// Assuming there are any documents in the current list
|
||||
if (remainingDocuments.length > 0) {
|
||||
const lastDocument = remainingDocuments[remainingDocuments.length - 1]
|
||||
const currentRoute = this.$router.currentRoute.path
|
||||
|
||||
const existingDocument = this.SGET_allOpenedDocuments.docs.find(e => {
|
||||
return e.url === currentRoute
|
||||
})
|
||||
|
||||
// Prevent infite route cycling by checking if this actually exists in the open tabs
|
||||
if (existingDocument) { return }
|
||||
if (existingDocument) {
|
||||
return
|
||||
}
|
||||
|
||||
// Load a new route if the new route isnt the one we are already on
|
||||
const newRoute = `/project/display-content/${lastDocument.type}/${lastDocument._id}`
|
||||
if (currentRoute !== newRoute) {
|
||||
this.$router.push({ path: newRoute }).catch(e => console.log(e))
|
||||
}
|
||||
} else {
|
||||
}
|
||||
// If there are no documents inthe list, just navigate to the front page of the project
|
||||
else {
|
||||
this.$router.push({ path: "/project" }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") { console.log(e) }
|
||||
if (e && e.name !== "NavigationDuplicated") {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
171
src/appSettings/defaultKeybinds.ts
Normal file
171
src/appSettings/defaultKeybinds.ts
Normal file
|
@ -0,0 +1,171 @@
|
|||
export const defaultKeybinds = [
|
||||
|
||||
// Open keybind cheatsheet - CTRL + ALT + K
|
||||
{
|
||||
altKey: true,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 75,
|
||||
editable: true,
|
||||
id: "openKeybindsCheatsheet",
|
||||
tooltip: "Open keybind cheatsheet"
|
||||
},
|
||||
|
||||
// Quick new document - CTRL + N
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 78,
|
||||
editable: true,
|
||||
id: "quickNewDocument",
|
||||
tooltip: "Quick-add new document"
|
||||
},
|
||||
|
||||
// Quick existing document - CTRL + Q
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 81,
|
||||
editable: true,
|
||||
id: "quickExistingDocument",
|
||||
tooltip: "Quick-search existing document"
|
||||
},
|
||||
|
||||
// Focus left tree search - CTRL + SHIFT + Q
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
keyCode: 81,
|
||||
editable: true,
|
||||
id: "focusHierarchicalTree",
|
||||
tooltip: "Focus search field in the left hierarchical tree"
|
||||
},
|
||||
|
||||
// Clear input in the left tree search - CTRL + SHIFT + W
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
keyCode: 87,
|
||||
editable: true,
|
||||
id: "clearInputHierarchicalTree",
|
||||
tooltip: "Clears any input in the search field in the left hierarchical tree"
|
||||
},
|
||||
|
||||
// Close tab - CTRL + W
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 87,
|
||||
editable: true,
|
||||
id: "closeTab",
|
||||
tooltip: "Close active document"
|
||||
},
|
||||
|
||||
// Next tab - ALT + RIGHT ARROW
|
||||
{
|
||||
altKey: true,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
keyCode: 39,
|
||||
editable: true,
|
||||
id: "nextTab",
|
||||
tooltip: "Next tab"
|
||||
},
|
||||
|
||||
// Previous tab - ALT + LEFT ARROW
|
||||
{
|
||||
altKey: true,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
keyCode: 37,
|
||||
editable: true,
|
||||
id: "previousTab",
|
||||
tooltip: "Previous tab"
|
||||
},
|
||||
|
||||
// Save document - CTRL + S
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 83,
|
||||
editable: true,
|
||||
id: "saveDocument",
|
||||
tooltip: "Save active document"
|
||||
},
|
||||
|
||||
// Edit document - CTRL + E
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 69,
|
||||
editable: true,
|
||||
id: "editDocument",
|
||||
tooltip: "Edit active document"
|
||||
},
|
||||
|
||||
// Delete document - CTRL + D
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: true,
|
||||
shiftKey: false,
|
||||
keyCode: 68,
|
||||
editable: true,
|
||||
id: "deleteDocument",
|
||||
tooltip: "Delete active document"
|
||||
},
|
||||
|
||||
// Next focus - Tab
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
keyCode: 9,
|
||||
editable: false,
|
||||
id: "nextFocus",
|
||||
tooltip: "Focuses next input field/input element/hierarchical tree node",
|
||||
note: "(functionality is the same as when using a web-browser)"
|
||||
},
|
||||
|
||||
// Previous focus - Shift + Tab
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: true,
|
||||
keyCode: 9,
|
||||
editable: false,
|
||||
id: "previousFocus",
|
||||
tooltip: "Focuses previous input field/input element/hierarchical tree node",
|
||||
note: "(functionality is the same as when using a web-browser)"
|
||||
},
|
||||
|
||||
// Open document coresponding to the tre node - Enter
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
keyCode: 13,
|
||||
editable: false,
|
||||
id: "openTreeNode",
|
||||
tooltip: "Open the focused document in the left hierarchical tree",
|
||||
note: "(while the hierarchical tree item is focused)"
|
||||
},
|
||||
|
||||
// Collapse/Expand hiararchical tree node - Space
|
||||
{
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
shiftKey: false,
|
||||
keyCode: 32,
|
||||
editable: false,
|
||||
id: "collapseExpandeTreeNode",
|
||||
tooltip: "Collapse or open the focused category in the left hierarchical tree",
|
||||
note: "(while the hierarchical tree item is focused)"
|
||||
}
|
||||
]
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<q-tree
|
||||
class="objectTree q-pa-sm"
|
||||
:nodes="treeList"
|
||||
:nodes="hierarchicalTree"
|
||||
node-key="key"
|
||||
no-connectors
|
||||
ref="tree"
|
||||
|
@ -21,16 +21,19 @@
|
|||
:selected.sync="selectedTreeNode"
|
||||
>
|
||||
<template v-slot:default-header="prop">
|
||||
<div class="row items-center col-grow">
|
||||
<div class="row items-center col-grow" @click.stop.prevent="processNodeClick(prop.node)">
|
||||
<q-icon
|
||||
:style="`color: ${prop.node.color}; width: 22px !important;`"
|
||||
:size="(prop.node.icon.includes('fas')? '16px': '21px')"
|
||||
:name="prop.node.icon"
|
||||
class="q-mr-sm" />
|
||||
<div class="documentLabel" :style="`color: ${prop.node.color}`">
|
||||
<div class="documentLabel"
|
||||
:style="`color: ${prop.node.color}`"
|
||||
@click.stop.prevent.middle="processNodeLabelMiddleClick(prop.node)"
|
||||
>
|
||||
{{ prop.node.label }}
|
||||
<span
|
||||
class="text-primary text-weight-medium"
|
||||
class="text-primary text-weight-medium q-ml-xs"
|
||||
v-if="prop.node.isRoot">
|
||||
({{prop.node.documentCount}})
|
||||
</span>
|
||||
|
@ -45,11 +48,41 @@
|
|||
Order priority of the document
|
||||
</q-tooltip>
|
||||
</q-badge>
|
||||
</div>
|
||||
<q-tooltip v-if="prop.node.specialLabel">
|
||||
Add new {{ prop.node.specialLabel }}
|
||||
</q-tooltip>
|
||||
<div class="treeButtonGroup">
|
||||
<q-btn
|
||||
tabindex="-1"
|
||||
v-if="!prop.node.specialLabel || prop.node.isRoot"
|
||||
round
|
||||
dense
|
||||
color="primary"
|
||||
class="z-1 q-ml-sm treeButton treeButton--add"
|
||||
icon="mdi-plus"
|
||||
size="8px"
|
||||
@click.stop.prevent="processNodeNewDocumentButton(prop.node)"
|
||||
>
|
||||
<q-tooltip>
|
||||
Add a new document belonging under {{ prop.node.label }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
<q-btn
|
||||
tabindex="-1"
|
||||
v-if="prop.node.children && prop.node.children.length > 0 && !prop.node.isRoot"
|
||||
round
|
||||
dense
|
||||
color="primary"
|
||||
class="z-1 q-ml-sm treeButton treeButton--edit"
|
||||
icon="mdi-pencil"
|
||||
size="8px"
|
||||
@click.stop.prevent="openExistingDocumentRoute(prop.node)"
|
||||
>
|
||||
<q-tooltip>
|
||||
Open/Edit {{ prop.node.label }}
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</q-tree>
|
||||
|
||||
|
@ -81,68 +114,87 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Watch, Prop } from "vue-property-decorator"
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_NewObjectTrigger } from "src/interfaces/I_NewObjectTrigger"
|
||||
import PouchDB from "pouchdb"
|
||||
import { I_KeyPressObject } from "src/interfaces/I_KeypressObject"
|
||||
import { engageBlueprints, retrieveAllBlueprints } from "src/databaseManager/blueprintManager"
|
||||
// import { cleanDatabases } from "src/databaseManager/cleaner"
|
||||
import { I_Blueprint } from "src/interfaces/I_Blueprint"
|
||||
|
||||
const menuAddNewItem = {
|
||||
icon: "mdi-plus",
|
||||
label: "Add new object type"
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class ObjectTree extends BaseClass {
|
||||
@Prop() readonly pushedKey!: I_KeyPressObject
|
||||
|
||||
@Watch("pushedKey", { deep: true })
|
||||
processKeyPress (keypress: I_KeyPressObject) {
|
||||
// Focus left tree search - CTRL + SHIFT + Q
|
||||
if (keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 81) {
|
||||
// @ts-ignore
|
||||
/****************************************************************/
|
||||
// KEYBINDS MANAGEMENT
|
||||
/****************************************************************/
|
||||
@Watch("SGET_getCurrentKeyBindData", { deep: true })
|
||||
processKeyPush () {
|
||||
// Focus left tree search
|
||||
if (this.determineKeyBind("focusHierarchicalTree")) {
|
||||
const treeFilterDOM = this.$refs.treeFilter as unknown as HTMLInputElement
|
||||
treeFilterDOM.focus()
|
||||
}
|
||||
|
||||
// Clear input in the left tree search - CTRL + SHIFT + W
|
||||
if (keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 87) {
|
||||
// Clear input in the left tree search
|
||||
if (this.determineKeyBind("clearInputHierarchicalTree")) {
|
||||
this.resetTreeFilter()
|
||||
}
|
||||
}
|
||||
|
||||
menuAddNewItem = menuAddNewItem
|
||||
|
||||
treeList: {children: I_ShortenedDocument[], icon: string, label: string}[] = []
|
||||
|
||||
firstTimeExpand = true
|
||||
/****************************************************************/
|
||||
// GENERIC FUNCTIONALITY
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* A resetter for the currently selected node
|
||||
* Load all blueprints and build the tree out of them
|
||||
*/
|
||||
selectedTreeNode = null
|
||||
async created () {
|
||||
// await cleanDatabases()
|
||||
await this.processBluePrints()
|
||||
|
||||
treeFilter = ""
|
||||
// Unfuck the rendering by giving the app some time to load first
|
||||
setTimeout(() => {
|
||||
this.buildCurrentObjectTree().catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// BLUEPRINT MANAGEMENT
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* In case any of the blueprints change, reload the whole tree
|
||||
*/
|
||||
@Watch("SGET_allBlueprints", { deep: true })
|
||||
reactToBluePrintRefresh () {
|
||||
this.buildCurrentObjectTree().catch((e) => { console.log(e) })
|
||||
this.buildCurrentObjectTree().catch((e) => {
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
resetTreeFilter () {
|
||||
this.treeFilter = ""
|
||||
// @ts-ignore
|
||||
const treeFilterDOM = this.$refs.treeFilter as unknown as HTMLInputElement
|
||||
treeFilterDOM.focus()
|
||||
/**
|
||||
* Processes all blueprints and redies the store for population of the app
|
||||
*/
|
||||
async processBluePrints (): Promise<void> {
|
||||
await engageBlueprints()
|
||||
|
||||
const allObjectBlueprints = (await retrieveAllBlueprints()).rows.map((blueprint) => {
|
||||
return blueprint.doc
|
||||
}) as I_Blueprint[]
|
||||
|
||||
this.SSET_allBlueprints(allObjectBlueprints)
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// HIERARCHICAL TREE - HELPERS AND MODELS
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Since we are using the object tree as URLs intead of selecting, this resets the select every time a node is clicked
|
||||
*/
|
||||
|
@ -153,31 +205,94 @@ export default class ObjectTree extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Watch("SGET_allOpenedDocuments", { deep: true })
|
||||
async reactToDocumentListChange () {
|
||||
await this.buildCurrentObjectTree()
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic wrapper for adding of new object types to the tree
|
||||
*/
|
||||
menuAddNewItem = {
|
||||
icon: "mdi-plus",
|
||||
label: "Add new object type"
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all the data for the render in tree
|
||||
*/
|
||||
hierarchicalTree: {children: I_ShortenedDocument[], icon: string, label: string}[] = []
|
||||
|
||||
/**
|
||||
* Determines if the tree should expand fully at first or not
|
||||
*/
|
||||
firstTimeExpand = true
|
||||
|
||||
/**
|
||||
* A resetter for the currently selected node
|
||||
*/
|
||||
selectedTreeNode = null
|
||||
|
||||
/**
|
||||
* Filter model for the tree
|
||||
*/
|
||||
treeFilter = ""
|
||||
|
||||
/**
|
||||
* Resets the tree filter and refocuses the search box
|
||||
*/
|
||||
resetTreeFilter () {
|
||||
this.treeFilter = ""
|
||||
const treeFilterDOM = this.$refs.treeFilter as unknown as HTMLInputElement
|
||||
treeFilterDOM.focus()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// HIERARCHICAL TREE - CONTENT CONSTRUCTION
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Sort the whole tree via alphabetical and custom numeric order
|
||||
* @param input Hierartchical tree object to sort
|
||||
*/
|
||||
sortDocuments (input: I_ShortenedDocument[]) {
|
||||
input
|
||||
|
||||
// Sort by name
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
|
||||
// Sort by custom order
|
||||
.sort((a, b) => {
|
||||
const order1 = a.extraFields.find(e => e.id === "order")?.value
|
||||
const order2 = b.extraFields.find(e => e.id === "order")?.value
|
||||
|
||||
if (order1 < order2) { return 1 }
|
||||
if (order1 > order2) { return -1 }
|
||||
if (order1 > order2) {
|
||||
return 1
|
||||
}
|
||||
if (order1 < order2) {
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
})
|
||||
|
||||
input.forEach((e, i) => {
|
||||
if (e.children.length > 0) { input[i].children = this.sortDocuments(input[i].children) }
|
||||
// Run recursive if the node has any children
|
||||
if (e.children.length > 0) {
|
||||
input[i].children = this.sortDocuments(input[i].children)
|
||||
}
|
||||
})
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds proper hiearachy for flat array of documents
|
||||
* @param input Non-hierarchical tree to build the hiearachy out of
|
||||
*/
|
||||
buildTreeHierarchy (input: I_ShortenedDocument[]) {
|
||||
const map: number[] = []
|
||||
let node
|
||||
|
@ -185,19 +300,22 @@ export default class ObjectTree extends BaseClass {
|
|||
let i
|
||||
|
||||
for (i = 0; i < input.length; i += 1) {
|
||||
map[input[i]._id] = i // initialize the map
|
||||
// Initialize the map
|
||||
map[input[i]._id] = i
|
||||
}
|
||||
|
||||
for (i = 0; i < input.length; i += 1) {
|
||||
node = input[i]
|
||||
if (node.parentDoc !== false) {
|
||||
// if you have dangling branches check that map[node.parentId] exists
|
||||
// If there are any dangling branches check that map[node.parentDoc] exists
|
||||
if (input[map[node.parentDoc]]) {
|
||||
input[map[node.parentDoc]].children.push(node)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
roots.push(node)
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
roots.push(node)
|
||||
}
|
||||
}
|
||||
|
@ -207,10 +325,14 @@ export default class ObjectTree extends BaseClass {
|
|||
return sortedRoots
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a brand new sparkling hearchy tree out of available data
|
||||
*/
|
||||
async buildCurrentObjectTree () {
|
||||
const allBlueprings = this.SGET_allBlueprints
|
||||
const treeObject: any[] = []
|
||||
|
||||
// Process all documents, build hieararchy out of the and sort them via name and custom order
|
||||
for (const blueprint of allBlueprings) {
|
||||
const CurrentObjectDB = new PouchDB(blueprint._id)
|
||||
|
||||
|
@ -229,7 +351,7 @@ export default class ObjectTree extends BaseClass {
|
|||
icon: (isCategory) ? "fas fa-folder-open" : doc.icon,
|
||||
sticker: doc.extraFields.find(e => e.id === "order")?.value,
|
||||
parentDoc: (parentDocID) ? parentDocID._id : false,
|
||||
handler: this.openExistingDocument,
|
||||
handler: this.openExistingDocumentRoute,
|
||||
expandable: true,
|
||||
color: color,
|
||||
type: doc.type,
|
||||
|
@ -253,7 +375,7 @@ export default class ObjectTree extends BaseClass {
|
|||
order: blueprint.order,
|
||||
_id: blueprint._id,
|
||||
key: blueprint._id,
|
||||
handler: this.addNewObjectType,
|
||||
handler: this.addNewObjectRoute,
|
||||
specialLabel: blueprint.nameSingular.toLowerCase(),
|
||||
isRoot: true,
|
||||
documentCount: documentCount,
|
||||
|
@ -262,8 +384,12 @@ export default class ObjectTree extends BaseClass {
|
|||
{
|
||||
label: `Add new ${blueprint.nameSingular.toLowerCase()}`,
|
||||
icon: "mdi-plus",
|
||||
handler: this.addNewObjectType,
|
||||
_id: blueprint._id
|
||||
handler: this.addNewObjectRoute,
|
||||
children: false,
|
||||
key: `${blueprint._id}_add`,
|
||||
_id: blueprint._id,
|
||||
specialLabel: blueprint.nameSingular.toLowerCase()
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -271,6 +397,7 @@ export default class ObjectTree extends BaseClass {
|
|||
treeObject.push(treeRow)
|
||||
}
|
||||
|
||||
// Sort the top level of the blueprints
|
||||
treeObject.sort((a, b) => {
|
||||
if (a.order < b.order) {
|
||||
return 1
|
||||
|
@ -282,36 +409,89 @@ export default class ObjectTree extends BaseClass {
|
|||
return 0
|
||||
})
|
||||
|
||||
this.treeList = treeObject
|
||||
// Assign the finished object to the render model
|
||||
this.hierarchicalTree = treeObject
|
||||
|
||||
// Expand all on first load
|
||||
if (this.firstTimeExpand) {
|
||||
this.firstTimeExpand = false
|
||||
// await this.$nextTick()
|
||||
// this.$refs.tree.expandAll()
|
||||
}
|
||||
console.log(treeObject)
|
||||
}
|
||||
|
||||
async created () {
|
||||
// await cleanDatabases()
|
||||
await this.processBluePrints()
|
||||
|
||||
setTimeout(() => {
|
||||
this.buildCurrentObjectTree().catch((e) => { console.log(e) })
|
||||
}, 1000)
|
||||
processNodeNewDocumentButton (node: {
|
||||
key: string
|
||||
_id: string
|
||||
children: []
|
||||
type: string
|
||||
isRoot: boolean
|
||||
specialLabel: string|boolean
|
||||
}) {
|
||||
// If this is top level blueprint
|
||||
if (node.isRoot) {
|
||||
// @ts-ignore
|
||||
this.addNewObjectRoute(node)
|
||||
}
|
||||
// If this is a custom document
|
||||
else {
|
||||
const routeObject = {
|
||||
_id: node.type,
|
||||
parent: node._id
|
||||
}
|
||||
// @ts-ignore
|
||||
this.addNewObjectRoute(routeObject)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes all blueprints and redies the store for population of the app
|
||||
*/
|
||||
async processBluePrints (): Promise<void> {
|
||||
await engageBlueprints()
|
||||
processNodeLabelMiddleClick (node: {
|
||||
key: string
|
||||
_id: string
|
||||
children: []
|
||||
type: string
|
||||
isRoot: boolean
|
||||
specialLabel: string|boolean
|
||||
}) {
|
||||
this.selectedTreeNode = null
|
||||
|
||||
const allObjectBlueprints = (await retrieveAllBlueprints()).rows.map((blueprint) => {
|
||||
return blueprint.doc
|
||||
}) as I_Blueprint[]
|
||||
if (!node.specialLabel && !node.isRoot) {
|
||||
// @ts-ignore
|
||||
this.openExistingDocumentRoute(node)
|
||||
}
|
||||
else {
|
||||
this.addNewObjectRoute(node)
|
||||
}
|
||||
}
|
||||
|
||||
this.SSET_allBlueprints(allObjectBlueprints)
|
||||
processNodeClick (node: {
|
||||
key: string
|
||||
children: []
|
||||
specialLabel: string|boolean
|
||||
}) {
|
||||
// If this is a category or has children
|
||||
if (node.children.length > 0) {
|
||||
this.expandeCollapseNode(node)
|
||||
}
|
||||
// If this lacks a "special label" - AKA anything that isn't the "Add new XY" node
|
||||
else if (!node.specialLabel) {
|
||||
// @ts-ignore
|
||||
this.openExistingDocumentRoute(node)
|
||||
}
|
||||
// If this lacks a "special label" - AKA if this is the "Add new XY" node
|
||||
else {
|
||||
// @ts-ignore
|
||||
this.addNewObjectRoute(node)
|
||||
}
|
||||
}
|
||||
|
||||
expandeCollapseNode (node: {key: string}) {
|
||||
const treeDOM = this.$refs.tree as unknown as {
|
||||
setExpanded: (key:string, state: boolean)=> void,
|
||||
isExpanded: (key:string)=> boolean
|
||||
}
|
||||
|
||||
const isExpanded = treeDOM.isExpanded(node.key)
|
||||
treeDOM.setExpanded(node.key, !isExpanded)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -319,14 +499,53 @@ export default class ObjectTree extends BaseClass {
|
|||
<style lang="scss">
|
||||
.objectTree {
|
||||
.q-tree__arrow {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
margin-right: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.q-tree__node-header {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.documentLabel {
|
||||
max-width: calc(100% - 30px);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 4px 4px 4px 0;
|
||||
}
|
||||
|
||||
.treeButtonGroup {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
height: fit-content;
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.treeButton {
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&--add {
|
||||
.q-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&--edit {
|
||||
.q-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.q-icon {
|
||||
color: $dark;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,28 +11,28 @@
|
|||
elevated
|
||||
class="bg-dark text-cultured"
|
||||
>
|
||||
<q-dialog
|
||||
v-if="currentlyCheckedDocument"
|
||||
v-model="documentCloseDialogConfirm"
|
||||
persistent>
|
||||
<q-card>
|
||||
<q-card-section class="row items-center">
|
||||
<span class="q-ml-sm">Discard changes to {{retrieveFieldValue(currentlyCheckedDocument,'name')}}?</span>
|
||||
</q-card-section>
|
||||
<q-dialog
|
||||
v-if="currentlyCheckedDocument"
|
||||
v-model="documentCloseDialogConfirm"
|
||||
persistent>
|
||||
<q-card>
|
||||
<q-card-section class="row items-center">
|
||||
<span class="q-ml-sm">Discard changes to {{retrieveFieldValue(currentlyCheckedDocument,'name')}}?</span>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Discard changes"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="closeDocument(currentlyCheckedDocument)" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Discard changes"
|
||||
color="primary"
|
||||
v-close-popup
|
||||
@click="closeDocument(currentlyCheckedDocument)" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<q-tabs
|
||||
<q-tabs
|
||||
align="left"
|
||||
inline-label
|
||||
class="tabsWrapper"
|
||||
|
@ -45,7 +45,8 @@
|
|||
leave-active-class="animated fadeOut"
|
||||
appear
|
||||
:duration="300">
|
||||
<q-route-tab
|
||||
|
||||
<q-route-tab
|
||||
:ripple="false"
|
||||
v-for="document in localDocuments"
|
||||
:to="`/project/display-content/${document.type}/${document._id}`"
|
||||
|
@ -55,6 +56,7 @@
|
|||
:style="`color: ${retrieveFieldValue(document,'documentColor')}`"
|
||||
:alert="document.hasEdits"
|
||||
alert-icon="mdi-feather"
|
||||
@click.prevent.middle="checkForCloseOpenedDocument(document)"
|
||||
>
|
||||
<q-btn
|
||||
round
|
||||
|
@ -67,6 +69,7 @@
|
|||
@click.stop.prevent="checkForCloseOpenedDocument(document)"
|
||||
/>
|
||||
</q-route-tab>
|
||||
|
||||
</transition-group>
|
||||
</q-tabs>
|
||||
|
||||
|
@ -95,7 +98,8 @@ export default class TppTabs extends BaseClass {
|
|||
this.currentlyCheckedDocument = input
|
||||
if (input.hasEdits) {
|
||||
this.documentCloseDialogConfirm = true
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.closeDocument(input)
|
||||
}
|
||||
}
|
||||
|
@ -120,56 +124,83 @@ export default class TppTabs extends BaseClass {
|
|||
|
||||
@Prop() readonly pushedKey!: I_KeyPressObject
|
||||
|
||||
@Watch("pushedKey", { deep: true })
|
||||
processKeyPress (keypress: I_KeyPressObject) {
|
||||
// Delete dialog - CTRL + W
|
||||
if (!keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 87 && this.localDocuments.length > 0) {
|
||||
const matchingDocument = this.localDocuments.find(e => e.url === this.$route.path)
|
||||
/****************************************************************/
|
||||
// Keybind handling
|
||||
/****************************************************************/
|
||||
|
||||
if (matchingDocument) {
|
||||
this.checkForCloseOpenedDocument(matchingDocument)
|
||||
}
|
||||
/**
|
||||
* React to keypresses passed from the parent document
|
||||
*/
|
||||
@Watch("SGET_getCurrentKeyBindData", { deep: true })
|
||||
processKeyPush () {
|
||||
// Delete dialog
|
||||
if (this.determineKeyBind("closeTab") && this.localDocuments.length > 0) {
|
||||
this.closeTab()
|
||||
}
|
||||
|
||||
// Next tab - ALT + RIGHT ARROW
|
||||
if (!keypress.shiftKey && !keypress.ctrlKey && keypress.altKey && keypress.keyCode === 39 && this.localDocuments.length > 0) {
|
||||
let index = -1
|
||||
const matchingDocument = this.localDocuments.find((e, i) => {
|
||||
index = i
|
||||
return e.url === this.$route.path
|
||||
})
|
||||
|
||||
if (matchingDocument && index !== this.localDocuments.length - 1) {
|
||||
this.$router.push({ path: this.localDocuments[index + 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") { console.log(e) }
|
||||
})
|
||||
}
|
||||
if (matchingDocument && index === this.localDocuments.length - 1) {
|
||||
this.$router.push({ path: this.localDocuments[0].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") { console.log(e) }
|
||||
})
|
||||
}
|
||||
// Next tab
|
||||
if (this.determineKeyBind("nextTab") && this.localDocuments.length > 0) {
|
||||
this.goToNextTab()
|
||||
}
|
||||
|
||||
// Previous tab - ALT + LEFT ARROW
|
||||
if (!keypress.shiftKey && !keypress.ctrlKey && keypress.altKey && keypress.keyCode === 37 && this.localDocuments.length > 0) {
|
||||
let index = -1
|
||||
const matchingDocument = this.localDocuments.find((e, i) => {
|
||||
index = i
|
||||
return e.url === this.$route.path
|
||||
// Previous tab
|
||||
if (this.determineKeyBind("previousTab") && this.localDocuments.length > 0) {
|
||||
this.goToPreviousTab()
|
||||
}
|
||||
}
|
||||
|
||||
closeTab () {
|
||||
const matchingDocument = this.localDocuments.find(e => e.url === this.$route.path)
|
||||
|
||||
if (matchingDocument) {
|
||||
this.checkForCloseOpenedDocument(matchingDocument)
|
||||
}
|
||||
}
|
||||
|
||||
goToNextTab () {
|
||||
let index = -1
|
||||
const matchingDocument = this.localDocuments.find((e, i) => {
|
||||
index = i
|
||||
return e.url === this.$route.path
|
||||
})
|
||||
|
||||
if (matchingDocument && index !== this.localDocuments.length - 1) {
|
||||
this.$router.push({ path: this.localDocuments[index + 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (matchingDocument && index === this.localDocuments.length - 1) {
|
||||
this.$router.push({ path: this.localDocuments[0].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingDocument && index !== 0) {
|
||||
this.$router.push({ path: this.localDocuments[index - 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") { console.log(e) }
|
||||
})
|
||||
}
|
||||
goToPreviousTab () {
|
||||
let index = -1
|
||||
const matchingDocument = this.localDocuments.find((e, i) => {
|
||||
index = i
|
||||
return e.url === this.$route.path
|
||||
})
|
||||
|
||||
if (matchingDocument && index === 0) {
|
||||
this.$router.push({ path: this.localDocuments[this.localDocuments.length - 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") { console.log(e) }
|
||||
})
|
||||
}
|
||||
if (matchingDocument && index !== 0) {
|
||||
this.$router.push({ path: this.localDocuments[index - 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (matchingDocument && index === 0) {
|
||||
this.$router.push({ path: this.localDocuments[this.localDocuments.length - 1].url }).catch((e: {name: string}) => {
|
||||
if (e && e.name !== "NavigationDuplicated") {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,11 @@ import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
|||
export default class Field_List extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
@Prop({ default: () => { return [] } }) readonly inputDataValue!: {
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: {
|
||||
value: string
|
||||
affix?: string
|
||||
}[]
|
|
@ -30,7 +30,7 @@
|
|||
:key="single._id"
|
||||
clickable
|
||||
class="text-primary"
|
||||
@click="openExistingDocument(single)">
|
||||
@click="openExistingDocumentRoute(single)">
|
||||
<q-item-section>
|
||||
{{single.label}}
|
||||
<span class="inline-block q-ml-xs text-italic connectionNote">
|
||||
|
@ -116,7 +116,11 @@ import { I_FieldRelationship, I_RelationshipPair } from "src/interfaces/I_FieldR
|
|||
export default class Field_SingleRelationship extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
@Prop({ default: () => { return [] } }) readonly inputDataValue!: I_RelationshipPair
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: I_RelationshipPair
|
||||
|
||||
@Prop({ default: "" }) readonly currentId!: ""
|
||||
|
||||
|
@ -225,7 +229,8 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
if (!allObjectsWithoutCurrent.find(e => e._id === s._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput.splice(index, 1)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const matchedFieldContent = allObjectsWithoutCurrent.find(e => e._id === s._id)
|
||||
|
||||
if (matchedFieldContent) {
|
|
@ -62,7 +62,11 @@ import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
|||
export default class Field_MultiSelect extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
@Prop({ default: [] }) readonly inputDataValue!: []
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: []
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
<q-item
|
||||
clickable
|
||||
class="text-primary"
|
||||
@click="openExistingDocument(localInput)">
|
||||
@click="openExistingDocumentRoute(localInput)">
|
||||
<q-item-section>
|
||||
{{localInput.label}}
|
||||
<span class="inline-block q-ml-xs text-italic connectionNote">
|
||||
|
@ -227,7 +227,8 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
if (!objectsWithoutCurrent.find(e => e._id === this.localInput._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput = ""
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const matchedFieldContent = objectsWithoutCurrent.find(e => e._id === this.localInput._id)
|
||||
if (matchedFieldContent) {
|
||||
this.localInput.label = matchedFieldContent.label
|
|
@ -51,7 +51,8 @@ export const engageBlueprints = async () => {
|
|||
try {
|
||||
// Try adding a brand new data blueprint
|
||||
await BlueprintsDB.put(newBlueprint)
|
||||
} catch (e) {
|
||||
}
|
||||
catch (e) {
|
||||
// Proceed with checking of the contents of the blueprint if it already exists
|
||||
const currentBlueprint = await BlueprintsDB.get(newBlueprint._id) as I_Blueprint
|
||||
const hasChanges = checkBlueprintUpdate(newBlueprint, currentBlueprint)
|
||||
|
@ -79,7 +80,9 @@ export const checkBlueprintUpdate = (newBlueprint: I_Blueprint, currentBlueprint
|
|||
newBlueprint?.nameSingular !== currentBlueprint?.nameSingular ||
|
||||
newBlueprint?.icon !== currentBlueprint?.icon ||
|
||||
_.isEqual(newBlueprint.extraFields, currentBlueprint.extraFields) === false
|
||||
) { hasChanges = true }
|
||||
) {
|
||||
hasChanges = true
|
||||
}
|
||||
|
||||
return hasChanges
|
||||
}
|
||||
|
|
|
@ -16,19 +16,49 @@ export const cleanDatabases = async () => {
|
|||
activeDB.info().then((result) => {
|
||||
originalTableSize = result.doc_count
|
||||
|
||||
activeDB.replicate.to(cleanedDB, { filter: function (doc: {_deleted: boolean}) { if (doc._deleted) { return false } else { return doc } } }).on("complete", function () {
|
||||
activeDB.replicate.to(cleanedDB, {
|
||||
filter: function (doc: {_deleted: boolean}) {
|
||||
if (doc._deleted) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
return doc
|
||||
}
|
||||
}
|
||||
}).on("complete", function () {
|
||||
cleanedDB.info().then((cleanedResult) => {
|
||||
cleanedTableSize = cleanedResult.doc_count
|
||||
if (cleanedTableSize === originalTableSize) {
|
||||
activeDB.destroy().then(() => {
|
||||
activeDB = new PouchDB(blueprint._id)
|
||||
cleanedDB.replicate.to(activeDB, { filter: function (doc: {_deleted: boolean}) { if (doc._deleted) { return false } else { return doc } } }).on("complete", function () {
|
||||
cleanedDB.destroy().catch((err) => { console.log(err) })
|
||||
}).catch((err) => { console.log(err) })
|
||||
}).catch((err) => { console.log(err) })
|
||||
cleanedDB.replicate.to(activeDB, {
|
||||
filter: function (doc: {_deleted: boolean}) {
|
||||
if (doc._deleted) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
return doc
|
||||
}
|
||||
}
|
||||
}).on("complete", function () {
|
||||
cleanedDB.destroy().catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
}).catch((err) => { console.log(err) })
|
||||
}).catch((err) => { console.log(err) })
|
||||
}).catch((err) => { console.log(err) })
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -201,7 +201,12 @@ export const many_removeRelationShipFromAnotherObject = async (
|
|||
|
||||
const PairedObjectDB = new PouchDB(typeToFind)
|
||||
let pairedDocument = false as unknown as I_OpenedDocument
|
||||
try { pairedDocument = await PairedObjectDB.get(idToFind) } catch (e) { return pairedDocument }
|
||||
try {
|
||||
pairedDocument = await PairedObjectDB.get(idToFind)
|
||||
}
|
||||
catch (e) {
|
||||
return pairedDocument
|
||||
}
|
||||
|
||||
const pairedField = previousValue.pairedField
|
||||
const pairedFieldIndex = pairedDocument.extraFields.findIndex(e => e.id === pairedField)
|
||||
|
|
|
@ -3,4 +3,8 @@ export interface I_KeyPressObject {
|
|||
ctrlKey: boolean
|
||||
shiftKey: boolean
|
||||
keyCode: number
|
||||
editable?: boolean
|
||||
id?: string
|
||||
tooltip?: string
|
||||
note? :string
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export interface I_NewObjectTrigger {
|
||||
label?: string
|
||||
icon?: string
|
||||
parent?: string
|
||||
handler?: (e: I_NewObjectTrigger) => void
|
||||
_id: string
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<h6 class="text-center q-my-sm">Keybind list</h6>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<q-card-section>
|
||||
<q-markup-table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -21,69 +21,9 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-left">Focuses next input field/input element/hierarchical tree node</td>
|
||||
<td class="text-left">TAB <br> <div class="text-italic keybindNote">(functionality is the same as when using a web-browser)</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Focuses previous input field/input element/hierarchical tree node</td>
|
||||
<td class="text-left">SHFIT + TAB <br> <div class="text-italic keybindNote">(functionality is the same as when using a web-browser)</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Open the focused document in the left hierarchical tree</td>
|
||||
<td class="text-left">SHIFT + TAB <br> <div class="text-italic keybindNote">(while the hierarchical tree item is focused)</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Open keybind cheatsheet</td>
|
||||
<td class="text-left">CTRL + ALT + K</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Focus search field in the left hierarchical tree</td>
|
||||
<td class="text-left">CTRL + SHIFT + Q</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Clears any inpuit in the search field in the left hierarchical tree</td>
|
||||
<td class="text-left">CTRL + SHIFT + W</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Open the focused document in the left hierarchical tree</td>
|
||||
<td class="text-left">ENTER <br> <div class="text-italic keybindNote">(while the hierarchical tree item is focused)</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Collapse or open the focused category in the left hierarchical tree</td>
|
||||
<td class="text-left">SPACE <br> <div class="text-italic keybindNote">(while the hierarchical tree item is focused)</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Quick-search existing document</td>
|
||||
<td class="text-left">CTRL + Q</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Quick-add new document</td>
|
||||
<td class="text-left">CTRL + N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Next tab</td>
|
||||
<td class="text-left">ALT + RIGHT ARROW</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Previous tab</td>
|
||||
<td class="text-left">ALT + LEFT ARROW</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Close active document</td>
|
||||
<td class="text-left">CTRL + W</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Delete active document</td>
|
||||
<td class="text-left">CTRL + D</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Edit active document</td>
|
||||
<td class="text-left">CTRL + E</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-left">Save active document</td>
|
||||
<td class="text-left">CTRL + S</td>
|
||||
<tr v-for="keybind in SGET_getCurrentKeyBindData.defaults" :key="keybind.id">
|
||||
<td class="text-left" v-html="keybind.tooltip"/>
|
||||
<td class="text-left" v-html="retrieveKeybindString(keybind)"/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</q-markup-table>
|
||||
|
@ -199,12 +139,11 @@
|
|||
content-class="bg-dark text-cultured sideWrapper"
|
||||
v-model="leftDrawerOpen"
|
||||
side="left"
|
||||
:width=375
|
||||
show-if-above
|
||||
>
|
||||
|
||||
<objectTree
|
||||
:pushed-key="pushedKey"
|
||||
/>
|
||||
<objectTree/>
|
||||
|
||||
<q-page-sticky position="bottom-right" class="controlButtons">
|
||||
|
||||
|
@ -242,9 +181,7 @@
|
|||
</q-drawer>
|
||||
|
||||
<!-- Header -->
|
||||
<topTabs
|
||||
:pushed-key="pushedKey"
|
||||
/>
|
||||
<topTabs/>
|
||||
|
||||
<!-- Right drawer -->
|
||||
<q-drawer
|
||||
|
@ -261,7 +198,7 @@
|
|||
appear
|
||||
:duration="300"
|
||||
>
|
||||
<router-view :key="$route.path" :pushed-key="pushedKey" />
|
||||
<router-view :key="$route.path" />
|
||||
</transition>
|
||||
</q-page-container>
|
||||
|
||||
|
@ -270,13 +207,12 @@
|
|||
|
||||
<script lang="ts">
|
||||
|
||||
import { Component } from "vue-property-decorator"
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
import BaseClass from "src/BaseClass"
|
||||
import PouchDB from "pouchdb"
|
||||
|
||||
import objectTree from "src/components/ObjectTree.vue"
|
||||
import topTabs from "src/components/TopTabs.vue"
|
||||
import { I_KeyPressObject } from "src/interfaces/I_KeypressObject"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
|
||||
interface NewObjectDocument {
|
||||
|
@ -294,7 +230,23 @@ export default class MainLayout extends BaseClass {
|
|||
leftDrawerOpen = true
|
||||
rightDrawerOpen = false
|
||||
|
||||
pushedKey = {} as I_KeyPressObject
|
||||
@Watch("SGET_getCurrentKeyBindData", { deep: true })
|
||||
processKeyPush () {
|
||||
// Keybind cheatsheet
|
||||
if (this.determineKeyBind("openKeybindsCheatsheet")) {
|
||||
this.keyBindsDialog = true
|
||||
}
|
||||
|
||||
// Quick new document
|
||||
if (this.determineKeyBind("quickNewDocument")) {
|
||||
this.populateNewObjectDialog()
|
||||
}
|
||||
|
||||
// Quick open existing document
|
||||
if (this.determineKeyBind("quickExistingDocument")) {
|
||||
this.populateExistingObjectDialog().catch(e => console.log(e))
|
||||
}
|
||||
}
|
||||
|
||||
created () {
|
||||
window.addEventListener("keyup", this.triggerKeyPush)
|
||||
|
@ -306,7 +258,9 @@ export default class MainLayout extends BaseClass {
|
|||
|
||||
// @ts-ignore
|
||||
triggerKeyPush (e) {
|
||||
if (this.newDocumentDialog || this.existingDocumentDialog || this.keyBindsDialog) { return false }
|
||||
if (this.newDocumentDialog || this.existingDocumentDialog || this.keyBindsDialog) {
|
||||
return false
|
||||
}
|
||||
if (e?.altKey === true || e?.ctrlKey || e?.shiftKey) {
|
||||
const ouputKeycombo = {
|
||||
altKey: e.altKey,
|
||||
|
@ -314,33 +268,13 @@ export default class MainLayout extends BaseClass {
|
|||
shiftKey: e.shiftKey,
|
||||
keyCode: e.keyCode
|
||||
}
|
||||
this.pushedKey = ouputKeycombo
|
||||
|
||||
this.processKeyPush()
|
||||
this.SSET_updatePressedKey(ouputKeycombo)
|
||||
}
|
||||
}
|
||||
|
||||
newDocumentDialog = false
|
||||
|
||||
processKeyPush () {
|
||||
const currentKey = this.pushedKey
|
||||
|
||||
// New document - CTRL + ALT + K
|
||||
if (!currentKey.shiftKey && currentKey.ctrlKey && currentKey.altKey && currentKey.keyCode === 75) {
|
||||
this.keyBindsDialog = true
|
||||
}
|
||||
|
||||
// New document - CTRL + N
|
||||
if (!currentKey.shiftKey && currentKey.ctrlKey && !currentKey.altKey && currentKey.keyCode === 78) {
|
||||
this.populateNewObjectDialog()
|
||||
}
|
||||
|
||||
// Open existing document - CTRL + Q
|
||||
if (!currentKey.shiftKey && currentKey.ctrlKey && !currentKey.altKey && currentKey.keyCode === 81) {
|
||||
this.populateExistingObjectDialog().catch(e => console.log(e))
|
||||
}
|
||||
}
|
||||
|
||||
newObjectList = [] as NewObjectDocument[]
|
||||
|
||||
newDocumentModel = null
|
||||
|
@ -406,7 +340,7 @@ export default class MainLayout extends BaseClass {
|
|||
|
||||
triggerNewInput (e: NewObjectDocument) {
|
||||
this.newDocumentDialog = false
|
||||
this.addNewObjectType(e)
|
||||
this.addNewObjectRoute(e)
|
||||
this.newDocumentModel = null
|
||||
}
|
||||
|
||||
|
@ -490,7 +424,7 @@ export default class MainLayout extends BaseClass {
|
|||
openExistingInput (e: I_ShortenedDocument) {
|
||||
this.existingDocumentDialog = false
|
||||
// @ts-ignore
|
||||
this.openExistingDocument(e)
|
||||
this.openExistingDocumentRoute(e)
|
||||
this.existingDocumentModel = null
|
||||
}
|
||||
|
||||
|
|
|
@ -4,167 +4,167 @@
|
|||
>
|
||||
<div class="row justify-start q-col-gutter-x-xl">
|
||||
|
||||
<q-dialog
|
||||
v-model="deleteConfirmationDialog"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section class="row items-center">
|
||||
<span class="q-ml-sm">Are you sure want to delete <b>{{retrieveFieldValue(currentData,'name')}}</b>? <br> This action can not be reverted and the data will be lost <b>forever</b>.</span>
|
||||
</q-card-section>
|
||||
<q-dialog
|
||||
v-model="deleteConfirmationDialog"
|
||||
>
|
||||
<q-card>
|
||||
<q-card-section class="row items-center">
|
||||
<span class="q-ml-sm">Are you sure want to delete <b>{{retrieveFieldValue(currentData,'name')}}</b>? <br> This action can not be reverted and the data will be lost <b>forever</b>.</span>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Delete"
|
||||
color="red"
|
||||
v-close-popup
|
||||
@click="deleteDocument()" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
||||
<q-btn
|
||||
flat
|
||||
label="Delete"
|
||||
color="red"
|
||||
v-close-popup
|
||||
@click="deleteDocument()" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<div class="col-12 flex justify-end q-mb-xl q-mt-md">
|
||||
<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"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="!currentData.isNew"
|
||||
color="red"
|
||||
:label="`Delete ${bluePrintData.nameSingular}`"
|
||||
@click="openDeleteDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="`col-${field.sizing} q-mb-md`"
|
||||
v-for="field in bluePrintData.extraFields"
|
||||
:key="field.id"
|
||||
>
|
||||
|
||||
<Field_Break
|
||||
class="inputWrapper break"
|
||||
v-if="field.type === 'break' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
<div class="col-12 flex justify-end q-mb-lg q-mt-md">
|
||||
<q-btn
|
||||
color="primary"
|
||||
:label="`Save ${bluePrintData.nameSingular}`"
|
||||
@click="saveDocument"
|
||||
class="q-mr-xl"
|
||||
v-if="editMode"
|
||||
/>
|
||||
|
||||
<Field_Text
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'text' && retrieveFieldValue(currentData,field.id) || field.type === 'text' && retrieveFieldLength(currentData,field.id) === 0) && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
<q-btn
|
||||
color="primary"
|
||||
:label="`Edit ${bluePrintData.nameSingular}`"
|
||||
@click="toggleEditMode"
|
||||
class="q-mr-xl"
|
||||
v-if="!editMode"
|
||||
/>
|
||||
|
||||
<Field_Number
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'number' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
<q-btn
|
||||
v-if="!currentData.isNew"
|
||||
color="red"
|
||||
:label="`Delete ${bluePrintData.nameSingular}`"
|
||||
@click="openDeleteDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Field_Switch
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'switch' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<div
|
||||
:class="`col-${field.sizing} q-mb-md`"
|
||||
v-for="field in bluePrintData.extraFields"
|
||||
:key="field.id"
|
||||
>
|
||||
|
||||
<Field_ColorPicker
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'colorPicker' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_Break
|
||||
class="inputWrapper break"
|
||||
v-if="field.type === 'break' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
/>
|
||||
|
||||
<Field_List
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'list' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_Text
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'text' && retrieveFieldValue(currentData,field.id) || field.type === 'text' && retrieveFieldLength(currentData,field.id) === 0) && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_SingleSelect
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'singleSelect' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_Number
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'number' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_MultiSelect
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'multiSelect' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_Switch
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'switch' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_SingleRelationship
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'singleToNoneRelationship' || field.type === 'singleToSingleRelationship' || field.type === 'singleToManyRelationship') && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_ColorPicker
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'colorPicker' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_MultiRelationship
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'manyToNoneRelationship' || field.type ===
|
||||
'manyToSingleRelationship' || field.type === 'manyToManyRelationship') && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_List
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'list' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_Wysiwyg
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'wysiwyg' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="(retrieveFieldValue(currentData, field.id)) ? retrieveFieldValue(currentData, field.id) : ''"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
<Field_SingleSelect
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'singleSelect' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<Field_MultiSelect
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'multiSelect' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_SingleRelationship
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'singleToNoneRelationship' || field.type === 'singleToSingleRelationship' || field.type === 'singleToManyRelationship') && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_MultiRelationship
|
||||
class="inputWrapper"
|
||||
v-if="(field.type === 'manyToNoneRelationship' || field.type ===
|
||||
'manyToSingleRelationship' || field.type === 'manyToManyRelationship') && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="retrieveFieldValue(currentData, field.id)"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
<Field_Wysiwyg
|
||||
class="inputWrapper"
|
||||
v-if="field.type === 'wysiwyg' && fieldLimiter(field.id)"
|
||||
:inputDataBluePrint="field"
|
||||
:inputDataValue="(retrieveFieldValue(currentData, field.id)) ? retrieveFieldValue(currentData, field.id) : ''"
|
||||
:isNew="currentData.isNew"
|
||||
:editMode="editMode"
|
||||
:current-id="currentData._id"
|
||||
@signal-input="reactToFieldUpdate($event, field)"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -172,7 +172,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Watch, Prop } from "vue-property-decorator"
|
||||
import { Component, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
|
@ -181,21 +181,20 @@ import { I_OpenedDocument } from "src/interfaces/I_OpenedDocument"
|
|||
import PouchDB from "pouchdb"
|
||||
// import { cleanDatabases } from "src/databaseManager/cleaner"
|
||||
import { single_changeRelationshipToAnotherObject, many_changeRelationshipToAnotherObject } from "src/databaseManager/relationshipManager"
|
||||
import { I_KeyPressObject } from "src/interfaces/I_KeypressObject"
|
||||
|
||||
import { extend } from "quasar"
|
||||
|
||||
import Field_Break from "src/components/Field_Break.vue"
|
||||
import Field_Text from "src/components/Field_Text.vue"
|
||||
import Field_Number from "src/components/Field_Number.vue"
|
||||
import Field_Switch from "src/components/Field_Switch.vue"
|
||||
import Field_ColorPicker from "src/components/Field_ColorPicker.vue"
|
||||
import Field_List from "src/components/Field_List.vue"
|
||||
import Field_SingleSelect from "src/components/Field_SingleSelect.vue"
|
||||
import Field_MultiSelect from "src/components/Field_MultiSelect.vue"
|
||||
import Field_SingleRelationship from "src/components/Field_SingleRelationship.vue"
|
||||
import Field_MultiRelationship from "src/components/Field_MultiRelationship.vue"
|
||||
import Field_Wysiwyg from "src/components/Field_Wysiwyg.vue"
|
||||
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"
|
||||
import Field_Switch from "src/components/fields/Field_Switch.vue"
|
||||
import Field_ColorPicker from "src/components/fields/Field_ColorPicker.vue"
|
||||
import Field_List from "src/components/fields/Field_List.vue"
|
||||
import Field_SingleSelect from "src/components/fields/Field_SingleSelect.vue"
|
||||
import Field_MultiSelect from "src/components/fields/Field_MultiSelect.vue"
|
||||
import Field_SingleRelationship from "src/components/fields/Field_SingleRelationship.vue"
|
||||
import Field_MultiRelationship from "src/components/fields/Field_MultiRelationship.vue"
|
||||
import Field_Wysiwyg from "src/components/fields/Field_Wysiwyg.vue"
|
||||
import console from "console"
|
||||
|
||||
@Component({
|
||||
|
@ -226,12 +225,18 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
// Check if the objects exists in a database
|
||||
const CurrentObjectDB = new PouchDB(this.$route.params.type)
|
||||
let retrievedObject = false as unknown as I_OpenedDocument
|
||||
try { retrievedObject = await CurrentObjectDB.get(this.$route.params.id) } catch (error) {}
|
||||
try {
|
||||
retrievedObject = await CurrentObjectDB.get(this.$route.params.id)
|
||||
}
|
||||
catch (error) {}
|
||||
if (!retrievedObject) {
|
||||
const snapshot: I_OpenedDocument[] = extend(true, [], this.SGET_allOpenedDocuments.docs)
|
||||
retrievedObject = snapshot.find(s => this.$route.params.id === s._id) as unknown as I_OpenedDocument
|
||||
if (retrievedObject?.isNew || retrievedObject?.editMode) { this.editMode = true }
|
||||
} else {
|
||||
if (retrievedObject?.isNew || retrievedObject?.editMode) {
|
||||
this.editMode = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
retrievedObject = (this.SGET_openedDocument(retrievedObject._id)) ? this.SGET_openedDocument(retrievedObject._id) : retrievedObject
|
||||
this.editMode = (this.SGET_openedDocument(retrievedObject._id)?.hasEdits || this.SGET_openedDocument(retrievedObject._id)?.editMode)
|
||||
}
|
||||
|
@ -239,9 +244,11 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
// Either create a new document or load existing one
|
||||
this.currentData = (retrievedObject) ? extend(true, [], retrievedObject) : this.createNewDocumentObject()
|
||||
|
||||
const objectFields = this.checkObjectFields()
|
||||
const objectFields = await this.checkObjectFields()
|
||||
|
||||
if (!objectFields) { return }
|
||||
if (!objectFields) {
|
||||
return
|
||||
}
|
||||
|
||||
this.currentData.extraFields = objectFields
|
||||
|
||||
|
@ -390,13 +397,17 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const CurrentObjectDB = new PouchDB(this.$route.params.type)
|
||||
|
||||
let currentDocument = false as unknown as I_OpenedDocument
|
||||
try { currentDocument = await CurrentObjectDB.get(this.$route.params.id) } catch (error) {}
|
||||
try {
|
||||
currentDocument = await CurrentObjectDB.get(this.$route.params.id)
|
||||
}
|
||||
catch (error) {}
|
||||
|
||||
let documentCopy = {} as unknown as I_OpenedDocument
|
||||
if (currentDocument) {
|
||||
documentCopy = extend(true, {}, this.currentData)
|
||||
documentCopy._rev = currentDocument?._rev
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
documentCopy = extend(true, {}, this.currentData)
|
||||
}
|
||||
|
||||
|
@ -470,22 +481,25 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
|
||||
editMode = false
|
||||
|
||||
@Prop() readonly pushedKey!: I_KeyPressObject
|
||||
|
||||
@Watch("pushedKey", { deep: true })
|
||||
processKeyPress (keypress: I_KeyPressObject) {
|
||||
// Save document - CTRL + S
|
||||
if (this.editMode && !keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 83) {
|
||||
this.saveDocument().catch(e => { console.log(e) })
|
||||
/**
|
||||
* 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.editMode && !keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 69) {
|
||||
if (this.determineKeyBind("editDocument") && !this.editMode) {
|
||||
this.toggleEditMode()
|
||||
}
|
||||
|
||||
// Delete dialog - CTRL + D
|
||||
if (keypress.ctrlKey && !keypress.shiftKey && keypress.ctrlKey && !keypress.altKey && keypress.keyCode === 68) {
|
||||
if (this.determineKeyBind("deleteDocument")) {
|
||||
this.openDeleteDialog()
|
||||
}
|
||||
}
|
||||
|
@ -500,7 +514,10 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
const CurrentObjectDB = new PouchDB(this.$route.params.type)
|
||||
|
||||
let currentDocument = false as unknown as I_OpenedDocument
|
||||
try { currentDocument = await CurrentObjectDB.get(this.$route.params.id) } catch (error) {}
|
||||
try {
|
||||
currentDocument = await CurrentObjectDB.get(this.$route.params.id)
|
||||
}
|
||||
catch (error) {}
|
||||
|
||||
const documentCopy: I_OpenedDocument = extend(true, {}, this.currentData)
|
||||
documentCopy._rev = currentDocument?._rev
|
||||
|
@ -528,15 +545,19 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
return this.SGET_blueprint(this.$route.params.type)
|
||||
}
|
||||
|
||||
checkObjectFields () {
|
||||
async checkObjectFields () {
|
||||
const currentExtraFields = (this.currentData && this.currentData.extraFields) ? this.currentData.extraFields : []
|
||||
|
||||
const blueprint = this.retrieveDocumentBlueprint()
|
||||
|
||||
if (!blueprint) { return false }
|
||||
if (!blueprint) {
|
||||
return false
|
||||
}
|
||||
|
||||
blueprint.extraFields.forEach(field => {
|
||||
const exists = currentExtraFields.find(f => { return f.id === field.id })
|
||||
for (const field of blueprint.extraFields) {
|
||||
const exists = currentExtraFields.find(f => {
|
||||
return f.id === field.id
|
||||
})
|
||||
|
||||
if (!exists) {
|
||||
if (field.id === "name") {
|
||||
|
@ -546,11 +567,50 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
value: `New ${this.bluePrintData.nameSingular.toLowerCase()}`
|
||||
}
|
||||
)
|
||||
} else {
|
||||
}
|
||||
else if (field.id === "parentDoc") {
|
||||
if (this.$route.query?.parent) {
|
||||
// Check if the objects exists in a database
|
||||
const CurrentObjectDB = new PouchDB(this.$route.params.type)
|
||||
const parentID = this.$route.query.parent as string
|
||||
let retrievedObject = false as unknown as I_OpenedDocument
|
||||
try {
|
||||
retrievedObject = await CurrentObjectDB.get(parentID)
|
||||
}
|
||||
catch (error) {}
|
||||
|
||||
console.log(retrievedObject)
|
||||
|
||||
currentExtraFields.push(
|
||||
{
|
||||
id: "parentDoc",
|
||||
value: {
|
||||
value: {
|
||||
_id: retrievedObject._id,
|
||||
value: retrievedObject._id,
|
||||
type: this.bluePrintData._id,
|
||||
disable: false,
|
||||
url: retrievedObject.url,
|
||||
label: this.retrieveFieldValue(retrievedObject, "name"),
|
||||
pairedField: ""
|
||||
},
|
||||
addedValues: {
|
||||
pairedId: "",
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
else {
|
||||
currentExtraFields.push({ id: field.id, value: "" })
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentExtraFields.push({ id: field.id, value: "" })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return currentExtraFields
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import Vuex from "vuex"
|
|||
|
||||
import blueprintsModule from "./module-blueprints"
|
||||
import openedDocumentsModule from "./module-openedDocuments"
|
||||
import keybindsModule from "./module-keybinds"
|
||||
|
||||
/*
|
||||
* If not building with SSR mode, you can
|
||||
|
@ -26,7 +27,8 @@ export default store(function ({ Vue }) {
|
|||
const Store = new Vuex.Store<StateInterface>({
|
||||
modules: {
|
||||
blueprintsModule,
|
||||
openedDocumentsModule
|
||||
openedDocumentsModule,
|
||||
keybindsModule
|
||||
// example
|
||||
},
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ const mutation: MutationTree<BlueprintStateInterface> = {
|
|||
const index = state.blueprints.findIndex((single: I_Blueprint) => blueprint._id === single._id)
|
||||
if (index !== -1) {
|
||||
state.blueprints[index] = blueprint
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
state.blueprints.push(blueprint)
|
||||
}
|
||||
}
|
||||
|
|
11
src/store/module-keybinds/actions.ts
Normal file
11
src/store/module-keybinds/actions.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { ActionTree } from "vuex"
|
||||
import { StateInterface } from "../index"
|
||||
import { KeybindsStateInterface } from "./state"
|
||||
|
||||
const actions: ActionTree<KeybindsStateInterface, StateInterface> = {
|
||||
// someAction (context) {
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
export default actions
|
11
src/store/module-keybinds/getters.ts
Normal file
11
src/store/module-keybinds/getters.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { GetterTree } from "vuex"
|
||||
import { StateInterface } from "../index"
|
||||
import { KeybindsStateInterface } from "./state"
|
||||
|
||||
const getters: GetterTree<KeybindsStateInterface, StateInterface> = {
|
||||
getCurrentKeyBindData (context) {
|
||||
return context.keyManagement
|
||||
}
|
||||
}
|
||||
|
||||
export default getters
|
16
src/store/module-keybinds/index.ts
Normal file
16
src/store/module-keybinds/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { Module } from "vuex"
|
||||
import { StateInterface } from "../index"
|
||||
import state, { KeybindsStateInterface } from "./state"
|
||||
import actions from "./actions"
|
||||
import getters from "./getters"
|
||||
import mutations from "./mutations"
|
||||
|
||||
const keybindsModule: Module<KeybindsStateInterface, StateInterface> = {
|
||||
namespaced: true,
|
||||
actions,
|
||||
getters,
|
||||
mutations,
|
||||
state
|
||||
}
|
||||
|
||||
export default keybindsModule
|
97
src/store/module-keybinds/mutations.ts
Normal file
97
src/store/module-keybinds/mutations.ts
Normal file
|
@ -0,0 +1,97 @@
|
|||
import { MutationTree } from "vuex"
|
||||
import { KeybindsStateInterface } from "./state"
|
||||
import { I_KeyPressObject } from "./../../interfaces/I_KeypressObject"
|
||||
|
||||
import { uid } from "quasar"
|
||||
|
||||
const resetCurrentKey = () => {
|
||||
return {
|
||||
altKey: true,
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
id: "",
|
||||
keyCode: 99999
|
||||
}
|
||||
}
|
||||
const mutation: MutationTree<KeybindsStateInterface> = {
|
||||
|
||||
registerDefaultKeybind (state: KeybindsStateInterface, input: I_KeyPressObject) {
|
||||
if (!input.id) {
|
||||
return
|
||||
}
|
||||
|
||||
state.keyManagement.currentKeyPress = resetCurrentKey()
|
||||
|
||||
const existingIndex = state.keyManagement.defaults.findIndex(e => e.id === input.id)
|
||||
|
||||
// Ovewrite existing if it exists
|
||||
if (existingIndex > -1) {
|
||||
state.keyManagement.defaults[existingIndex] = input
|
||||
}
|
||||
// Otherwise, add a new one altogether
|
||||
else {
|
||||
state.keyManagement.defaults.push(input)
|
||||
}
|
||||
|
||||
state.keyManagement.timestamp = uid()
|
||||
},
|
||||
|
||||
deregisterDefaultKeybind (state: KeybindsStateInterface, input: I_KeyPressObject) {
|
||||
if (!input.id) {
|
||||
return
|
||||
}
|
||||
|
||||
state.keyManagement.currentKeyPress = resetCurrentKey()
|
||||
|
||||
const existingIndex = state.keyManagement.defaults.findIndex(e => e.id === input.id)
|
||||
// Remove the existing keybind
|
||||
if (existingIndex > -1) {
|
||||
state.keyManagement.defaults.splice(existingIndex, 1)
|
||||
|
||||
state.keyManagement.timestamp = uid()
|
||||
}
|
||||
},
|
||||
|
||||
registerUserKeybind (state: KeybindsStateInterface, input: I_KeyPressObject) {
|
||||
if (!input.id) {
|
||||
return
|
||||
}
|
||||
|
||||
state.keyManagement.currentKeyPress = resetCurrentKey()
|
||||
|
||||
const existingIndex = state.keyManagement.userKeybinds.findIndex(e => e.id === input.id)
|
||||
// Ovewrite existing if it exists
|
||||
if (existingIndex > -1) {
|
||||
state.keyManagement.userKeybinds[existingIndex] = input
|
||||
}
|
||||
// Otherwise, add a new one altogether
|
||||
else {
|
||||
state.keyManagement.userKeybinds.push(input)
|
||||
}
|
||||
|
||||
state.keyManagement.timestamp = uid()
|
||||
},
|
||||
|
||||
deregisterUserKeybind (state: KeybindsStateInterface, input: I_KeyPressObject) {
|
||||
if (!input.id) {
|
||||
return
|
||||
}
|
||||
|
||||
state.keyManagement.currentKeyPress = resetCurrentKey()
|
||||
|
||||
const existingIndex = state.keyManagement.userKeybinds.findIndex(e => e.id === input.id)
|
||||
// Remove the existing keybind
|
||||
if (existingIndex > -1) {
|
||||
state.keyManagement.userKeybinds.splice(existingIndex, 1)
|
||||
|
||||
state.keyManagement.timestamp = uid()
|
||||
}
|
||||
},
|
||||
|
||||
updatePressedKey (state: KeybindsStateInterface, input: I_KeyPressObject) {
|
||||
state.keyManagement.currentKeyPress = input
|
||||
state.keyManagement.timestamp = uid()
|
||||
}
|
||||
}
|
||||
|
||||
export default mutation
|
31
src/store/module-keybinds/state.ts
Normal file
31
src/store/module-keybinds/state.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { I_KeyPressObject } from "./../../interfaces/I_KeypressObject"
|
||||
|
||||
export interface KeybindsStateInterface {
|
||||
keyManagement: KeyManagementInterface
|
||||
}
|
||||
|
||||
export interface KeyManagementInterface {
|
||||
timestamp: string,
|
||||
userKeybinds: I_KeyPressObject[]
|
||||
defaults: I_KeyPressObject[]
|
||||
currentKeyPress: I_KeyPressObject
|
||||
}
|
||||
|
||||
function state (): KeybindsStateInterface {
|
||||
return {
|
||||
keyManagement: {
|
||||
timestamp: "",
|
||||
userKeybinds: [],
|
||||
defaults: [],
|
||||
currentKeyPress: {
|
||||
altKey: true,
|
||||
ctrlKey: true,
|
||||
shiftKey: true,
|
||||
id: "",
|
||||
keyCode: 99999
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default state
|
|
@ -3,9 +3,9 @@
|
|||
- Add on-the-fly generation of non-existent 2-way relationships
|
||||
|
||||
- Add subtabs (character stats, general info, etc)
|
||||
- Add colored backgrounds to documents (along with already existingt colored texts)
|
||||
|
||||
- Custom icons/images to documents
|
||||
- Middle mouse button close tab
|
||||
- Add option to make the command buttons for document sticky (save/delete/edit)
|
||||
- Allow/Disallow default document types
|
||||
- Dark mode
|
||||
|
|
Loading…
Reference in a new issue