aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts21
-rw-r--r--src/client/util/CurrentUserUtils.ts3
-rw-r--r--src/client/views/DocComponent.tsx3
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx2
-rw-r--r--src/client/views/nodes/FilterBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx1
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss18
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx40
-rw-r--r--src/client/views/pdf/PDFViewer.tsx3
12 files changed, 76 insertions, 26 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 19f719c43..ad30e7d33 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -889,6 +889,27 @@ export namespace Docs {
}
export namespace DocUtils {
+ export function Excluded(d: Doc, docFilters: string[]) {
+ const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields
+ for (let i = 0; i < docFilters.length; i += 3) {
+ const [key, value, modifiers] = docFilters.slice(i, i + 3);
+ if (!filterFacets[key]) {
+ filterFacets[key] = {};
+ }
+ filterFacets[key][value] = modifiers;
+ }
+
+ if (d.z) return false;
+ for (const facetKey of Object.keys(filterFacets)) {
+ const facet = filterFacets[facetKey];
+ const xs = Object.keys(facet).filter(value => facet[value] === "x");
+ const failsNotEqualFacets = xs?.some(value => Doc.matchFieldValue(d, facetKey, value));
+ if (failsNotEqualFacets) {
+ return true;
+ }
+ }
+ return false;
+ }
export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField) {
const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 342954a4e..3e76b189a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1127,8 +1127,9 @@ export class CurrentUserUtils {
CurrentUserUtils.openDashboard(userDoc, dashboardDoc);
}
- public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number) {
+ public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean) {
const tbox = Docs.Create.TextDocument("", {
+ _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined,
_width: width || 200, _height: height || 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
_fontFamily: StrCast(Doc.UserDoc().fontFamily), title
});
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index b3c90a68f..893b74d75 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -123,7 +123,8 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
@action.bound
removeDocument(doc: Doc | Doc[]): boolean {
const effectiveAcl = GetEffectiveAcl(this.dataDoc);
- if (effectiveAcl === AclAdmin || effectiveAcl === AclEdit) {
+ const docAcl = GetEffectiveAcl(doc);
+ if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin || docAcl === AclAdmin) {
const docs = doc instanceof Doc ? [doc] : doc;
docs.map(doc => doc.isPushpin = doc.annotationOn = undefined);
const targetDataDoc = this.dataDoc;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 4299dba86..5469c2358 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -86,7 +86,7 @@ export class MainView extends React.Component {
document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
new InkStrokeProperties();
this._sidebarContent.proto = undefined;
- DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollY", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
+ DocServer.setPlaygroundFields(["dataTransition", "_delayAutoHeight", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollY", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 26fe00657..649b8c175 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -142,6 +142,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const docsforFilter: Doc[] = [];
childDocs.forEach((d) => {
+ if (DocUtils.Excluded(d, docFilters)) return;
let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && ((!docFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript).length > 0));
const fieldKey = Doc.LayoutFieldKey(d);
const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView");
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 967055638..a3f76839d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1625,6 +1625,12 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
const pany = -this.props.panY();
const zoom = this.props.zoomScaling();
return <div className={freeformclass}
+ onScroll={e => {
+ const target = e.target as any;
+ if (getComputedStyle(target.parentElement)?.overflow === "visible") { // if collection is visible, then scrolling will mess things up since there are no scroll bars
+ target.scrollTop = target.scrollLeft = 0;
+ }
+ }}
style={{
transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}) translate(${panx}px, ${pany}px)`,
transition: this.props.transition,
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e1ebb4eee..7c64fd429 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -141,7 +141,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
} else if (!e.ctrlKey && !e.metaKey) {
FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout && !this.props.ChildLayoutString ? e.key : "";
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch("live text batch");
- this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100));
+ this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100, this.props.xMargin === 0));
e.stopPropagation();
}
}
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index c1978e331..d5b50122b 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -48,7 +48,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
const keys = new Set<string>(noviceFields);
this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key)));
- return Array.from(keys.keys()).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_") && !key.startsWith("acl")) || noviceFields.includes(key)).sort();
+ return Array.from(keys.keys()).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_")) || noviceFields.includes(key) || !Doc.UserDoc().noviceMode).sort();
}
gatherFieldValues(dashboard: Doc, facetKey: string) {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index a7b534956..421aac69f 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -508,6 +508,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
if (!e.aborted && e.annoDragData && !e.annoDragData.linkDocument) {
e.annoDragData.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
annotationDoc.isLinkButton = true;
+ annotationDoc.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.Document;
}
}
});
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index d1109b388..dbf98a5e9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -106,6 +106,15 @@
border-width: 1px;
}
}
+.formattedTextBox-inner-rounded-selected,
+.formattedTextBox-inner-selected {
+ .ProseMirror {
+ padding:10px;
+ }
+ .ProseMirror:hover {
+ background: unset;
+ }
+}
// .menuicon {
// display: inline-block;
@@ -332,15 +341,6 @@ footnote::after {
.multi4:before { transition: 0.5s;counter-increment: multi4; display: inline-block; vertical-align: top; margin-left: -4.2em; width: 4.2em; content: counter(multi1, upper-alpha) "."counter(multi2, decimal) "."counter(multi3, lower-alpha) "."counter(multi4, lower-roman) ". "; }
}
-.formattedTextBox-inner-rounded-selected,
-.formattedTextBox-inner-selected {
- .ProseMirror {
- padding:10px;
- }
- .ProseMirror:hover {
- background: unset;
- }
-}
@media only screen and (max-width: 1000px) {
@import "../../globalCssVariables";
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 12fc690c8..1148087c6 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -557,11 +557,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
sidebarDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction,
- action(() => {
+ () => setTimeout(action(() => {
const prevWidth = this.sidebarWidth();
this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%";
this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth);
- }));
+ })), false);
}
sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => {
const bounds = this.CurrentDiv.getBoundingClientRect();
@@ -1524,6 +1524,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
+ @computed get audioHandle() {
+ return !this.layoutDoc._showAudio ? (null) :
+ <div className="formattedTextBox-dictation" onClick={action(e => this._recording = !this._recording)} >
+ <FontAwesomeIcon className="formattedTextBox-audioFont" style={{ color: this._recording ? "red" : "blue", transitionDelay: "0.6s", opacity: this._recording ? 1 : 0.25, }} icon={"microphone"} size="sm" />
+ </div>;
+ }
+
+ @computed get sidebarHandle() {
+ const annotated = DocListCast(this.dataDoc[this.annotationKey]).length;
+ return !this.props.isSelected() && !(annotated && !this.sidebarWidth()) ? (null) :
+ <div className="formattedTextBox-sidebar-handle"
+ style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`, background: annotated ? "lightBlue" : undefined }}
+ onPointerDown={this.sidebarDown}
+ onClick={e => {
+ console.log(e);
+ }}
+ />;
+ }
+
@computed get sidebarCollection() {
const fitToBox = this.props.Document._fitToBox;
return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
@@ -1531,6 +1550,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
PanelHeight={this.props.PanelHeight}
PanelWidth={this.sidebarWidth}
+ xMargin={0}
scaleField={this.annotationKey + "-scale"}
annotationsKey={this.annotationKey}
isAnnotationOverlay={true}
@@ -1565,8 +1585,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
selected && setTimeout(() => this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props)); // need to make sure that we update a text box that is selected after updating the one that was deselected
if (!selected && FormattedTextBoxComment.textBox === this) { FormattedTextBoxComment.Hide(); }
const minimal = this.props.ignoreAutoHeight;
- const selPad = (selected && !this.layoutDoc._singleLine) || minimal ? -10 : 0;
- const selclass = selected && !this.layoutDoc._singleLine ? "-selected" : "";
+ const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0);
+ const selPad = Math.min(margins, 10);
+ const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
+ const selclass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
return (
<div className={"formattedTextBox-cont"} ref={this._boxRef}
style={{
@@ -1614,18 +1636,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
<div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selclass}`} ref={this.createDropTarget}
style={{
overflow: this.layoutDoc._singleLine ? "hidden" : undefined,
- padding: this.layoutDoc._textBoxPadding ? StrCast(this.layoutDoc._textBoxPadding) :
- `${Math.max(0, NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0) + selPad)}px ${NumCast(this.layoutDoc._xMargin, this.props.xMargin || 0) + selPad}px`,
+ padding: this.layoutDoc._textBoxPadding ? StrCast(this.layoutDoc._textBoxPadding) : `${padding}px`,
pointerEvents: !active ? ((this.layoutDoc.isLinkButton || this.props.onClick) ? "none" : undefined) : undefined
}}
/>
</div>
{this.sidebarCollection}
- {selected ? <div className="formattedTextBox-sidebar-handle" style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 5px))`, background: DocListCast(this.dataDoc[this.annotationKey]).length ? "lightBlue" : undefined }} onPointerDown={this.sidebarDown} /> : (null)}
- {!this.layoutDoc._showAudio ? (null) :
- <div className="formattedTextBox-dictation" onClick={action(e => this._recording = !this._recording)} >
- <FontAwesomeIcon className="formattedTextBox-audioFont" style={{ color: this._recording ? "red" : "blue", transitionDelay: "0.6s", opacity: this._recording ? 1 : 0.25, }} icon={"microphone"} size="sm" />
- </div>}
+ {this.sidebarHandle}
+ {this.audioHandle}
</div>
</div>
);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index fb87da744..77dd40f2a 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -642,6 +642,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
e.annoDragData.linkDocument = DocUtils.MakeLink({ doc: annotationDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
}
annotationDoc.isLinkButton = true; // prevents link button fro showing up --- maybe not a good thing?
+ annotationDoc.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.Document;
e.annoDragData && e.annoDragData.linkDocument && e.annoDragData?.linkDropCallback?.({ linkDocument: e.annoDragData.linkDocument });
}
});
@@ -733,7 +734,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
addDocument={this.addDocument}
- docFilters={this.props.docRangeFilters}
+ docFilters={this.props.docFilters}
docRangeFilters={this.props.docRangeFilters}
CollectionView={undefined}
ScreenToLocalTransform={this.overlayTransform}