1.1.0 Added @at links to editors & fullpage search

This commit is contained in:
Elvanos 2023-05-13 18:43:26 +02:00
parent 982fded0b0
commit bea9547e46
18 changed files with 251 additions and 28 deletions

21
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "fantasiaarchive",
"version": "0.1.9",
"version": "0.1.10",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -3314,7 +3314,8 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz",
"integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==",
"dev": true
"dev": true,
"optional": true
},
"boom": {
"version": "2.10.1",
@ -6371,6 +6372,11 @@
"unzip-crx-3": "^0.2.0"
}
},
"electron-find": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/electron-find/-/electron-find-1.0.7.tgz",
"integrity": "sha512-C2FQJuk8567P2a2loBNwl5c8kwOTQVMB0capgHtPI7zKwZG16X0UxG+sNYZExQfnJ0PA+ecECA/4LcXxQa2TCA=="
},
"electron-is-accelerator": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz",
@ -18080,6 +18086,7 @@
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true,
"optional": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
@ -18098,6 +18105,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -18130,6 +18138,7 @@
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true,
"optional": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
@ -18142,6 +18151,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -18196,13 +18206,15 @@
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"dev": true,
"optional": true
},
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
"optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@ -18212,6 +18224,7 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@ -18223,6 +18236,7 @@
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
"optional": true,
"requires": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
@ -18272,6 +18286,7 @@
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"dev": true,
"optional": true,
"requires": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"

View file

@ -1,6 +1,6 @@
{
"name": "fantasiaarchive",
"version": "0.1.9",
"version": "0.1.10",
"description": "A database manager for world building",
"productName": "Fantasia Archive",
"author": "Elvanos <elvanos66@gmail.com>",
@ -18,6 +18,7 @@
"apexcharts": "^3.26.0",
"axios": "^0.27.2",
"core-js": "^3.6.5",
"electron-find": "^1.0.7",
"html-parse-stringify": "^3.0.1",
"json2md": "^1.10.0",
"katex": "^0.12.0",

View file

@ -685,7 +685,6 @@ export default class BaseClass extends Vue {
// @ts-ignore
const url = new URL(link)
// @ts-ignore
console.log(url)
if (url.protocol === "http:" || url.protocol === "https:") {
shell.openExternal(url.href).catch(e => console.log(e))
}

View file

@ -33,6 +33,7 @@ import appControl from "src/components/appHeader/AppControl.vue"
}
})
export default class AppHeader extends BaseClass {
}
</script>

View file

@ -104,6 +104,7 @@
<Field_SingleRelationship
class="inputWrapper"
v-if="(field.type === 'singleToNoneRelationship' || field.type === 'singleToSingleRelationship' || field.type === 'singleToManyRelationship') && categoryFieldFilter(field.id)"
:quickInsertMode="quickInsertMode"
:inputDataBluePrint="field"
:inputDataValue="retrieveFieldValue(localDocument, field.id)"
:isNew="false"
@ -121,6 +122,7 @@
class="inputWrapper"
v-if="(field.type === 'manyToNoneRelationship' || field.type ===
'manyToSingleRelationship' || field.type === 'manyToManyRelationship') && categoryFieldFilter(field.id)"
:quickInsertMode="quickInsertMode"
:inputDataBluePrint="field"
:inputDataValue="retrieveFieldValue(localDocument, field.id)"
:isNew="false"
@ -249,6 +251,7 @@
<Field_SingleRelationship
class="inputWrapper"
v-if="(field.type === 'singleToNoneRelationship' || field.type === 'singleToSingleRelationship' || field.type === 'singleToManyRelationship') && categoryFieldFilter(field.id)"
:quickInsertMode="quickInsertMode"
:inputDataBluePrint="field"
:inputDataValue="retrieveFieldValue(localDocument, field.id)"
:isNew="false"
@ -262,6 +265,7 @@
class="inputWrapper"
v-if="(field.type === 'manyToNoneRelationship' || field.type ===
'manyToSingleRelationship' || field.type === 'manyToManyRelationship') && categoryFieldFilter(field.id)"
:quickInsertMode="quickInsertMode"
:inputDataBluePrint="field"
:inputDataValue="retrieveFieldValue(localDocument, field.id)"
:isNew="false"
@ -313,7 +317,6 @@ 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_Wysiwyg from "src/components/fields/Field_Wysiwyg.vue"
import Field_Tags from "src/components/fields/Field_Tags.vue"
import { extend } from "quasar"
import { I_DocumentTemplate } from "src/interfaces/I_DocumentTemplate"
@ -331,7 +334,7 @@ import { retrieveAllDocumentTemplatesFromDB } from "src/scripts/projectManagemen
Field_MultiSelect,
Field_SingleRelationship: () => import("src/components/fields/Field_SingleRelationship.vue"),
Field_MultiRelationship: () => import("src/components/fields/Field_MultiRelationship.vue"),
Field_Wysiwyg,
Field_Wysiwyg: () => import("src/components/fields/Field_Wysiwyg.vue"),
Field_Tags
}
})
@ -509,6 +512,14 @@ export default class DocumentPreview extends BaseClass {
}, this.customCloseDelay)
}
/**
* Determines if the "quick insert mode is on"
* This prevents the dialog from scrolling up if used within wisywig editors
*/
@Prop({
default: false
}) readonly quickInsertMode!: boolean
/**
* Debounce timer for nice user experience
*/

