From 8485c5430d7feb5eee9cf3e0374afe7fbf0e60cd Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 7 Sep 2023 10:04:27 -0400 Subject: fixed removing map pins to not reappear. updated config anchors to not be added to annotations list. fixed imageBox to not pass its configs on to its parent collection when focusing. --- src/client/views/nodes/PDFBox.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 758b49655..6f9d96a33 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -243,14 +243,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent Date: Tue, 12 Sep 2023 20:43:20 -0400 Subject: dropping link button on same collection makes a pushpin. fixed broken undo typing to crate doc in sidebar. fixed min/max scaling for cropped images and made annotationOverlays start to use it. Fixed nested text boxes to stopPropagation on pointer down to enable editing of translations in sidebar. moved sidebar filters onto doc's filters. Added metadata filters back to sidebar. Added an -any- option to filtersPanel. fixed schema view preview window, added buttons and sliders. --- package-lock.json | 119 ++++++++++++++++----- package.json | 4 +- src/client/documents/Documents.ts | 7 +- src/client/util/CurrentUserUtils.ts | 10 +- src/client/views/FilterPanel.tsx | 20 ++-- src/client/views/PropertiesView.tsx | 7 +- src/client/views/SidebarAnnos.tsx | 30 +++--- src/client/views/StyleProvider.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 44 +++++--- .../collectionSchema/CollectionSchemaView.scss | 8 +- .../collectionSchema/CollectionSchemaView.tsx | 1 + .../collections/collectionSchema/SchemaRowBox.tsx | 4 +- .../collectionSchema/SchemaTableCell.tsx | 26 ++++- src/client/views/global/globalScripts.ts | 8 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 10 +- src/client/views/nodes/PDFBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 51 ++++++--- src/fields/Doc.ts | 1 + 21 files changed, 255 insertions(+), 110 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/package-lock.json b/package-lock.json index e0e54769a..fbfdf0136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7244,12 +7244,97 @@ "strip-ansi": "^7.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "strip-ansi": { "version": "7.1.0", "bundled": true, "requires": { "ansi-regex": "^6.0.1" } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } } } }, @@ -8754,7 +8839,7 @@ } }, "string-width-cjs": { - "version": "npm:string-width@4.2.3", + "version": "npm:string-width-cjs@4.2.3", "bundled": true, "requires": { "emoji-regex": "^8.0.0", @@ -8777,7 +8862,7 @@ } }, "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", + "version": "npm:strip-ansi-cjs@6.0.1", "bundled": true, "requires": { "ansi-regex": "^5.0.1" @@ -8936,7 +9021,7 @@ } }, "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", + "version": "npm:wrap-ansi-cjs@7.0.0", "bundled": true, "requires": { "ansi-styles": "^4.0.0", @@ -14742,6 +14827,11 @@ "node-forge": "^0.10.0" } }, + "google-translate-api-browser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/google-translate-api-browser/-/google-translate-api-browser-3.0.1.tgz", + "integrity": "sha512-KTLodkyGBWMK9IW6QIeJ2zCuju4Z0CLpbkADKo+yLhbSTD4l+CXXpQ/xaynGVAzeBezzJG6qn8MLeqOq3SmW0A==" + }, "googleapis": { "version": "40.0.1", "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-40.0.1.tgz", @@ -27327,29 +27417,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, - "translate-google-api": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/translate-google-api/-/translate-google-api-1.0.4.tgz", - "integrity": "sha512-KVXmo4+64/H1vIbnzf2zNiJ2JLeEB3jrEnNRP2EFNAGNqna/5bmw/Cps3pCHu0n3BzTOoWh9u6wFvrRYdzQ6Iw==", - "requires": { - "axios": "^0.20.0" - }, - "dependencies": { - "axios": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", - "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - } - } - }, "traverse-chain": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", diff --git a/package.json b/package.json index 67fdedeb2..d013ad74d 100644 --- a/package.json +++ b/package.json @@ -164,6 +164,7 @@ "@types/three": "^0.126.2", "@types/web": "0.0.53", "@webscopeio/react-textarea-autocomplete": "^4.9.1", + "D": "^1.0.0", "adm-zip": "^0.4.16", "archiver": "^3.1.1", "array-batcher": "^1.2.3", @@ -196,7 +197,6 @@ "cors": "^2.8.5", "csv-parser": "^3.0.0", "csv-stringify": "^6.3.0", - "D": "^1.0.0", "d3": "^7.6.1", "depcheck": "^0.9.2", "equation-editor-react": "github:bobzel/equation-editor-react#useLocally", @@ -219,6 +219,7 @@ "golden-layout": "^1.5.9", "google-auth-library": "^4.2.4", "google-maps-react": "^2.0.6", + "google-translate-api-browser": "^3.0.1", "googleapis": "^40.0.0", "googlephotos": "^0.2.5", "got": "^12.0.1", @@ -327,7 +328,6 @@ "textarea-caret": "^3.1.0", "three": "^0.127.0", "tough-cookie": "^4.0.0", - "translate-google-api": "^1.0.4", "typescript-collections": "^1.3.3", "typescript-language-server": "^0.4.0", "url-loader": "^1.1.2", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bb60cb329..85ee4ef59 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -145,7 +145,6 @@ class CTypeInfo extends FInfo { class DTypeInfo extends FInfo { fieldType? = 'enumeration'; values? = Array.from(Object.keys(DocumentType)); - readOnly = true; } class DateInfo extends FInfo { fieldType? = 'date'; @@ -338,11 +337,13 @@ export class DocumentOptions { // freeform properties _freeform_backgroundGrid?: BOOLt = new BoolInfo('whether background grid is shown on freeform collections'); + _freeform_scale_min?: NUMt = new NumInfo('how far out a view can zoom (used by image/videoBoxes that are clipped'); + _freeform_scale_max?: NUMt = new NumInfo('how far in a view can zoom (used by sidebar freeform views'); _freeform_scale?: NUMt = new NumInfo('how much a freeform view has been scaled (zoomed)'); _freeform_panX?: NUMt = new NumInfo('horizontal pan location of a freeform view'); _freeform_panY?: NUMt = new NumInfo('vertical pan location of a freeform view'); _freeform_noAutoPan?: BOOLt = new BoolInfo('disables autopanning when this item is dragged'); - _freeform_noZoom?: BOOLt = new BoolInfo('disables zooming'); + _freeform_noZoom?: BOOLt = new BoolInfo('disables zooming (used by Pile docs)'); //BUTTONS buttonText?: string; @@ -426,7 +427,7 @@ export class DocumentOptions { treeView_FreezeChildren?: STRt = new StrInfo('set (add, remove, add|remove) to disable adding, removing or both from collection'); sidebar_color?: string; // background color of text sidebar - sidebar_collectionType?: string; // collection type of text sidebar + sidebar_type_collection?: string; // collection type of text sidebar data_dashboards?: List; // list of dashboards used in shareddocs; text?: string; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8bedea562..527f251f9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -627,6 +627,11 @@ export class CurrentUserUtils { { title: "Z order", icon: "z", toolTip: "Keep Z order on Drag", btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: '{ return toggleRaiseOnDrag(_readOnly_);}'}}, // Only when floating document is selected in freeform ] } + static stackTools(): Button[] { + return [ + { title: "Center", icon: "align-center", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"center", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + ] + } static viewTools(): Button[] { return [ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform @@ -682,8 +687,8 @@ export class CurrentUserUtils { static schemaTools():Button[] { return [ - {title: "Show preview", toolTip: "Show selection preview", btnType: ButtonType.ToggleButton, buttonText: "Show Preview", icon: "eye", scripts:{ onClick: '{ return toggleSchemaPreview(_readOnly_); }'} }, - {title: "Single Lines", toolTip: "Single Line Rows", btnType: ButtonType.ToggleButton, buttonText: "Single Line", icon: "eye", scripts:{ onClick: '{ return toggleSingleLineSchema(_readOnly_); }'} }, + {title: "Preview", toolTip: "Show selection preview", btnType: ButtonType.ToggleButton, icon: "portrait", scripts:{ onClick: '{ return toggleSchemaPreview(_readOnly_); }'} }, + {title: "1 Line",toolTip: "Single Line Rows", btnType: ButtonType.ToggleButton, icon: "eye", scripts:{ onClick: '{ return toggleSingleLineSchema(_readOnly_); }'} }, ]; } @@ -713,6 +718,7 @@ export class CurrentUserUtils { { title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: { linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available { title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available + { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected ]; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 0d4f4df5a..a601706ce 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -235,7 +235,7 @@ export class FilterPanel extends React.Component { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); - const set = new Set([String.fromCharCode(127) + '--undefined--']); + const set = new Set([String.fromCharCode(127) + '--undefined--', Doc.FilterAny]); if (facetHeader === 'tags') allCollectionDocs.forEach(child => StrListCast(child[facetHeader]) @@ -257,24 +257,16 @@ export class FilterPanel extends React.Component { }; render() { - // console.log('this is frist one today ' + this._allFacets); - this._allFacets.forEach(element => console.log(element)); - // const options = Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => pair[1].filterable ).map(facet => value: facet, label: facet) //this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); - // console.log('HEELLLLLL ' + DocumentOptions); - - let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest']; + let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest', ...this._allFacets.filter(facet => facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => { if (pair[1].filterable) { filteredOptions.push(pair[0]); - console.log('THIS IS FILTERABLE ALKDJFIIEII' + filteredOptions); } }); let options = filteredOptions.map(facet => ({ value: facet, label: facet })); - // Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => console.log('this is first piar ' + pair[0] + ' this is second piar ' + pair[1].filterable)); - return (
@@ -398,13 +390,13 @@ export class FilterPanel extends React.Component {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' - } + ?.split(Doc.FilterSep)[2] ?? '' + )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? (fval === Doc.FilterAny ? 'exists' : 'check') : 'remove'), 'set filter')} /> {facetValue}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 699aafe80..21b6bfac5 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -18,7 +18,7 @@ import { ComputedField } from '../../fields/ScriptField'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; -import { DocumentType } from '../documents/DocumentTypes'; +import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; import { LinkManager } from '../util/LinkManager'; @@ -122,6 +122,9 @@ export class PropertiesView extends React.Component { @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } + @computed get isStack() { + return this.selectedDoc?.type_collection === CollectionViewType.Stacking; + } rtfWidth = () => (!this.selectedDoc ? 0 : Math.min(this.selectedDoc?.[Width](), this.props.width - 20)); rtfHeight = () => (!this.selectedDoc ? 0 : this.rtfWidth() <= this.selectedDoc?.[Width]() ? Math.min(this.selectedDoc?.[Height](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT); @@ -1096,6 +1099,8 @@ export class PropertiesView extends React.Component { @computed get transformEditor() { return (
+ {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), (val: number) => !isNaN(val) && (this.selectedDoc!.gridGap = val))} + {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.xMargin = val))} {this.isInk ? this.controlPointsButton : null} {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, (val: number) => !isNaN(val) && (this.shapeWid = val), 1000, 1)} {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, (val: number) => !isNaN(val) && (this.shapeHgt = val), 1000, 1)} diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index ff347d65f..1e1b8e0e6 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -62,12 +62,9 @@ export class SidebarAnnos extends React.Component { DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc => keys.add(StrCast(doc.author))); return Array.from(keys.keys()).sort(); } - get filtersKey() { - return '_' + this.sidebarKey + '_childFilters'; - } anchorMenuClick = (anchor: Doc, filterExlusions?: string[]) => { - const startup = StrListCast(this.props.rootDoc.childFilters) + const startup = this.childFilters() .map(filter => filter.split(':')[0]) .join(' '); const target = Docs.Create.TextDocument(startup, { @@ -151,8 +148,9 @@ export class SidebarAnnos extends React.Component { }; makeDocUnfiltered = (doc: Doc) => { if (DocListCast(this.props.rootDoc[this.sidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { - if (this.props.layoutDoc[this.filtersKey]) { - this.props.layoutDoc[this.filtersKey] = new List(); + if (this.childFilters()) { + // if any child filters exist, get rid of them + this.props.layoutDoc._childFilters = new List(); } return true; } @@ -178,7 +176,7 @@ export class SidebarAnnos extends React.Component { addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey); moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey); removeDocument = (doc: Doc | Doc[]) => this.props.removeDocument(doc, this.sidebarKey); - childFilters = () => [...StrListCast(this.props.layoutDoc._childFilters), ...StrListCast(this.props.layoutDoc[this.filtersKey])]; + childFilters = () => StrListCast(this.props.layoutDoc._childFilters); layout_showTitle = () => 'title'; setHeightCallback = (height: number) => this.props.setHeight?.(height + this.filtersHeight()); sortByLinkAnchorY = (a: Doc, b: Doc) => { @@ -188,25 +186,25 @@ export class SidebarAnnos extends React.Component { }; render() { const renderTag = (tag: string) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`tags::${tag}::check`); + const active = this.childFilters().includes(`tags${Doc.FilterSep}${tag}${Doc.FilterSep}check`); return ( -
Doc.setDocFilter(this.props.rootDoc, 'tags', tag, 'check', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, 'tags', tag, 'check', true, undefined, e.shiftKey)}> {tag}
); }; const renderMeta = (tag: string, dflt: FieldResult) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`${tag}:${dflt}:exists`); + const active = this.childFilters().includes(`${tag}${Doc.FilterSep}${Doc.FilterAny}${Doc.FilterSep}exists`); return ( -
Doc.setDocFilter(this.props.rootDoc, tag, dflt, 'exists', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, tag, Doc.FilterAny, 'exists', true, undefined, e.shiftKey)}> {tag}
); }; const renderUsers = (user: string) => { - const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`author:${user}:check`); + const active = this.childFilters().includes(`author:${user}:check`); return ( -
Doc.setDocFilter(this.props.rootDoc, 'author', user, 'check', true, this.sidebarKey, e.shiftKey)}> +
Doc.setDocFilter(this.props.rootDoc, 'author', user, 'check', true, undefined, e.shiftKey)}> {user}
); @@ -224,11 +222,11 @@ export class SidebarAnnos extends React.Component { height: '100%', }}>
e.stopPropagation()}> - {this.allUsers.map(renderUsers)} + {this.allUsers.length > 1 ? this.allUsers.map(renderUsers) : null} {this.allHashtags.map(renderTag)} - {/* {Array.from(this.allMetadata.keys()) + {Array.from(this.allMetadata.keys()) .sort() - .map(key => renderMeta(key, this.allMetadata.get(key)))} */} + .map(key => renderMeta(key, this.allMetadata.get(key)))}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 85aa5ad83..0a14b93f7 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -317,7 +317,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ({ + items={[ DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard)!, ...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])].map(dv => ({ text: StrCast(dv.rootDoc.title), val: dv as any, style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor}, diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 9ba4cb6cf..8c40567d3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -138,7 +138,7 @@ export class CollectionStackingView extends CollectionSubView diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 3aadeffcd..3598d548a 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -361,7 +361,11 @@ export class CollectionStackingViewFieldColumn extends React.Component +
e.stopPropagation()} + className="collectionStackingView-addDocumentButton" + style={{ width: 'calc(100% - 25px)', maxWidth: this.props.columnWidth / this.props.numGroupColumns - 25, marginBottom: 10 }}> number; @@ -421,11 +422,27 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.Document._isGroup || this.Document._freeform_noZoom) return; + if (this.Document._isGroup || this.Document[this.scaleFieldKey + '_noZoom']) return; let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05; if (deltaScale < 0) deltaScale = -deltaScale; const [x, y] = this.getTransform().transformPoint(pointX, pointY); @@ -1032,12 +1049,15 @@ export class CollectionFreeFormView extends CollectionSubView 20) { deltaScale = 20 / invTransform.Scale; } - if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) { + if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc[this.scaleFieldKey + '_min'])) { this.setPan(0, 0); return; } - if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) { - deltaScale = NumCast(this.rootDoc._freeform_scale_min, 1) / invTransform.Scale; + if (deltaScale * invTransform.Scale > NumCast(this.rootDoc[this.scaleFieldKey + '_max'], Number.MAX_VALUE)) { + deltaScale = NumCast(this.rootDoc[this.scaleFieldKey + '_max'], 1) / invTransform.Scale; + } + if (deltaScale * invTransform.Scale < NumCast(this.rootDoc[this.scaleFieldKey + '_min'], this.isAnnotationOverlay ? 1 : 0)) { + deltaScale = NumCast(this.rootDoc[this.scaleFieldKey + '_min'], 1) / invTransform.Scale; } const localTransform = invTransform.scaleAbout(deltaScale, x, y); @@ -1527,12 +1547,6 @@ export class CollectionFreeFormView extends CollectionSubView .schema-column-header:nth-child(2) > .left { @@ -205,7 +211,7 @@ overflow-x: hidden; overflow-y: auto; padding: 5px; - display: inline-block; + display: inline-flex; } .schema-row { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 5c7dcc1a4..d757d5349 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -836,6 +836,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this.props.isContentActive() && e.stopPropagation()} ref={r => { // prevent wheel events from passively propagating up through containers diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 5b4fc34bb..4e418728f 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -16,7 +16,7 @@ import { CollectionSchemaView } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; import { Transform } from '../../../util/Transform'; -import { IconButton } from 'browndash-components'; +import { IconButton, Size } from 'browndash-components'; import { CgClose } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; @@ -117,6 +117,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { } + size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( this, @@ -133,6 +134,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { } + size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( this, diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 1c9c0de53..e18f27fb0 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -325,10 +325,34 @@ export class SchemaEnumerationCell extends React.Component const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props); const options = this.props.options?.map(facet => ({ value: facet, label: facet })); return ( -
+
() { className={`toolbar-slider ${active ? '' : 'none'}`} onPointerDown={e => { PresBox._sliderBatch = UndoManager.StartBatch('pres slider'); + document.addEventListener('pointerup', PresBox.endBatch, true); e.stopPropagation(); }} - onPointerUp={() => PresBox._sliderBatch.end()} onChange={e => { e.stopPropagation(); change(e.target.value); -- cgit v1.2.3-70-g09d2 From 0df1fc3fd85c1dea84dcaec5a934fc08f0da6832 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 4 Oct 2023 07:46:05 -0400 Subject: several fixes for webclips, linking to pdf/web, fonticon dropdowns. removed sliderbox. reduce uses of scriptContext fixed web clipping annotations to be in correct spot and not to crash because of using a url that it doesn't have. fixed pdf/web links to not use anchor from other end of link. because of sharing of GetAnchor global. added a backup when presbox overwrites a doc's data field. removed sliderBox. fixed fontIcon dropdowns to not call click script twice. removed scriptContext where it wasn't needed which is everywhere except TreeViews. --- src/client/documents/DocumentTypes.ts | 3 +- src/client/documents/Documents.ts | 8 -- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/MainView.tsx | 2 - src/client/views/StyleProvider.tsx | 2 - .../views/collections/CollectionNoteTakingView.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 37 +++----- .../views/collections/CollectionStackingView.tsx | 1 - .../collectionSchema/CollectionSchemaView.tsx | 1 - src/client/views/nodes/DocumentContentsView.tsx | 2 - src/client/views/nodes/FontIconBox/FontIconBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/SliderBox.scss | 19 ---- src/client/views/nodes/SliderBox.tsx | 103 --------------------- src/client/views/nodes/WebBox.scss | 1 - src/client/views/nodes/WebBox.tsx | 80 +++++++++++----- src/client/views/nodes/trails/PresBox.tsx | 7 +- src/client/views/pdf/PDFViewer.tsx | 5 +- 18 files changed, 82 insertions(+), 195 deletions(-) delete mode 100644 src/client/views/nodes/SliderBox.scss delete mode 100644 src/client/views/nodes/SliderBox.tsx (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index f8d129e79..87010f770 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -30,14 +30,13 @@ export enum DocumentType { // special purpose wrappers that either take no data or are compositions of lower level types LINK = 'link', IMPORT = 'import', - SLIDER = 'slider', PRES = 'presentation', PRESELEMENT = 'preselement', COLOR = 'color', YOUTUBE = 'youtube', COMPARISON = 'comparison', GROUP = 'group', - PUSHPIN = "pushpin", + PUSHPIN = 'pushpin', SCRIPTDB = 'scriptdb', // database of scripts GROUPDB = 'groupdb', // database of groups diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f7ceef4f4..a79a62b57 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -54,7 +54,6 @@ import { PhysicsSimulationBox } from '../views/nodes/PhysicsBox/PhysicsSimulatio import { RecordingBox } from '../views/nodes/RecordingBox/RecordingBox'; import { ScreenshotBox } from '../views/nodes/ScreenshotBox'; import { ScriptingBox } from '../views/nodes/ScriptingBox'; -import { SliderBox } from '../views/nodes/SliderBox'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; import { PresBox } from '../views/nodes/trails/PresBox'; import { PresElementBox } from '../views/nodes/trails/PresElementBox'; @@ -628,13 +627,6 @@ export namespace Docs { options: {}, }, ], - [ - DocumentType.SLIDER, - { - layout: { view: SliderBox, dataField: defaultDataKey }, - options: {}, - }, - ], [ DocumentType.PRES, { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2ea5972ee..cc8f72ddf 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -820,7 +820,7 @@ export class CurrentUserUtils { // When the user views one of these documents, it will be added to the sharing documents 'viewed' list field // The sharing document also stores the user's color value which helps distinguish shared documents from personal documents static setupSharedDocs(doc: Doc, sharingDocumentId: string) { - const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}"; + const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(documentView.props.treeViewDoc, 'viewed', documentView.rootDoc);}"; const sharedScripts = { treeView_ChildDoubleClick: dblClkScript, } const sharedDocOpts:DocumentOptions = { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d6f5d63fe..0a3389fc2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -728,7 +728,6 @@ export class MainView extends React.Component { PanelHeight={this.leftMenuFlyoutHeight} renderDepth={0} isContentActive={returnTrue} - scriptContext={CollectionDockingView.Instance?.props.Document} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -766,7 +765,6 @@ export class MainView extends React.Component { childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - scriptContext={this} />
); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d7537bffb..8417a6f5b 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -21,7 +21,6 @@ import { InkingStroke } from './InkingStroke'; import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; -import { SliderBox } from './nodes/SliderBox'; import './StyleProvider.scss'; import React = require('react'); import { PropertiesView } from './PropertiesView'; @@ -215,7 +214,6 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ); diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index ad3160a08..c4650647c 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -58,9 +58,7 @@ export class CollectionStackedTimeline extends CollectionSubView CollectionStackedTimeline.RangeScript; - rangePlayScript = () => CollectionStackedTimeline.RangePlayScript; + @computed get rangeClick() { + // prettier-ignore + return ScriptField.MakeFunction('stackedTimeline.clickAnchor(this, clientX)', + { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any } + )!; + } + @computed get rangePlay() { + // prettier-ignore + return ScriptField.MakeFunction('stackedTimeline.playOnClick(this, clientX)', + { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any })!; + } + rangeClickScript = () => this.rangeClick; + rangePlayScript = () => this.rangePlay; // handles key events for for creating key anchors, scrubbing, exiting trim @action @@ -835,7 +825,6 @@ class StackedTimelineAnchor extends React.Component hideResizeHandles={true} bringToFront={emptyFunction} contextMenuItems={this.contextMenuItems} - scriptContext={this.props.stackedTimeline} /> ), }; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 36f8bc101..c43a9d2b8 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -361,7 +361,6 @@ export class CollectionStackingView extends CollectionSubView ); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d2b61167e..f73c037f4 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -972,7 +972,6 @@ class CollectionSchemaViewDocs extends React.Component
); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 8ac9d6804..e1de2fa76 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -41,7 +41,6 @@ import { PhysicsSimulationBox } from './PhysicsBox/PhysicsSimulationBox'; import { RecordingBox } from './RecordingBox'; import { ScreenshotBox } from './ScreenshotBox'; import { ScriptingBox } from './ScriptingBox'; -import { SliderBox } from './SliderBox'; import { PresBox } from './trails/PresBox'; import { VideoBox } from './VideoBox'; import { WebBox } from './WebBox'; @@ -240,7 +239,6 @@ export class DocumentContentsView extends React.Component< FontIconBox, LabelBox, EquationBox, - SliderBox, FieldView, CollectionFreeFormView, CollectionDockingView, diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 14a3d16ef..d2e1293da 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -240,7 +240,6 @@ export class FontIconBox extends DocComponent() { text: typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title), val: value, style: getStyle(value), - onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value), // shortcut: '#', })); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 73a5be90a..cf44649a2 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -242,7 +242,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(SliderBox, fieldKey); - } - - get minThumbKey() { - return this.fieldKey + '-minThumb'; - } - get maxThumbKey() { - return this.fieldKey + '-maxThumb'; - } - get minKey() { - return this.fieldKey + '-min'; - } - get maxKey() { - return this.fieldKey + '-max'; - } - specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ description: 'Edit Thumb Change Script', icon: 'edit', event: (obj: any) => ScriptBox.EditButtonScript('On Thumb Change ...', this.props.Document, 'onThumbChange', obj.x, obj.y) }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' }); - }; - onChange = (values: readonly number[]) => - runInAction(() => { - this.dataDoc[this.minThumbKey] = values[0]; - this.dataDoc[this.maxThumbKey] = values[1]; - ScriptCast(this.layoutDoc.onThumbChanged, null)?.script.run({ - self: this.rootDoc, - scriptContext: this.props.scriptContext, - range: values, - this: this.layoutDoc, - }); - }); - - render() { - const domain = [NumCast(this.layoutDoc[this.minKey]), NumCast(this.layoutDoc[this.maxKey])]; - const defaultValues = [NumCast(this.dataDoc[this.minThumbKey]), NumCast(this.dataDoc[this.maxThumbKey])]; - return domain[1] <= domain[0] ? null : ( -
e.stopPropagation()} style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}> -
- - {railProps => } - - {({ handles, activeHandleID, getHandleProps }) => ( -
- {handles.map((handle, i) => { - const value = i === 0 ? defaultValues[0] : defaultValues[1]; - return ( -
- -
- ); - })} -
- )} -
- - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map(tick => ( - val.toString()} /> - ))} -
- )} -
-
-
-
- ); - } -} diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 75847c100..511c91da0 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -176,7 +176,6 @@ width: 100%; height: 100%; transform-origin: top left; - overflow: auto; .webBox-iframe { width: 100%; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 27c19105f..d4ba7a48f 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -62,10 +62,8 @@ export class WebBox extends ViewBoxAnnotatableComponent(); private _searchString = ''; private _scrollTimer: any; + private _getAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = () => undefined; - private get _getAnchor() { - return AnchorMenu.Instance?.GetAnchor; - } @observable private _webUrl = ''; // url of the src parameter of the embedded iframe but not necessarily the rendered page - eg, when following a link, the rendered page changes but we don't want the src parameter to also change as that would cause an unnecessary re-render. @observable private _hackHide = false; // apparently changing the value of the 'sandbox' prop doesn't necessarily apply it to the active iframe. so thisforces the ifrmae to be rebuilt when allowScripts is toggled @observable private _searching: boolean = false; @@ -186,13 +184,15 @@ export class WebBox extends ViewBoxAnnotatableComponent { - this._annotationKeySuffix = () => this._urlHash + '_annotations'; - const reqdFuncs: { [key: string]: string } = {}; + this._annotationKeySuffix = () => (this._urlHash ? this._urlHash + '_' : '') + 'annotations'; // bcz: need to make sure that doc.data_annotations points to the currently active web page's annotations (this could/should be when the doc is created) - reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"])`; - reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"] = value`; - reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_sidebar"])`; - DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs); + if (this._url) { + const reqdFuncs: { [key: string]: string } = {}; + reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"])`; + reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"] = value`; + reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"sidebar"])`; + DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs); + } }); this._disposers.urlchange = reaction( () => WebCast(this.rootDoc.data), @@ -264,14 +264,16 @@ export class WebBox extends ViewBoxAnnotatableComponent this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined); AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale); // Changing which document to add the annotation to (the currently selected WebBox) - GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash}_sidebar`); + GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); GPTPopup.Instance.addDoc = this.sidebarAddDocument; } } }; @action + webClipDown = (e: React.PointerEvent) => { + const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); + const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; + const word = getWordAtPoint(e.target, e.clientX, e.clientY); + this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc); + MarqueeAnnotator.clearAnnotations(this._savedAnnotations); + e.button !== 2 && (this._marqueeing = [e.clientX, e.clientY]); + if (word || (e.target as any)?.className?.includes('rangeslider') || (e.target as any)?.onclick || (e.target as any)?.parentNode?.onclick) { + e.stopPropagation(); + setTimeout( + action(() => (this._marqueeing = undefined)), + 100 + ); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it. + } else { + this._isAnnotating = true; + this.props.select(false); + e.stopPropagation(); + e.preventDefault(); + } + document.addEventListener('pointerup', this.webClipUp); + }; + webClipUp = (e: PointerEvent) => { + document.removeEventListener('pointerup', this.webClipUp); + this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value + const sel = window.getSelection(); + if (sel && !sel.isCollapsed) { + const selRange = sel.getRangeAt(0); + this._selectionText = sel.toString(); + AnchorMenu.Instance.setSelectedText(sel.toString()); + this._textAnnotationCreator = () => this.createTextAnnotation(sel, selRange); + AnchorMenu.Instance.jumpTo(e.clientX, e.clientY); + // Changing which document to add the annotation to (the currently selected WebBox) + GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); + GPTPopup.Instance.addDoc = this.sidebarAddDocument; + } + }; + @action iframeDown = (e: PointerEvent) => { const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; @@ -396,9 +435,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - return 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1; - }; + isFirefox = () => 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1; iframeClick = () => this._iframeClick; iframeScaling = () => 1 / this.props.ScreenToLocalTransform().Scale; @@ -722,10 +759,11 @@ export class WebBox extends ViewBoxAnnotatableComponent { + this._getAnchor = AnchorMenu.Instance?.GetAnchor; this._marqueeing = undefined; this._isAnnotating = false; this._iframeClick = undefined; - const sel = this._iframe?.contentDocument?.getSelection(); + const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection(); if (sel?.empty) sel.empty(); // Chrome else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox if (x !== undefined && y !== undefined) { @@ -750,7 +788,7 @@ export class WebBox extends ViewBoxAnnotatableComponent e.stopPropagation()} dangerouslySetInnerHTML={{ __html: field.html }} />; + return r && (this._scrollHeight = Number(getComputedStyle(r).height.replace('px', '')))} contentEditable onPointerDown={this.webClipDown} dangerouslySetInnerHTML={{ __html: field.html }} />; } if (field instanceof WebField) { const url = this.layoutDoc[this.fieldKey + '_useCors'] ? Utils.CorsProxy(this._webUrl) : this._webUrl; @@ -775,7 +813,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url))); + this._url && (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url))); return this.addDocument(doc, annotationKey); }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 2a3b232bd..383b400c8 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -465,7 +465,11 @@ export class PresBox extends ViewBoxBaseComponent() { const fkey = Doc.LayoutFieldKey(bestTarget); const setData = bestTargetView?.ComponentView?.setData; if (setData) setData(activeItem.config_data); - else Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; + else { + const current = Doc.GetProto(bestTarget)[fkey]; + Doc.GetProto(bestTarget)[fkey + '_' + Date.now()] = current instanceof ObjectField ? current[Copy]() : current; + Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; + } bestTarget[fkey + '_usePath'] = activeItem.config_usePath; setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10); } @@ -2650,7 +2654,6 @@ export class PresBox extends ViewBoxBaseComponent() { removeDocument={returnFalse} dontRegisterView={true} focus={this.focusElement} - scriptContext={this} ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 2a191477b..23dc084ad 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -82,9 +82,7 @@ export class PDFViewer extends React.Component { private _ignoreScroll = false; private _initialScroll: { loc: Opt; easeFunc: 'linear' | 'ease' | undefined } | undefined; private _forcedScroll = true; - get _getAnchor() { - return AnchorMenu.Instance?.GetAnchor; - } + _getAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = () => undefined; selectionText = () => this._selectionText; selectionContent = () => this._selectionContent; @@ -400,6 +398,7 @@ export class PDFViewer extends React.Component { @action finishMarquee = (x?: number, y?: number) => { + this._getAnchor = AnchorMenu.Instance?.GetAnchor; this.isAnnotating = false; this._marqueeing = undefined; this._textSelecting = true; -- cgit v1.2.3-70-g09d2