mirror of
https://github.com/Elvanos/fantasia-archive.git
synced 2024-06-26 10:00:23 +12:00
0.1.5 - fields refactor
This commit is contained in:
parent
ae54bc6aae
commit
2c11029b56
|
@ -9,26 +9,14 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop } from "vue-property-decorator"
|
||||
import { Component } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Text extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
@Prop({ default: "" }) readonly inputDataValue!: string
|
||||
@Prop() readonly editMode!: boolean
|
||||
@Prop() readonly isNew!: boolean
|
||||
export default class Field_Text extends FieldBase {
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput = ""
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -62,50 +62,45 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_ColorPicker extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_ColorPicker extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: null }) readonly inputDataValue!: string
|
||||
@Prop() readonly editMode!: boolean
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput = ""
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput.trim()
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = this.inputDataValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = ""
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
return this.localInput.trim()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -106,17 +106,20 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
import { extend } from "quasar"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_List extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_List extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
|
@ -126,76 +129,59 @@ export default class Field_List extends BaseClass {
|
|||
affix?: string
|
||||
}[]
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput = [] as {
|
||||
value: string
|
||||
affix?: string
|
||||
}[]
|
||||
|
||||
localExtraInput = []
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue) ? this.inputDataValue : []
|
||||
}
|
||||
|
||||
get inputAffix () {
|
||||
return (this.inputDataBluePrint?.predefinedListExtras?.affix) || ""
|
||||
}
|
||||
|
||||
removeFromList (index: number) {
|
||||
this.localInput.splice(index, 1)
|
||||
this.signalInput()
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = [] as {
|
||||
value: string
|
||||
affix?: string
|
||||
}[]
|
||||
|
||||
/**
|
||||
* Determine if the input has any extra values attached to it or not
|
||||
*/
|
||||
get hasExtraInput () {
|
||||
// @ts-ignore
|
||||
this.localExtraInput = this.inputDataBluePrint?.predefinedListExtras?.extraSelectValueList
|
||||
return this.inputDataBluePrint?.predefinedListExtras?.extraSelectValueList
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
/**
|
||||
* List of extra input values
|
||||
*/
|
||||
localExtraInput:string[] = []
|
||||
|
||||
const dataCopy: {
|
||||
value: string
|
||||
affix?: string
|
||||
}[] = extend(true, [], this.localInput)
|
||||
|
||||
const returnValue = dataCopy.map(e => {
|
||||
e.value = e.value.trim()
|
||||
if (e.affix) {
|
||||
e.affix = e.affix.trim()
|
||||
}
|
||||
return e
|
||||
})
|
||||
|
||||
return returnValue
|
||||
/**
|
||||
* Label for the extra input
|
||||
* EG: "Level" or "Skill tier"
|
||||
*/
|
||||
get inputAffix () {
|
||||
return (this.inputDataBluePrint?.predefinedListExtras?.affix) || ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an existing row from the input list
|
||||
*/
|
||||
removeFromList (index: number) {
|
||||
this.localInput.splice(index, 1)
|
||||
this.signalInput()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new row to the input list
|
||||
*/
|
||||
async addNewInput () {
|
||||
this.localInput.push({
|
||||
value: "",
|
||||
|
@ -214,6 +200,28 @@ export default class Field_List extends BaseClass {
|
|||
|
||||
this.signalInput()
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
const dataCopy: {
|
||||
value: string
|
||||
affix?: string
|
||||
}[] = extend(true, [], this.localInput)
|
||||
|
||||
// Fix hanging whitespaces in inputs
|
||||
const returnValue = dataCopy.map(e => {
|
||||
e.value = e.value.trim()
|
||||
if (e.affix) {
|
||||
e.affix = e.affix.trim()
|
||||
}
|
||||
return e
|
||||
})
|
||||
|
||||
return returnValue
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -79,9 +79,8 @@
|
|||
dark
|
||||
style="flex-grow: 1;"
|
||||
dense
|
||||
@popup-show="reloadAllDocuments"
|
||||
:ref="`multieRelationshipField${this.inputDataBluePrint.id}`"
|
||||
:options="filteredInput"
|
||||
:options="filterList"
|
||||
use-input
|
||||
:outlined="!isDarkMode"
|
||||
:filled="isDarkMode"
|
||||
|
@ -103,6 +102,20 @@
|
|||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt.label) }}
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
class="z-max"
|
||||
style="color: #000 !important;"
|
||||
size="sm"
|
||||
icon="mdi-open-in-new"
|
||||
@click.stop.prevent="openNewTab(scope.opt)"
|
||||
>
|
||||
<q-tooltip :delay="500">
|
||||
Open in new tab without leaving this one
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-chip>
|
||||
</template>
|
||||
<template v-slot:option="{ itemProps, itemEvents, opt }">
|
||||
|
@ -176,45 +189,50 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
import PouchDB from "pouchdb"
|
||||
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
|
||||
import { extend } from "quasar"
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import { I_FieldRelationship, I_RelationshipPair } from "src/interfaces/I_FieldRelationship"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_SingleRelationship extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_MultiRelationship extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: I_RelationshipPair
|
||||
|
||||
/**
|
||||
* ID of the document this field belongs to
|
||||
*/
|
||||
@Prop({ default: "" }) readonly currentId!: ""
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
localInput = [] as unknown as I_FieldRelationship[]
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
textShadow = false
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
this.textShadow = options.textShadow
|
||||
/**
|
||||
* Determines if this is a one or two way relationship
|
||||
*/
|
||||
get isOneWayRelationship () {
|
||||
return (this.inputDataBluePrint.type === "singleToNoneRelationship" || this.inputDataBluePrint.type === "manyToNoneRelationship")
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
* Also reload the local object list
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue?.value) ? this.inputDataValue.value : []
|
||||
|
@ -227,32 +245,54 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
/**
|
||||
* Reload the local object list based on blueprint changes
|
||||
*/
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
/**
|
||||
* Reload the local object list based on current document ID changes
|
||||
*/
|
||||
@Watch("currentId")
|
||||
reactToIDChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
async openNewTab (input: I_FieldRelationship) {
|
||||
const CurrentObjectDB = new PouchDB(input.type)
|
||||
const retrievedObject = await CurrentObjectDB.get(input._id)
|
||||
|
||||
const dataPass = {
|
||||
doc: retrievedObject,
|
||||
treeAction: false
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
extraInput: I_FieldRelationship[] = []
|
||||
filteredInput: I_FieldRelationship[] = []
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = [] as unknown as I_FieldRelationship[]
|
||||
|
||||
/**
|
||||
* List of notes paired to the local input
|
||||
*/
|
||||
inputNotes: { pairedId: string; value: string; }[] = []
|
||||
|
||||
/**
|
||||
* Retrieves note text
|
||||
*/
|
||||
retrieveNoteText (id: string) {
|
||||
const pairedNote = this.inputNotes.find(e => e.pairedId === id)
|
||||
return (pairedNote && pairedNote.value.length > 0) ? `(${pairedNote.value})` : ""
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of all retrieved documents without the current one
|
||||
*/
|
||||
allDocumentsWithoutCurrent: I_ShortenedDocument[] = []
|
||||
|
||||
/**
|
||||
* A copy of the list for the filter feed
|
||||
* A copy is needed here as the list gets modified as the filter returns highlights and similar
|
||||
*/
|
||||
filterList: I_ShortenedDocument[] = []
|
||||
|
||||
/**
|
||||
* Refocus after filtering to avoid un-intuitive focusing
|
||||
*/
|
||||
async refocusSelect () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
|
@ -263,17 +303,14 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
allDocuments: I_ShortenedDocument[] = []
|
||||
|
||||
async reloadAllDocuments () {
|
||||
this.allDocuments = await this.retrieveAllDocuments()
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the document list
|
||||
*/
|
||||
filterSelect (val: string, update: (e: () => void) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
this.filteredInput = this.extraInput
|
||||
if (this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filteredInput.length > 0) {
|
||||
this.filterList = this.allDocumentsWithoutCurrent
|
||||
if (this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
|
@ -282,51 +319,35 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
|
||||
update(() => {
|
||||
const needle = val.toLowerCase()
|
||||
const listCopy : I_ShortenedDocument[] = extend(true, [], this.extraInput)
|
||||
this.filterList = extend(true, [], this.allDocumentsWithoutCurrent)
|
||||
|
||||
// @ts-ignore
|
||||
this.filteredInput = advancedDocumentFilter(needle, listCopy, this.SGET_allBlueprints, this.allDocuments)
|
||||
this.filterList = advancedDocumentFilter(needle, this.filterList, this.SGET_allBlueprints, this.filterList)
|
||||
|
||||
/*eslint-disable */
|
||||
if(this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filteredInput.length > 0){
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
/* eslint-enable */
|
||||
if (this.$refs[`multiRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
retrieveNoteText (id: string) {
|
||||
const pairedNote = this.inputNotes.find(e => e.pairedId === id)
|
||||
return (pairedNote && pairedNote.value.length > 0) ? `(${pairedNote.value})` : ""
|
||||
}
|
||||
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
@Watch("currentId")
|
||||
reactToIDChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get isOneWayRelationship () {
|
||||
return (this.inputDataBluePrint.type === "singleToNoneRelationship" || this.inputDataBluePrint.type === "manyToNoneRelationship")
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the initial loading of the list for filtering and furhter use
|
||||
* Also remove the document itself from the list, checks if connected input fields even exist and altogether formats and clears the list
|
||||
*/
|
||||
async reloadObjectListAndCheckIfValueExists () {
|
||||
if (this.inputDataBluePrint?.relationshipSettings && this.currentId.length > 0) {
|
||||
// Get a list of all objects connected to this field and remap them
|
||||
const CurrentObjectDB = new PouchDB(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
|
||||
const allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows.map(doc => doc.doc)
|
||||
|
||||
const allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows
|
||||
const allDbDocs = allDbObjects.map(doc => doc.doc)
|
||||
|
||||
const allObjects = allDbDocs.map((doc) => {
|
||||
// Map all of the documents to something more digestible for the select
|
||||
const allObjects = allDbObjects.map((doc) => {
|
||||
const objectDoc = doc as unknown as I_ShortenedDocument
|
||||
|
||||
const pairedField = (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
|
||||
let isDisabled = false
|
||||
|
||||
// If the paired field exists and if this is "singleToSingleRelationship", set it as disabled since it is already paired
|
||||
if (pairedField.length > 0) {
|
||||
const pairedFieldObject = objectDoc.extraFields.find(f => f.id === pairedField)
|
||||
|
||||
|
@ -350,52 +371,72 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
pairedField: pairedField,
|
||||
tags: objectDoc.extraFields.find(e => e.id === "tags")?.value,
|
||||
// @ts-ignore
|
||||
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbDocs)
|
||||
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbObjects)
|
||||
|
||||
}
|
||||
}) as unknown as I_FieldRelationship[]
|
||||
}) as unknown as I_ShortenedDocument[]
|
||||
|
||||
const allObjectsWithoutCurrent: I_FieldRelationship[] = allObjects.filter((obj) => obj._id !== this.currentId)
|
||||
// Filter out current object
|
||||
const allObjectsWithoutCurrent: I_ShortenedDocument[] = allObjects.filter((obj) => obj._id !== this.currentId)
|
||||
|
||||
// Do a quick check on formatting of the current input (if something is wrong with it, set it as empty array)
|
||||
this.localInput = (Array.isArray(this.localInput)) ? this.localInput : []
|
||||
|
||||
let nonExistValue = false
|
||||
let needsRefresh = false
|
||||
|
||||
this.localInput.forEach((s, index) => {
|
||||
// Proceed only if the local input is properly set up
|
||||
if (s._id) {
|
||||
// If the matched object doesn't exist in the object, assume it has been deleted or newer existed and silently emit a signal input which auto-updates the document
|
||||
if (!allObjectsWithoutCurrent.find(e => e._id === s._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput.splice(index, 1)
|
||||
nonExistValue = true
|
||||
needsRefresh = true
|
||||
}
|
||||
// If the object does exist, make sure we have the newest available name by reasigning the label if it is different. Then trigger a silent update
|
||||
else {
|
||||
const matchedFieldContent = allObjectsWithoutCurrent.find(e => e._id === s._id)
|
||||
|
||||
if (matchedFieldContent) {
|
||||
if (matchedFieldContent && this.localInput[index].label !== matchedFieldContent.label) {
|
||||
this.localInput[index].label = matchedFieldContent.label
|
||||
needsRefresh = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (nonExistValue) {
|
||||
if (needsRefresh) {
|
||||
this.signalInput(true)
|
||||
}
|
||||
|
||||
const allObjectsWithoutCategories: I_FieldRelationship[] = allObjectsWithoutCurrent.filter((obj) => !obj.isCategory)
|
||||
|
||||
this.extraInput = allObjectsWithoutCategories
|
||||
// Do a last set of filtering
|
||||
this.allDocumentsWithoutCurrent = allObjectsWithoutCurrent.filter((obj) => !obj.isCategory)
|
||||
}
|
||||
}
|
||||
|
||||
checkNotes () {
|
||||
this.localInput.forEach(single => {
|
||||
if (!this.inputNotes.find(e => single._id === e.pairedId)) {
|
||||
this.inputNotes.push({ pairedId: single._id, value: "" })
|
||||
}
|
||||
})
|
||||
/****************************************************************/
|
||||
// FIELD ACTIONS
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Opens a new tab from a connected rleationship
|
||||
*/
|
||||
async openNewTab (input: I_FieldRelationship) {
|
||||
const CurrentObjectDB = new PouchDB(input.type)
|
||||
const retrievedObject = await CurrentObjectDB.get(input._id)
|
||||
|
||||
const dataPass = {
|
||||
doc: retrievedObject,
|
||||
treeAction: false
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput (skipSave?: boolean) {
|
||||
this.checkNotes()
|
||||
|
@ -406,6 +447,17 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
skipSave: (skipSave)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds the note list to match the input relationships
|
||||
*/
|
||||
checkNotes () {
|
||||
this.localInput.forEach(single => {
|
||||
if (!this.inputNotes.find(e => single._id === e.pairedId)) {
|
||||
this.inputNotes.push({ pairedId: single._id, value: "" })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -81,52 +81,60 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_MultiSelect extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_MultiSelect extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: []
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput = []
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue) ? this.inputDataValue : []
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = []
|
||||
|
||||
/**
|
||||
* List of extra input values
|
||||
*/
|
||||
extraInput: string[] = []
|
||||
|
||||
/**
|
||||
* Load data into the extra input
|
||||
*/
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
populateExtraInput () {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
this.extraInput = this.inputDataBluePrint?.predefinedSelectValues
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defocus after filtering to avoid un-intuitive focus
|
||||
*/
|
||||
async defocusSelectRef () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
|
@ -135,13 +143,9 @@ export default class Field_MultiSelect extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
populateExtraInput () {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
this.extraInput = this.inputDataBluePrint?.predefinedSelectValues
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the input list
|
||||
*/
|
||||
filterFn (val: string, update: (fn: any) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
|
@ -162,9 +166,11 @@ export default class Field_MultiSelect extends BaseClass {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,50 +43,45 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Number extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_Number extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: null }) readonly inputDataValue!: null|number
|
||||
@Prop() readonly editMode!: boolean
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput: null|number = null
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = this.inputDataValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput: null|number = null
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
|
|
|
@ -77,9 +77,8 @@
|
|||
style="flex-grow: 1;"
|
||||
dense
|
||||
:ref="`singleRelationshipField${inputDataBluePrint.id}`"
|
||||
:options="filteredInput"
|
||||
:options="filterList"
|
||||
use-input
|
||||
@popup-show="reloadAllDocuments"
|
||||
:outlined="!isDarkMode"
|
||||
:filled="isDarkMode"
|
||||
input-debounce="200"
|
||||
|
@ -92,6 +91,7 @@
|
|||
v-if="scope.opt.label && scope.opt.label.length > 0"
|
||||
removable
|
||||
dense
|
||||
@click="openNewTab(scope.opt)"
|
||||
@remove="scope.removeAtIndex(scope.index)"
|
||||
:tabindex="scope.tabindex"
|
||||
color="accent"
|
||||
|
@ -99,6 +99,20 @@
|
|||
class="text-bold"
|
||||
>
|
||||
{{ stripTags(scope.opt.label) }}
|
||||
<q-btn
|
||||
round
|
||||
dense
|
||||
flat
|
||||
class="z-max"
|
||||
style="color: #000 !important;"
|
||||
size="sm"
|
||||
icon="mdi-open-in-new"
|
||||
@click.stop.prevent="openNewTab(scope.opt)"
|
||||
>
|
||||
<q-tooltip :delay="500">
|
||||
Open in new tab without leaving this one
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-chip>
|
||||
</template>
|
||||
|
||||
|
@ -171,47 +185,56 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
import PouchDB from "pouchdb"
|
||||
import { advancedDocumentFilter } from "src/scripts/utilities/advancedDocumentFilter"
|
||||
import { extend } from "quasar"
|
||||
|
||||
import { I_ShortenedDocument } from "src/interfaces/I_OpenedDocument"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import { I_FieldRelationship, I_RelationshipPairSingle } from "src/interfaces/I_FieldRelationship"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_SingleRelationship extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_SingleRelationship extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: "" }) readonly inputDataValue!: I_RelationshipPairSingle
|
||||
|
||||
/**
|
||||
* ID of the document this field belongs to
|
||||
*/
|
||||
@Prop({ default: "" }) readonly currentId!: ""
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
localInput = "" as unknown as I_FieldRelationship
|
||||
|
||||
inputNote: { pairedId: string; value: string; } = {
|
||||
pairedId: "",
|
||||
value: ""
|
||||
/**
|
||||
* Current field ID
|
||||
* This is used for special handling of the "parentDoc" field used for hiearachical pathing
|
||||
*/
|
||||
get inputFieldID () {
|
||||
return this.inputDataBluePrint?.id
|
||||
}
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
textShadow = false
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
this.textShadow = options.textShadow
|
||||
/**
|
||||
* Determines if this is a one or two way relationship
|
||||
*/
|
||||
get isOneWayRelationship () {
|
||||
return (this.inputDataBluePrint.type === "singleToNoneRelationship" || this.inputDataBluePrint.type === "manyToNoneRelationship")
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
* Also reload the local object list
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
// @ts-ignore
|
||||
|
@ -222,21 +245,57 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
/**
|
||||
* Reload the local object list based on blueprint changes
|
||||
*/
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
/**
|
||||
* Reload the local object list based on current document ID changes
|
||||
*/
|
||||
@Watch("currentId")
|
||||
reactToIDChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get inputFieldID () {
|
||||
return this.inputDataBluePrint?.id
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = "" as unknown as I_FieldRelationship
|
||||
|
||||
/**
|
||||
* A note paired to the local input
|
||||
*/
|
||||
inputNote: { pairedId: string; value: string; } = {
|
||||
pairedId: "",
|
||||
value: ""
|
||||
}
|
||||
|
||||
extraInput: I_FieldRelationship[] = []
|
||||
filteredInput: I_FieldRelationship[] = []
|
||||
/**
|
||||
* Retrieves note text
|
||||
*/
|
||||
retrieveNoteText () {
|
||||
const pairedNote = this.inputNote
|
||||
return (pairedNote && pairedNote.value.length > 0) ? `(${pairedNote.value})` : ""
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of all retrieved documents without the current one
|
||||
*/
|
||||
allDocumentsWithoutCurrent: I_ShortenedDocument[] = []
|
||||
|
||||
/**
|
||||
* A copy of the list for the filter feed
|
||||
* A copy is needed here as the list gets modified as the filter returns highlights and similar
|
||||
*/
|
||||
filterList: I_ShortenedDocument[] = []
|
||||
|
||||
/**
|
||||
* Refocus after filtering to avoid un-intuitive focusing
|
||||
*/
|
||||
async refocusSelect () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
|
@ -247,18 +306,15 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
allDocuments: I_ShortenedDocument[] = []
|
||||
|
||||
async reloadAllDocuments () {
|
||||
this.allDocuments = await this.retrieveAllDocuments()
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the document list
|
||||
*/
|
||||
filterSelect (val: string, update: (e: () => void) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
this.filteredInput = this.extraInput
|
||||
this.filterList = this.allDocumentsWithoutCurrent
|
||||
|
||||
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filteredInput.length > 0) {
|
||||
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
|
@ -267,61 +323,34 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
|
||||
update(() => {
|
||||
const needle = val.toLowerCase()
|
||||
const listCopy : I_ShortenedDocument[] = extend(true, [], this.extraInput)
|
||||
this.filterList = extend(true, [], this.allDocumentsWithoutCurrent)
|
||||
// @ts-ignore
|
||||
this.filteredInput = advancedDocumentFilter(needle, listCopy, this.SGET_allBlueprints, this.allDocuments)
|
||||
this.filterList = advancedDocumentFilter(needle, this.filterList, this.SGET_allBlueprints, this.filterList)
|
||||
|
||||
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filteredInput.length > 0) {
|
||||
if (this.$refs[`singleRelationshipField${this.inputDataBluePrint.id}`] && this.filterList.length > 0) {
|
||||
this.refocusSelect().catch(e => console.log(e))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
retrieveNoteText () {
|
||||
const pairedNote = this.inputNote
|
||||
return (pairedNote && pairedNote.value.length > 0) ? `(${pairedNote.value})` : ""
|
||||
}
|
||||
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
@Watch("currentId")
|
||||
reactToIDChanges () {
|
||||
this.reloadObjectListAndCheckIfValueExists().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get isOneWayRelationship () {
|
||||
return (this.inputDataBluePrint.type === "singleToNoneRelationship" || this.inputDataBluePrint.type === "manyToNoneRelationship")
|
||||
}
|
||||
|
||||
async openNewTab (input: I_FieldRelationship) {
|
||||
const CurrentObjectDB = new PouchDB(input.type)
|
||||
const retrievedObject = await CurrentObjectDB.get(input._id)
|
||||
|
||||
const dataPass = {
|
||||
doc: retrievedObject,
|
||||
treeAction: false
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the initial loading of the list for filtering and furhter use
|
||||
* Also remove the document itself from the list, checks if connected input fields even exist and altogether formats and clears the list
|
||||
*/
|
||||
async reloadObjectListAndCheckIfValueExists () {
|
||||
if (this.inputDataBluePrint?.relationshipSettings && this.currentId.length > 0) {
|
||||
// Get a list of all objects connected to this field and remap them
|
||||
const CurrentObjectDB = new PouchDB(this.inputDataBluePrint.relationshipSettings.connectedObjectType)
|
||||
const allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows.map(doc => doc.doc)
|
||||
|
||||
const allDbObjects = (await CurrentObjectDB.allDocs({ include_docs: true })).rows
|
||||
const allDbDocs = allDbObjects.map(doc => doc.doc)
|
||||
|
||||
const allObjects = allDbDocs.map((doc) => {
|
||||
// Map all of the documents to something more digestible for the select
|
||||
const allObjects = allDbObjects.map((doc) => {
|
||||
const objectDoc = doc as unknown as I_ShortenedDocument
|
||||
|
||||
const pairedField = (this.inputDataBluePrint?.relationshipSettings?.connectedField) || ""
|
||||
let isDisabled = false
|
||||
|
||||
// If the paired field exists and if this is "singleToSingleRelationship", set it as disabled since it is already paired
|
||||
if (pairedField.length > 0) {
|
||||
const pairedFieldObject = objectDoc.extraFields.find(f => f.id === pairedField)
|
||||
const pairingType = this.inputDataBluePrint.type
|
||||
|
@ -345,38 +374,61 @@ export default class Field_SingleRelationship extends BaseClass {
|
|||
pairedField: pairedField,
|
||||
tags: objectDoc.extraFields.find(e => e.id === "tags")?.value,
|
||||
// @ts-ignore
|
||||
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbDocs)
|
||||
hierarchicalPath: this.getDocumentHieararchicalPath(objectDoc, allDbObjects)
|
||||
}
|
||||
}) as unknown as I_FieldRelationship[]
|
||||
}) as unknown as I_ShortenedDocument[]
|
||||
|
||||
// If this is the "parentDoc" field, include categories, otherwise, filter them out from the list
|
||||
const isBelongsUnder = (this.inputDataBluePrint.id === "parentDoc")
|
||||
|
||||
const allObjectsWithoutCategories: I_FieldRelationship[] = allObjects.filter((obj) => !obj.isCategory)
|
||||
|
||||
const objectsWithoutCurrent: I_FieldRelationship[] = (isBelongsUnder)
|
||||
const objectsWithoutCurrent: I_ShortenedDocument[] = (isBelongsUnder)
|
||||
? allObjects.filter((obj) => obj._id !== this.currentId)
|
||||
: allObjectsWithoutCategories.filter((obj) => obj._id !== this.currentId)
|
||||
: allObjects.filter((obj) => obj._id !== this.currentId).filter((obj) => !obj.isCategory)
|
||||
|
||||
// Proceed only if the local input is properly set up
|
||||
if (this.localInput._id) {
|
||||
// If the matched object doesn't exist in the object, assume it has been deleted or newer existed and silently emit a signal input which auto-updates the document
|
||||
if (!objectsWithoutCurrent.find(e => e._id === this.localInput._id)) {
|
||||
// @ts-ignore
|
||||
this.localInput = ""
|
||||
this.signalInput(true)
|
||||
}
|
||||
// If the object does exist, make sure we have the newest available name by reasigning the label if it is different. Then trigger a silent update
|
||||
else {
|
||||
const matchedFieldContent = objectsWithoutCurrent.find(e => e._id === this.localInput._id)
|
||||
if (matchedFieldContent) {
|
||||
if (matchedFieldContent && this.localInput.label !== matchedFieldContent.label) {
|
||||
this.localInput.label = matchedFieldContent.label
|
||||
this.signalInput(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.extraInput = objectsWithoutCurrent
|
||||
this.allDocumentsWithoutCurrent = objectsWithoutCurrent
|
||||
}
|
||||
}
|
||||
|
||||
debounceTimerCheck = false
|
||||
/****************************************************************/
|
||||
// FIELD ACTIONS
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Opens a new tab from a connected rleationship
|
||||
*/
|
||||
async openNewTab (input: I_FieldRelationship) {
|
||||
const CurrentObjectDB = new PouchDB(input.type)
|
||||
const retrievedObject = await CurrentObjectDB.get(input._id)
|
||||
|
||||
const dataPass = {
|
||||
doc: retrievedObject,
|
||||
treeAction: false
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput (skipSave?: boolean) {
|
||||
this.inputNote = (this.localInput !== null) ? this.inputNote : { pairedId: "", value: "" }
|
||||
|
|
|
@ -69,47 +69,56 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_SingleSelect extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_SingleSelect extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: "" }) readonly inputDataValue!: ""
|
||||
@Prop() readonly isNew!: boolean
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput = ""
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue) ? this.inputDataValue : ""
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = ""
|
||||
|
||||
/**
|
||||
* List of extra input values
|
||||
*/
|
||||
extraInput: string[] = []
|
||||
|
||||
/**
|
||||
* Load data into the extra input
|
||||
*/
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
populateExtraInput () {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
this.extraInput = this.inputDataBluePrint?.predefinedSelectValues
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defocus after filtering to avoid un-intuitive focus
|
||||
*/
|
||||
async defocusSelectRef () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
|
@ -118,13 +127,9 @@ export default class Field_SingleSelect extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
populateExtraInput () {
|
||||
if (this.inputDataBluePrint?.predefinedSelectValues) {
|
||||
this.extraInput = this.inputDataBluePrint?.predefinedSelectValues
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the input list
|
||||
*/
|
||||
filterFn (val: string, update: (fn: any) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
|
@ -145,9 +150,11 @@ export default class Field_SingleSelect extends BaseClass {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,49 +26,44 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Switch extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_Switch extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: false }) readonly inputDataValue!: boolean
|
||||
@Prop() readonly editMode!: boolean
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput: null|boolean = null
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (typeof this.inputDataValue === "boolean") ? this.inputDataValue : false
|
||||
}
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput: null|boolean = null
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -73,62 +73,79 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
import { tagListBuildFromBlueprints } from "src/scripts/utilities/tagListBuilder"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Tags extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_Tags extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
}) readonly inputDataValue!: []
|
||||
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
changedInput = false
|
||||
localInput: string[] = []
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = (this.inputDataValue) ? this.inputDataValue : []
|
||||
this.buildTagList().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput: string[] = []
|
||||
|
||||
/**
|
||||
* Add an additional blueprint watch to catch all the changes for the tag refresh to avoid glitches and bugs
|
||||
*/
|
||||
@Watch("inputDataBluePrint", { deep: true, immediate: true })
|
||||
reactToBlueprintChanges () {
|
||||
this.buildTagList().catch(e => console.log(e))
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.tagAlreadyExists = false
|
||||
return this.localInput
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
/****************************************************************/
|
||||
// TAG MANAGEMENT
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* List of all currently existing tags
|
||||
*/
|
||||
allTags: string[] = []
|
||||
|
||||
/**
|
||||
* List of all currently filtered tags
|
||||
*/
|
||||
filteredTags: string[] = []
|
||||
|
||||
/**
|
||||
* Defocus after filtering to avoid un-intuitive focus
|
||||
*/
|
||||
async defocusSelectRef () {
|
||||
await this.$nextTick()
|
||||
/*eslint-disable */
|
||||
|
@ -137,8 +154,14 @@ export default class Field_Tags extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the newly added tag already exists or not
|
||||
*/
|
||||
tagAlreadyExists = false
|
||||
|
||||
/**
|
||||
* Add a new tag value to the list
|
||||
*/
|
||||
addNewValue (val: string) {
|
||||
const formattedNewTag = val.toLowerCase().trim()
|
||||
|
||||
|
@ -164,6 +187,9 @@ export default class Field_Tags extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the tag list
|
||||
*/
|
||||
filterFn (val: string, update: (fn: any) => void) {
|
||||
if (val === "") {
|
||||
update(() => {
|
||||
|
@ -184,15 +210,11 @@ export default class Field_Tags extends BaseClass {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new tag list from all existing tags on all documents across the whole project
|
||||
*/
|
||||
async buildTagList () {
|
||||
this.allTags = await tagListBuildFromBlueprints(this.SGET_allBlueprints)
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.tagAlreadyExists = false
|
||||
this.changedInput = true
|
||||
return this.localInput
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -48,51 +48,59 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Text extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_Text extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: "" }) readonly inputDataValue!: string
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
/**
|
||||
* Determines if the parent document is new or not
|
||||
*/
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = this.inputDataValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the input has any changes on it or not
|
||||
*/
|
||||
changedInput = false
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = ""
|
||||
|
||||
/**
|
||||
* Deletes the placeholder value in the input field
|
||||
*/
|
||||
deletePlaceholder () {
|
||||
this.localInput = ""
|
||||
this.signalInput()
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput.trim()
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe change on the edit mode and in case this field is "name", auto-select it as first field
|
||||
*/
|
||||
@Watch("editMode", { immediate: true })
|
||||
checkForNameFields () {
|
||||
if (this.inputDataBluePrint?.id === "name" && this.editMode === true) {
|
||||
|
@ -110,9 +118,13 @@ export default class Field_Text extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = this.inputDataValue
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput.trim()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -40,51 +40,53 @@
|
|||
<script lang="ts">
|
||||
import { Component, Emit, Prop, Watch } from "vue-property-decorator"
|
||||
|
||||
import BaseClass from "src/BaseClass"
|
||||
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
import FieldBase from "src/components/fields/_FieldBase"
|
||||
|
||||
@Component({
|
||||
components: { }
|
||||
})
|
||||
export default class Field_Wysiwyg extends BaseClass {
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
export default class Field_Wysiwyg extends FieldBase {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Already existing value in the input field (IF one is there right now)
|
||||
*/
|
||||
@Prop({ default: "" }) readonly inputDataValue!: string
|
||||
@Prop() readonly editMode!: boolean
|
||||
@Prop() readonly isNew!: boolean
|
||||
|
||||
changedInput = false
|
||||
localInput = ""
|
||||
|
||||
isDarkMode = false
|
||||
disableDocumentToolTips = false
|
||||
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
const options = this.SGET_options
|
||||
this.isDarkMode = options.darkMode
|
||||
this.disableDocumentToolTips = options.disableDocumentToolTips
|
||||
}
|
||||
|
||||
@Emit()
|
||||
signalInput () {
|
||||
this.changedInput = true
|
||||
return this.localInput.trim()
|
||||
}
|
||||
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
/****************************************************************/
|
||||
// INPUT HANDLING
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Watch changes to the prefilled data already existing in the field and update local input accordingly
|
||||
*/
|
||||
@Watch("inputDataValue", { deep: true, immediate: true })
|
||||
reactToInputChanges () {
|
||||
this.localInput = this.inputDataValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Model for the local input
|
||||
*/
|
||||
localInput = ""
|
||||
|
||||
/**
|
||||
* Signals the input change to the document body parent component
|
||||
*/
|
||||
@Emit()
|
||||
signalInput () {
|
||||
return this.localInput.trim()
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// WYSIWYG FUNCTIONALITY
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Disableds the full-screen edit mode upon cancleling the editing mode
|
||||
*/
|
||||
@Watch("editMode")
|
||||
turnOffFullScreen () {
|
||||
if (!this.editMode && this.$refs[`wysiwygField${this.inputDataBluePrint.id}`]) {
|
||||
|
@ -95,6 +97,9 @@ export default class Field_Wysiwyg extends BaseClass {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips all formatting from CTRL + V pasting
|
||||
*/
|
||||
pasteCapture (evt: any) {
|
||||
/*eslint-disable */
|
||||
|
||||
|
@ -126,10 +131,16 @@ export default class Field_Wysiwyg extends BaseClass {
|
|||
/* eslint-enable */
|
||||
}
|
||||
|
||||
/**
|
||||
* Subsitution strings for toolbar
|
||||
*/
|
||||
definitions = {
|
||||
fullscreen: { label: "Fullscreen" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Font list
|
||||
*/
|
||||
wysiwygFonts = {
|
||||
arial: "Arial",
|
||||
arial_black: "Arial Black",
|
||||
|
@ -141,6 +152,9 @@ export default class Field_Wysiwyg extends BaseClass {
|
|||
verdana: "Verdana"
|
||||
}
|
||||
|
||||
/**
|
||||
* Wysiwyg toolbar ontions
|
||||
*/
|
||||
wysiwygOptions = [
|
||||
["left", "center", "right", "justify"],
|
||||
["bold", "italic", "underline", "subscript", "superscript"],
|
||||
|
|
63
src/components/fields/_FieldBase.ts
Normal file
63
src/components/fields/_FieldBase.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { Component, Prop, Watch } from "vue-property-decorator"
|
||||
import BaseClass from "src/BaseClass"
|
||||
import { I_ExtraFields } from "src/interfaces/I_Blueprint"
|
||||
|
||||
@Component
|
||||
export default class FieldBase extends BaseClass {
|
||||
/****************************************************************/
|
||||
// BASIC FIELD DATA
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* Blueprint data for the specific field
|
||||
*/
|
||||
@Prop({ default: [] }) readonly inputDataBluePrint!: I_ExtraFields
|
||||
|
||||
/**
|
||||
* Determines if the document is curently in edit mode or not
|
||||
*/
|
||||
@Prop() readonly editMode!: boolean
|
||||
|
||||
/**
|
||||
* Field icon defined in the blueprint
|
||||
*/
|
||||
get inputIcon () {
|
||||
return this.inputDataBluePrint?.icon
|
||||
}
|
||||
|
||||
/**
|
||||
* Field tooltip defined in the blueprint
|
||||
*/
|
||||
get toolTip () {
|
||||
return this.inputDataBluePrint?.tooltip
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
// LOCAL SETTINGS
|
||||
/****************************************************************/
|
||||
|
||||
/**
|
||||
* React to changes on the options store
|
||||
*/
|
||||
@Watch("SGET_options", { immediate: true, deep: true })
|
||||
onSettingsChange () {
|
||||
this.isDarkMode = this.SGET_options.darkMode
|
||||
this.disableDocumentToolTips = this.SGET_options.disableDocumentToolTips
|
||||
this.textShadow = this.SGET_options.textShadow
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the text has shadows or not
|
||||
*/
|
||||
textShadow = false
|
||||
|
||||
/**
|
||||
* Determines if this is in dark-mode or not
|
||||
*/
|
||||
isDarkMode = false
|
||||
|
||||
/**
|
||||
* Determines if the tooltips should be disabled or not
|
||||
*/
|
||||
disableDocumentToolTips = false
|
||||
}
|
|
@ -15,9 +15,12 @@
|
|||
- Fixed a typo in `Type of being` field in the `Races/Species` document type
|
||||
- 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 rather peculiar recuring bug that could cause the database to endlessly attempt to update a document while constantly throwing errors
|
||||
|
||||
### New features
|
||||
|
||||
- Added a dedicated button that opens the connected documents straight from the little chips in relationship fields while in edit mode
|
||||
|
||||
### QoL adjustments
|
||||
|
||||
- Updated fullscreen editor looks to work more like a proper document editor
|
||||
|
|
|
@ -365,7 +365,7 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
this.SSET_addOpenedDocument(dataPass)
|
||||
}
|
||||
|
||||
async reactToFieldUpdate (inputData: string, field: I_ExtraFields) {
|
||||
reactToFieldUpdate (inputData: string, field: I_ExtraFields) {
|
||||
// FIELD - Text
|
||||
if (field.type === "text") {
|
||||
this.currentData.hasEdits = true
|
||||
|
@ -474,8 +474,7 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
// @ts-ignore
|
||||
if (inputData.skipSave) {
|
||||
this.currentData.extraFields[indexToUpdate].value.skipSave = false
|
||||
await this.triggerSaveDocument()
|
||||
return
|
||||
dataPass.doc.hasEdits = false
|
||||
}
|
||||
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
|
@ -494,8 +493,7 @@ export default class PageDocumentDisplay extends BaseClass {
|
|||
// @ts-ignore
|
||||
if (inputData.skipSave) {
|
||||
this.currentData.extraFields[indexToUpdate].value.skipSave = false
|
||||
await this.triggerSaveDocument()
|
||||
return
|
||||
dataPass.doc.hasEdits = false
|
||||
}
|
||||
|
||||
this.SSET_updateOpenedDocument(dataPass)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
- Fix custom order sorting in tag groups
|
||||
- Add to "-webkit-app-region: no-drag;" ".q-position-engine"
|
||||
- Add to "-webkit-app-region: no-drag;" ".q-position-engine"
|
||||
|
||||
### ADD DOCS ABOUT BUGGY BUILD FILE
|
||||
|
||||
- Unify "/" style capitals across document fields
|
||||
|
@ -10,7 +11,6 @@
|
|||
- Save scroll distance when switching tabs (consider some auto-scroll when opening edit mode)
|
||||
- Fix lag on opening Quick-search popup
|
||||
- Mass tag rename
|
||||
- Add click-through from chips in edit mode
|
||||
- Add advanced search capabilities to the hierarchical tree
|
||||
- Add "is dead" or some similar switch to documents and show strike-through/etc on items in lists, tombstone icon or overlay crossed out icon
|
||||
- Custom icons/images to documents
|
||||
|
|
Loading…
Reference in a new issue