View file

@ -4,6 +4,10 @@
:class="{'AppControl': !isFrontpage}"
>
<appSearchBox
v-if="fullPageSeachPopupTrigger"
/>
<!-- New document dialog -->
<newDocumentDialog
:dialog-trigger="newObjectDialogTrigger"
@ -581,9 +585,11 @@ import { saveProject } from "src/scripts/projectManagement/projectManagent"
import { toggleDevTools } from "src/scripts/utilities/devTools"
import appLogo from "src/assets/appLogo.png"
import appSearchBox from "src/components/appHeader/AppSearchBox.vue"
@Component({
components: {
appSearchBox,
projectCloseCheckDialog,
keybindCheatsheetDialog,
loadProjectCheckDialog,
@ -654,27 +660,49 @@ export default class AppControl extends BaseClass {
@Watch("SGET_getCurrentKeyBindData", { deep: true })
processKeyPush () {
// Open full page search
if (this.determineKeyBind("openFullPageSearch") && !this.SGET_getDialogsState) {
this.fullPageSeachPopupClose()
setTimeout(() => {
this.fullPageSeachPopupAssignUID()
}, 100)
}
// Keybind cheatsheet
if (this.determineKeyBind("openKeybindsCheatsheet") && !this.SGET_getDialogsState) {
this.keybindsDialogAssignUID()
}
// App options
// Open app options page
if (this.determineKeyBind("openAppOptions") && !this.SGET_getDialogsState) {
this.programSettingsDialogAssignUID()
}
// App options
// Navigate to project overview
if (this.determineKeyBind("navigateToProjectOverview") && this.projectExists && !this.isProjectPage) {
this.navigateToProjectPage()
}
// App options
// Tohhle dev tools
if (this.determineKeyBind("toggleDeveloperTools")) {
this.toggleDevTools()
}
}
/****************************************************************/
// Full page search pop-up
/****************************************************************/
fullPageSeachPopupTrigger: string | false = false
fullPageSeachPopupClose () {
this.fullPageSeachPopupTrigger = false
}
fullPageSeachPopupAssignUID () {
this.fullPageSeachPopupTrigger = this.generateUID()
}
/****************************************************************/
// Navigate to project page action
/****************************************************************/

View file

@ -0,0 +1,84 @@
<template>
<div
class="appSearchBox bg-dark"
>
</div>
</template>
<script lang="ts">
import { Component } from "vue-property-decorator"
import { remote } from "electron"
import BaseClass from "src/BaseClass"
import projectCloseCheckDialog from "src/components/dialogs/ProjectCloseCheck.vue"
// @ts-ignore
import { FindInPage } from "electron-find"
import internal from "stream"
interface I_FindInPage{
openFindWindow: () => void
closeFindWindow: () => void
destroy: () => void
options?: {
preload?: boolean
parentElement?: HTMLElement
duration?: number
offsetTop?: number
offsetRight?: number
boxBgColor?: string
boxShadowColor?: string
inputColor?: string
inputBgColor?: string
inputFocusColor?: string
textColor?: string
textHoverBgColor?: string
caseSelectedColor?: string
}
}
@Component({
components: { projectCloseCheckDialog }
})
export default class AppWindowButtons extends BaseClass {
findInPageInstance = null as unknown as I_FindInPage
findInPageDOM = null as unknown as HTMLElement
mounted () {
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
this.findInPageInstance = new FindInPage(remote.getCurrentWebContents(), {
preload: true,
duration: 0,
parentElement: document.querySelector(".appSearchBox")
})
this.findInPageInstance.openFindWindow()
this.findInPageDOM = document.querySelector(".find-box") as HTMLElement
setTimeout(() => {
setInterval(() => {
if (this.findInPageDOM.style.visibility === "hidden") {
this.findInPageInstance.destroy()
}
}, 100)
}, 350)
}
beforeUnmount () {
this.findInPageInstance.destroy()
}
}
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" >
</style>

View file

@ -57,6 +57,7 @@
>
<documentPreview
v-if="!preventPreviewsPopups"
:quickInsertMode="quickInsertMode"
:document-id="opt._id"
:external-close-trigger="documentPreviewClose"
:special-z-index="999999999"
@ -92,6 +93,7 @@
</q-item-label>
</q-item-section>
<q-btn
v-if="!quickInsertMode"
tabindex="-1"
round
flat
@ -110,6 +112,7 @@
</q-tooltip>
</q-btn>
<q-btn
v-if="!quickInsertMode"
tabindex="-1"
round
flat
@ -130,6 +133,7 @@
</q-tooltip>
</q-btn>
<q-btn
v-if="!quickInsertMode"
tabindex="-1"
round
flat
@ -151,6 +155,7 @@
</q-btn>
<q-menu
v-if="!quickInsertMode"
touch-position
context-menu
auto-close
@ -252,11 +257,10 @@ import { copyDocument } from "src/scripts/documentActions/copyDocument"
import DialogBase from "src/components/dialogs/_DialogBase"
import { I_Blueprint } from "src/interfaces/I_Blueprint"
import documentPreview from "src/components/DocumentPreview.vue"
@Component({
components: {
documentPreview
documentPreview: () => import("src/components/DocumentPreview.vue")
}
})
export default class ExistingDocumentDialog extends DialogBase {
@ -311,6 +315,14 @@ export default class ExistingDocumentDialog extends DialogBase {
this.preventPreviewsPopups = this.SGET_options.preventPreviewsPopups
}
/**
* Determines if the "quick insert mode is on"
* This prevents the dialog from scrolling up if used within wisywig editors
*/
@Prop({
default: false
}) readonly quickInsertMode!: boolean
/**
* Determines if the document previews should be disabled or not
*/
@ -508,8 +520,11 @@ export default class ExistingDocumentDialog extends DialogBase {
// Open document and close dialog
if (!this.disableCloseAftertSelectQuickSearch) {
this.dialogModel = false
if (!this.quickInsertMode) {
// @ts-ignore
this.openExistingDocumentRoute(e)
this.openExistingDocumentRoute(e)
}
this.existingDocumentModel = []
}
// Open document and DO NOT close the dialog
@ -539,8 +554,10 @@ export default class ExistingDocumentDialog extends DialogBase {
// Open document and close dialog
if (!this.disableCloseAftertSelectQuickSearch) {
this.dialogModel = false
if (!this.quickInsertMode) {
// @ts-ignore
this.openExistingDocumentRouteWithEdit(e)
this.openExistingDocumentRouteWithEdit(e)
}
this.existingDocumentModel = []
}
// Open document and DO NOT close the dialog

View file

@ -103,6 +103,7 @@
</q-item-section>
<q-menu
touch-position
context-menu
auto-close
@ -394,6 +395,7 @@
:custom-delay="1500"
/>
<q-menu
v-if="!quickInsertMode"
touch-position
context-menu
auto-close
@ -578,6 +580,14 @@ export default class Field_MultiRelationship extends FieldBase {
@Prop({ default: 999 }) readonly specialZIndex!: number
/**
* Determines if the "quick insert mode is on"
* This prevents the dialog from scrolling up if used within wisywig editors
*/
@Prop({
default: false
}) readonly quickInsertMode!: boolean
/**
* Prevent document preview in already existing previews
*/

View file

@ -94,6 +94,7 @@
</span>
</q-item-section>
<q-menu
v-if="!quickInsertMode"
touch-position
context-menu
auto-close
@ -526,6 +527,14 @@ export default class Field_SingleRelationship extends FieldBase {
@Prop({ default: 999 }) readonly specialZIndex!: number
/**
* Determines if the "quick insert mode is on"
* This prevents the dialog from scrolling up if used within wisywig editors
*/
@Prop({
default: false
}) readonly quickInsertMode!: boolean
/**
* Prevent document preview in already existing previews
*/

View file

@ -1,13 +1,13 @@
<template>
<div>
<template v-if="editMode">
<existingDocumentDialog
preventOpen="true"
:dialog-trigger="existingObjectDialogTrigger"
@trigger-dialog-close="existingObjectDialogClose"
@signal-document-selected="handleDocumentSelected"
/>
</template>
<existingDocumentDialog
v-if="editMode"
preventOpen="true"
quickInsertMode="true"
:dialog-trigger="existingObjectDialogTrigger"
@trigger-dialog-close="existingObjectDialogClose"
@signal-document-selected="handleDocumentSelected"
/>
<div class="flex justify-center items-center text-weight-bolder q-mb-sm q-mt-md fieldWysiwygTitle">
<span>
@ -170,8 +170,9 @@ export default class Field_Wysiwyg extends FieldBase {
// We need to timeout here to give time to the runtime to focus the editor.
// when focused the caret will return to it's previous position and we can insert the document link
setTimeout(() => {
editor.runCmd("insertHtml", `<a href="document:${id}">${doc.label}<a/>`)
}, 1)
editor.runCmd("insertHtml", `<a href="document:${id}">${doc.label}</a>&nbsp;`)
}, 100)
/* eslint-enable */
}
@ -189,14 +190,18 @@ export default class Field_Wysiwyg extends FieldBase {
const editor = this.$refs[`wysiwygField${this.inputDataBluePrint.id}`] as QEditor
// We don't want to paste anything special in the source mode editor, let the user do their thing
if ((editor as any).isViewingSource)
if ((editor as any).isViewingSource){
return;
}
// Prevent showing up `@` character
evt.preventDefault()
// Open the selector dialog
this.existingObjectAssignUID()
// Timeout to allow to actually type the '@' symbol
setTimeout(() => {
this.existingObjectAssignUID()
}, 1)
}
/* eslint-enable */
}
@ -207,8 +212,6 @@ export default class Field_Wysiwyg extends FieldBase {
// Only follow links when ctrl is pressed
if (evt.ctrlKey) {
const link = evt.target.href
console.log(link)
console.log(evt.target.tagName)
evt.stopPropagation()
this.openLink(link)
}

View file

@ -906,3 +906,7 @@ font[size="7"] {
.q-item--dense {
min-height: 42px !important;
}
.find-box{
top: auto !important;
bottom: 5px !important;
}

View file

@ -33,6 +33,7 @@ $customColors: (
'ruby-red': #f75746,
'satin-sheen-gold': #e8bb50,
'satin-sheen-gold-dark': darken(#e8bb50, 12.5),
'satin-sheen-gold-darker': darken(#e8bb50, 17.5),
'satin-sheen-gold-light': lighten(#e8bb50, 7.5),
'satin-sheen-gold-bright': lighten(#e8bb50, 15),
'gainsboro': #dde4e4,

View file

@ -3,6 +3,25 @@
---
## 0.1.10
- Creating a brand new project can very occasionally get stuck. Restarting the app fixes this.
- Loading existing project can very occasionally get stuck. Restarting the app fixes this.
- Saving documents can sometimes leave it in edit mode instead of closing it (data gets saved anyway).
### New features
- **Added page-wide search option similar to web-browsers with a default keybind of "CTRL+ALT+F"**
- The keybind can be modified to the user's preferences as usual in the Keybinds menu
- **Added support for "@" links inside document editors** (thanks AkroMentos!)
- Pressing "@" inside the big editor fields will now allow you connect links directly inside the text editors
- Clicking on links created this way, while not in edit mode, inside text editors will open the connected document in a new tab
- Clicking on links created this way, while in edit mode, inside text editors and holding CTRL key will also open the connected document in a new tab
- Clicking on links created this way, while in document quick-preview, will open the connected document in a new tab
### Bugfixes & Optimizations
- Slightly improved color scheme for edit mode of documents while in light mode
## 0.1.9
### Known issues

View file

@ -1281,7 +1281,14 @@ export default class PageDocumentDisplay extends BaseClass {
}
body:not(.body--dark) {
.documentDisplay {
a,
.text-primary{
color: #e6ae2b !important;
}
.isDead {
text-decoration-color: #000;
}

View file

@ -11,6 +11,17 @@ export const defaultKeybinds = [
tooltip: "Open keybind cheatsheet"
},
// Open full-page search - CTRL + SHIFT + F
{
altKey: false,
ctrlKey: true,
shiftKey: true,
which: 70,
editable: true,
id: "openFullPageSearch",
tooltip: "Open full-page search"
},
// Show project overview - NONE
{
altKey: false,

View file

@ -3,6 +3,8 @@
* Toggles dev tools in the current window
*/
export const tipsTricks: string[] = [
"Typing '@' symbol while editing big text editor fields will allow you to link to other documents directly inside the text-editor!",
"\"CTRL+SHIFT\" will bring up a full-page search in case you are hunting for that particular word in the current document!",
"Any field in the document editing mode with the small dropdown arrow allows for custom values! Just close the menu of predefined values with ESC, type your desired value and confirm with ENTER.",
"It is possible to search through all documents and all of their fields at once using the following in either the Quick search popup or any of the relationship searches: \"%field-name:whatever-you-need\"",
"There is a whole list of really helpful keybinds that can make your use of FA a lot quicker and easier!",

View file

@ -4,6 +4,7 @@
"baseUrl": ".",
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"strictPropertyInitialization": false,
"suppressImplicitAnyIndexErrors": true
},
"include": [