aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.DS_Storebin10244 -> 10244 bytes
-rw-r--r--src/ClientUtils.ts649
-rw-r--r--src/client/DocServer.ts10
-rw-r--r--src/client/documents/Documents.ts10
-rw-r--r--src/client/util/CurrentUserUtils.ts14
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/GroupManager.tsx6
-rw-r--r--src/client/util/HypothesisUtils.ts2
-rw-r--r--src/client/util/SettingsManager.tsx4
-rw-r--r--src/client/util/SharingManager.tsx10
-rw-r--r--src/client/util/reportManager/ReportManager.tsx2
-rw-r--r--src/client/views/DashboardView.tsx6
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/PropertiesView.tsx4
-rw-r--r--src/client/views/SidebarAnnos.tsx2
-rw-r--r--src/client/views/StyleProvider.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx2
-rw-r--r--src/client/views/collections/TreeView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx18
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx2
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts4
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts4
-rw-r--r--src/client/views/nodes/formattedText/marks_rts.ts2
-rw-r--r--src/fields/Doc.ts75
-rw-r--r--src/fields/util.ts10
26 files changed, 744 insertions, 102 deletions
diff --git a/src/.DS_Store b/src/.DS_Store
index f8d745dbf..75cff7b55 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
new file mode 100644
index 000000000..57e0373c4
--- /dev/null
+++ b/src/ClientUtils.ts
@@ -0,0 +1,649 @@
+import * as Color from 'color';
+import * as React from 'react';
+import { ColorResult } from 'react-color';
+import * as rp from 'request-promise';
+import { numberRange, decimalToHexString } from './Utils';
+import { DocumentType } from './client/documents/DocumentTypes';
+import { Colors } from './client/views/global/globalEnums';
+
+export function DashColor(color: string) {
+ try {
+ return color ? Color(color.toLowerCase()) : Color('transparent');
+ } catch (e) {
+ if (color.includes('gradient')) console.log("using color 'white' in place of :" + color);
+ else console.log('COLOR error:', e);
+ return Color('white');
+ }
+}
+
+export function lightOrDark(color: any) {
+ if (color === 'transparent' || !color) return Colors.BLACK;
+ if (color.startsWith?.('linear')) return Colors.BLACK;
+ if (DashColor(color).isLight()) return Colors.BLACK;
+ return Colors.WHITE;
+}
+
+export function returnTransparent() {
+ return 'transparent';
+}
+
+export function returnTrue() {
+ return true;
+}
+
+export function returnIgnore(): 'ignore' {
+ return 'ignore';
+}
+export function returnAlways(): 'always' {
+ return 'always';
+}
+export function returnNever(): 'never' {
+ return 'never';
+}
+
+export function returnDefault(): 'default' {
+ return 'default';
+}
+
+export function return18() {
+ return 18;
+}
+
+export function returnFalse() {
+ return false;
+}
+
+export function returnAll(): 'all' {
+ return 'all';
+}
+
+export function returnNone(): 'none' {
+ return 'none';
+}
+
+export function returnVal(val1?: number, val2?: number) {
+ return val1 || (val2 !== undefined ? val2 : 0);
+}
+
+export function returnOne() {
+ return 1;
+}
+
+export function returnZero() {
+ return 0;
+}
+
+export function returnEmptyString() {
+ return '';
+}
+
+export function returnEmptyFilter() {
+ return [] as string[];
+}
+
+export function returnEmptyDoclist() {
+ return [] as any[];
+}
+
+export namespace ClientUtils {
+ export const CLICK_TIME = 300;
+ export const DRAG_THRESHOLD = 4;
+ export const SNAP_THRESHOLD = 10;
+ let _currentUserEmail: string = '';
+ export function CurrentUserEmail() {
+ return _currentUserEmail;
+ }
+ export function SetCurrentUserEmail(email: string) {
+ _currentUserEmail = email;
+ }
+ export function isClick(x: number, y: number, downX: number, downY: number, downTime: number) {
+ return Date.now() - downTime < ClientUtils.CLICK_TIME && Math.abs(x - downX) < ClientUtils.DRAG_THRESHOLD && Math.abs(y - downY) < ClientUtils.DRAG_THRESHOLD;
+ }
+
+ export function cleanDocumentType(type: DocumentType) {
+ switch (type) {
+ case DocumentType.IMG: return 'Image';
+ case DocumentType.AUDIO: return 'Audio';
+ case DocumentType.COL: return 'Collection';
+ case DocumentType.RTF: return 'Text';
+ default: return type.charAt(0).toUpperCase() + type.slice(1);
+ } // prettier-ignore
+ }
+
+ export function readUploadedFileAsText(inputFile: File) {
+ // eslint-disable-next-line no-undef
+ const temporaryFileReader = new FileReader();
+
+ return new Promise((resolve, reject) => {
+ temporaryFileReader.onerror = () => {
+ temporaryFileReader.abort();
+ reject(new DOMException('Problem parsing input file.'));
+ };
+
+ temporaryFileReader.onload = () => {
+ resolve(temporaryFileReader.result);
+ };
+ temporaryFileReader.readAsText(inputFile);
+ });
+ }
+
+ /**
+ * Uploads an image buffer to the server and stores with specified filename. by default the image
+ * is stored at multiple resolutions each retrieved by using the filename appended with _o, _s, _m, _l (indicating original, small, medium, or large)
+ * @param imageUri the bytes of the image
+ * @param returnedFilename the base filename to store the image on the server
+ * @param nosuffix optionally suppress creating multiple resolution images
+ */
+ export async function convertDataUri(imageUri: string, returnedFilename: string, nosuffix = false, replaceRootFilename: string | undefined = undefined) {
+ try {
+ const posting = ClientUtils.prepend('/uploadURI');
+ const returnedUri = await rp.post(posting, {
+ body: {
+ uri: imageUri,
+ name: returnedFilename,
+ nosuffix,
+ replaceRootFilename,
+ },
+ json: true,
+ });
+ return returnedUri;
+ } catch (e) {
+ console.log('ConvertDataURI :' + e);
+ }
+ return undefined;
+ }
+
+ export function GetScreenTransform(ele?: HTMLElement | null): { scale: number; translateX: number; translateY: number } {
+ if (!ele) {
+ return { scale: 1, translateX: 1, translateY: 1 };
+ }
+ const rect = ele.getBoundingClientRect();
+ const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / ele.offsetWidth;
+ const translateX = rect.left;
+ const translateY = rect.top;
+
+ return { scale, translateX, translateY };
+ }
+
+ /**
+ * A convenience method. Prepends the full path (i.e. http://localhost:<port>) to the
+ * requested extension
+ * @param extension the specified sub-path to append to the window origin
+ */
+ export function prepend(extension: string): string {
+ return window.location.origin + extension;
+ }
+ export function fileUrl(filename: string): string {
+ return prepend(`/files/${filename}`);
+ }
+
+ export function shareUrl(documentId: string): string {
+ return prepend(`/doc/${documentId}?sharing=true`);
+ }
+
+ export function CorsProxy(url: string): string {
+ return prepend('/corsProxy/') + encodeURIComponent(url);
+ }
+
+ export function CopyText(text: string) {
+ navigator.clipboard.writeText(text);
+ }
+
+ export function colorString(color: ColorResult) {
+ return color.hex.startsWith('#') && color.hex.length < 8 ? color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff') : color.hex;
+ }
+
+ export function fromRGBAstr(rgba: string) {
+ const rm = rgba.match(/rgb[a]?\(([ 0-9]+)/);
+ const r = rm ? Number(rm[1]) : 0;
+ const gm = rgba.match(/rgb[a]?\([ 0-9]+,([ 0-9]+)/);
+ const g = gm ? Number(gm[1]) : 0;
+ const bm = rgba.match(/rgb[a]?\([ 0-9]+,[ 0-9]+,([ 0-9]+)/);
+ const b = bm ? Number(bm[1]) : 0;
+ const am = rgba.match(/rgba?\([ 0-9]+,[ 0-9]+,[ 0-9]+,([ .0-9]+)/);
+ const a = am ? Number(am[1]) : 1;
+ return { r: r, g: g, b: b, a: a };
+ }
+
+ const isTransparentFunctionHack = 'isTransparent(__value__)';
+ export const noRecursionHack = '__noRecursion';
+
+ // special case filters
+ export const noDragDocsFilter = 'noDragDocs::any::check';
+ export const TransparentBackgroundFilter = `backgroundColor::${isTransparentFunctionHack},${noRecursionHack}::check`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
+ export const OpaqueBackgroundFilter = `backgroundColor::${isTransparentFunctionHack},${noRecursionHack}::x`; // bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
+
+ export function IsRecursiveFilter(val: string) {
+ return !val.includes(noRecursionHack);
+ }
+ export function HasFunctionFilter(val: string) {
+ if (val.includes(isTransparentFunctionHack)) return (color: string) => color !== '' && DashColor(color).alpha() !== 1;
+ // add other function filters here...
+ return undefined;
+ }
+
+ export function toRGBAstr(col: { r: number; g: number; b: number; a?: number }) {
+ return 'rgba(' + col.r + ',' + col.g + ',' + col.b + (col.a !== undefined ? ',' + col.a : '') + ')';
+ }
+
+ export function HSLtoRGB(h: number, s: number, l: number) {
+ // Must be fractions of 1
+ // s /= 100;
+ // l /= 100;
+
+ const c = (1 - Math.abs(2 * l - 1)) * s;
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
+ const m = l - c / 2;
+ let r = 0;
+ let g = 0;
+ let b = 0;
+ if (h >= 0 && h < 60) {
+ r = c;
+ g = x;
+ b = 0;
+ } else if (h >= 60 && h < 120) {
+ r = x;
+ g = c;
+ b = 0;
+ } else if (h >= 120 && h < 180) {
+ r = 0;
+ g = c;
+ b = x;
+ } else if (h >= 180 && h < 240) {
+ r = 0;
+ g = x;
+ b = c;
+ } else if (h >= 240 && h < 300) {
+ r = x;
+ g = 0;
+ b = c;
+ } else if (h >= 300 && h < 360) {
+ r = c;
+ g = 0;
+ b = x;
+ }
+ r = Math.round((r + m) * 255);
+ g = Math.round((g + m) * 255);
+ b = Math.round((b + m) * 255);
+ return { r: r, g: g, b: b };
+ }
+
+ export function RGBToHSL(red: number, green: number, blue: number) {
+ // Make r, g, and b fractions of 1
+ const r = red / 255;
+ const g = green / 255;
+ const b = blue / 255;
+
+ // Find greatest and smallest channel values
+ const cmin = Math.min(r, g, b);
+ const cmax = Math.max(r, g, b);
+ const delta = cmax - cmin;
+ let h = 0;
+ let s = 0;
+ let l = 0;
+ // Calculate hue
+
+ // No difference
+ if (delta === 0) h = 0;
+ // Red is max
+ else if (cmax === r) h = ((g - b) / delta) % 6;
+ // Green is max
+ else if (cmax === g) h = (b - r) / delta + 2;
+ // Blue is max
+ else h = (r - g) / delta + 4;
+
+ h = Math.round(h * 60);
+
+ // Make negative hues positive behind 360°
+ if (h < 0) h += 360; // Calculate lightness
+
+ l = (cmax + cmin) / 2;
+
+ // Calculate saturation
+ s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
+
+ // Multiply l and s by 100
+ // s = +(s * 100).toFixed(1);
+ // l = +(l * 100).toFixed(1);
+
+ return { h: h, s: s, l: l };
+ }
+
+ export function scrollIntoView(targetY: number, targetHgt: number, scrollTop: number, contextHgt: number, minSpacing: number, scrollHeight: number) {
+ if (!targetHgt) return targetY; // if there's no height, then assume that
+ if (scrollTop + contextHgt < Math.min(scrollHeight, targetY + minSpacing + targetHgt)) {
+ return Math.ceil(targetY + minSpacing + targetHgt - contextHgt);
+ }
+ if (scrollTop >= Math.max(0, targetY - minSpacing)) {
+ return Math.max(0, Math.floor(targetY - minSpacing));
+ }
+ return undefined;
+ }
+
+ export function GetClipboardText(): string {
+ const textArea = document.createElement('textarea');
+ document.body.appendChild(textArea);
+ textArea.focus();
+ textArea.select();
+
+ try {
+ document.execCommand('paste');
+ } catch (err) {
+ /* empty */
+ }
+
+ const val = textArea.value;
+ document.body.removeChild(textArea);
+ return val;
+ }
+}
+
+export function OmitKeys(obj: any, keys: string[], pattern?: string, addKeyFunc?: (dup: any) => void): { omit: any; extract: any } {
+ const omit: any = { ...obj };
+ const extract: any = {};
+ keys.forEach(key => {
+ extract[key] = omit[key];
+ delete omit[key];
+ });
+ pattern &&
+ Array.from(Object.keys(omit))
+ .filter(key => key.match(pattern))
+ .forEach(key => {
+ extract[key] = omit[key];
+ delete omit[key];
+ });
+ addKeyFunc?.(omit);
+ return { omit, extract };
+}
+
+export function WithKeys(obj: any, keys: string[], addKeyFunc?: (dup: any) => void) {
+ const dup: any = {};
+ keys.forEach(key => {
+ dup[key] = obj[key];
+ });
+ addKeyFunc && addKeyFunc(dup);
+ return dup;
+}
+
+export function incrementTitleCopy(title: string) {
+ const numstr = title.match(/.*(\{([0-9]*)\})+/);
+ const copyNumStr = `{${1 + (numstr ? +numstr[2] : 0)}}`;
+ return (numstr ? title.replace(numstr[1], '') : title) + copyNumStr;
+}
+
+const easeFunc = (transition: 'ease' | 'linear' | undefined, currentTime: number, start: number, change: number, duration: number) => {
+ if (transition === 'linear') {
+ const newCurrentTime = currentTime / duration; // currentTime / (duration / 2);
+ return start + newCurrentTime * change;
+ }
+
+ let newCurrentTime = currentTime / (duration / 2);
+ if (newCurrentTime < 1) {
+ return (change / 2) * newCurrentTime * newCurrentTime + start;
+ }
+
+ newCurrentTime -= 1;
+ return (-change / 2) * (newCurrentTime * (newCurrentTime - 2) - 1) + start;
+};
+
+export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number, transition: 'ease' | 'linear' | undefined, stopper?: () => void) {
+ stopper?.();
+ const elements = element instanceof HTMLElement ? [element] : element;
+ const starts = elements.map(element => element.scrollTop);
+ const startDate = new Date().getTime();
+ let _stop = false;
+ const stop = () => {
+ _stop = true;
+ };
+ const animateScroll = () => {
+ const currentDate = new Date().getTime();
+ const currentTime = currentDate - startDate;
+ const setScrollTop = (element: HTMLElement, value: number) => {
+ element.scrollTop = value;
+ };
+ if (!_stop) {
+ if (currentTime < duration) {
+ elements.forEach((element, i) => currentTime && setScrollTop(element, easeFunc(transition, Math.min(currentTime, duration), starts[i], to - starts[i], duration)));
+ requestAnimationFrame(animateScroll);
+ } else {
+ elements.forEach(element => setScrollTop(element, to));
+ }
+ }
+ };
+ animateScroll();
+ return stop;
+}
+
+export function smoothScrollHorizontal(duration: number, element: HTMLElement | HTMLElement[], to: number) {
+ const elements = element instanceof HTMLElement ? [element] : element;
+ const starts = elements.map(element => element.scrollLeft);
+ const startDate = new Date().getTime();
+
+ const animateScroll = () => {
+ const currentDate = new Date().getTime();
+ const currentTime = currentDate - startDate;
+ elements.forEach((element, i) => {
+ element.scrollLeft = easeFunc('ease', currentTime, starts[i], to - starts[i], duration);
+ });
+
+ if (currentTime < duration) {
+ requestAnimationFrame(animateScroll);
+ } else {
+ elements.forEach(element => {
+ element.scrollLeft = to;
+ });
+ }
+ };
+ animateScroll();
+}
+
+export function addStyleSheet(styleType: string = 'text/css') {
+ const style = document.createElement('style');
+ style.type = styleType;
+ const sheets = document.head.appendChild(style);
+ return (sheets as any).sheet;
+}
+export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') {
+ const propText =
+ typeof css === 'string'
+ ? css
+ : Object.keys(css)
+ .map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p]))
+ .join(';');
+ return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length);
+}
+export function removeStyleSheetRule(sheet: any, rule: number) {
+ if (sheet.rules.length) {
+ sheet.removeRule(rule);
+ return true;
+ }
+ return false;
+}
+export function clearStyleSheetRules(sheet: any) {
+ if (sheet.rules.length) {
+ numberRange(sheet.rules.length).map(() => sheet.removeRule(0));
+ return true;
+ }
+ return false;
+}
+
+export function simulateMouseClick(element: Element | null | undefined, x: number, y: number, sx: number, sy: number, rightClick = true) {
+ if (!element) return;
+ ['pointerdown', 'pointerup'].forEach(event => {
+ const me = new PointerEvent(event, {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ button: 2,
+ pointerType: 'mouse',
+ clientX: x,
+ clientY: y,
+ screenX: sx,
+ screenY: sy,
+ });
+ (me as any).dash = true;
+ element.dispatchEvent(me);
+ });
+
+ if (rightClick) {
+ const me = new MouseEvent('contextmenu', {
+ view: window,
+ bubbles: true,
+ cancelable: true,
+ button: 2,
+ clientX: x,
+ clientY: y,
+ movementX: 0,
+ movementY: 0,
+ screenX: sx,
+ screenY: sy,
+ });
+ (me as any).dash = true;
+ element.dispatchEvent(me);
+ }
+}
+
+export function getWordAtPoint(elem: any, x: number, y: number): string | undefined {
+ if (elem.tagName === 'INPUT') return 'input';
+ if (elem.tagName === 'TEXTAREA') return 'textarea';
+ if (elem.nodeType === elem.TEXT_NODE) {
+ const range = elem.ownerDocument.createRange();
+ range.selectNodeContents(elem);
+ let currentPos = 0;
+ const endPos = range.endOffset;
+ while (currentPos + 1 <= endPos) {
+ range.setStart(elem, currentPos);
+ range.setEnd(elem, currentPos + 1);
+ const rangeRect = range.getBoundingClientRect();
+ if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) {
+ range.expand?.('word'); // doesn't exist in firefox
+ const ret = range.toString();
+ range.detach();
+ return ret;
+ }
+ currentPos += 1;
+ }
+ } else {
+ Array.from(elem.childNodes).forEach((childNode: any) => {
+ const range = childNode.ownerDocument.createRange();
+ range.selectNodeContents(childNode);
+ const rangeRect = range.getBoundingClientRect();
+ if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) {
+ range.detach();
+ const word = getWordAtPoint(childNode, x, y);
+ if (word) return word;
+ } else {
+ range.detach();
+ }
+ return undefined;
+ });
+ }
+ return undefined;
+}
+
+export function isTargetChildOf(ele: HTMLDivElement | null, target: Element | null) {
+ let entered = false;
+ for (let child = target; !entered && child; child = child.parentElement) {
+ entered = child === ele;
+ }
+ return entered;
+}
+
+export function StopEvent(e: React.PointerEvent | React.MouseEvent | React.KeyboardEvent) {
+ e.stopPropagation();
+ e.preventDefault();
+}
+
+export function setupMoveUpEvents(
+ target: object,
+ e: React.PointerEvent,
+ moveEvent: (e: PointerEvent, down: number[], delta: number[]) => boolean,
+ upEvent: (e: PointerEvent, movement: number[], isClick: boolean) => any,
+ clickEvent: (e: PointerEvent, doubleTap?: boolean) => any,
+ // eslint-disable-next-line default-param-last
+ stopPropagation: boolean = true,
+ // eslint-disable-next-line default-param-last
+ stopMovePropagation: boolean = true,
+ noDoubleTapTimeout?: () => void
+) {
+ const targetAny = target as any;
+ const doubleTapTimeout = 300;
+ targetAny._doubleTap = Date.now() - (target as any)._lastTap < doubleTapTimeout;
+ targetAny._lastTap = Date.now();
+ targetAny._downX = targetAny._lastX = e.clientX;
+ targetAny._downY = targetAny._lastY = e.clientY;
+ targetAny._noClick = false;
+ let moving = false;
+
+ const _moveEvent = (e: PointerEvent): void => {
+ if (moving || Math.abs(e.clientX - (target as any)._downX) > ClientUtils.DRAG_THRESHOLD || Math.abs(e.clientY - (target as any)._downY) > ClientUtils.DRAG_THRESHOLD) {
+ moving = true;
+ if ((target as any)._doubleTime) {
+ clearTimeout((target as any)._doubleTime);
+ targetAny._doubleTime = undefined;
+ }
+ if (moveEvent(e, [(target as any)._downX, (target as any)._downY], [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) {
+ document.removeEventListener('pointermove', _moveEvent);
+ // eslint-disable-next-line no-use-before-define
+ document.removeEventListener('pointerup', _upEvent);
+ }
+ }
+ targetAny._lastX = e.clientX;
+ targetAny._lastY = e.clientY;
+ stopMovePropagation && e.stopPropagation();
+ };
+ const _upEvent = (e: PointerEvent): void => {
+ const isClick = Math.abs(e.clientX - targetAny._downX) < 4 && Math.abs(e.clientY - targetAny._downY) < 4;
+ upEvent(e, [e.clientX - targetAny._downX, e.clientY - targetAny._downY], isClick);
+ if (isClick) {
+ if (!targetAny._doubleTime && noDoubleTapTimeout) {
+ targetAny._doubleTime = setTimeout(() => {
+ noDoubleTapTimeout?.();
+ targetAny._doubleTime = undefined;
+ }, doubleTapTimeout);
+ }
+ if (targetAny._doubleTime && targetAny._doubleTap) {
+ clearTimeout(targetAny._doubleTime);
+ targetAny._doubleTime = undefined;
+ }
+ targetAny._noClick = clickEvent(e, targetAny._doubleTap);
+ }
+ document.removeEventListener('pointermove', _moveEvent);
+ document.removeEventListener('pointerup', _upEvent, true);
+ };
+ const _clickEvent = (e: MouseEvent): void => {
+ if ((target as any)._noClick) e.stopPropagation();
+ document.removeEventListener('click', _clickEvent, true);
+ };
+ if (stopPropagation) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ document.addEventListener('pointermove', _moveEvent);
+ document.addEventListener('pointerup', _upEvent, true);
+ document.addEventListener('click', _clickEvent, true);
+}
+
+export function DivHeight(ele: HTMLElement): number {
+ return Number(getComputedStyle(ele).height.replace('px', ''));
+}
+export function DivWidth(ele: HTMLElement): number {
+ return Number(getComputedStyle(ele).width.replace('px', ''));
+}
+
+export function dateRangeStrToDates(dateStr: string) {
+ // dateStr in yyyy-mm-dd format
+ const dateRangeParts = dateStr.split('|'); // splits into from and to date
+ const fromParts = dateRangeParts[0].split('-');
+ const toParts = dateRangeParts[1].split('-');
+
+ const fromYear = parseInt(fromParts[0]);
+ const fromMonth = parseInt(fromParts[1]) - 1;
+ const fromDay = parseInt(fromParts[2]);
+
+ const toYear = parseInt(toParts[0]);
+ const toMonth = parseInt(toParts[1]) - 1;
+ const toDay = parseInt(toParts[2]);
+
+ return [new Date(fromYear, fromMonth, fromDay), new Date(toYear, toMonth, toDay)];
+}
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 804e6d1d7..b833d3287 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -102,7 +102,7 @@ export namespace DocServer {
}
export function getFieldWriteMode(field: string) {
- return ClientUtils.CurrentUserEmail === 'guest' ? WriteMode.LivePlayground : fieldWriteModes[field] || WriteMode.Default;
+ return ClientUtils.CurrentUserEmail() === 'guest' ? WriteMode.LivePlayground : fieldWriteModes[field] || WriteMode.Default;
}
export function registerDocWithCachedUpdate(doc: Doc, field: string, oldValue: any) {
@@ -463,7 +463,7 @@ export namespace DocServer {
function _CreateFieldImpl(field: RefField) {
_cache[field[Id]] = field;
const initialState = SerializationHelper.Serialize(field);
- ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Emit(_socket, MessageStore.CreateField, initialState);
+ ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.CreateField, initialState);
}
// NOTIFY THE SERVER OF AN UPDATE TO A DOC'S STATE
@@ -481,7 +481,7 @@ export namespace DocServer {
}
function _UpdateFieldImpl(id: string, diff: any) {
- !DocServer.Control.isReadOnly() && ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Emit(_socket, MessageStore.UpdateField, { id, diff });
+ !DocServer.Control.isReadOnly() && ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.UpdateField, { id, diff });
}
function _respondToUpdateImpl(diff: any) {
@@ -516,11 +516,11 @@ export namespace DocServer {
}
export function DeleteDocument(id: string) {
- ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Emit(_socket, MessageStore.DeleteField, id);
+ ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.DeleteField, id);
}
export function DeleteDocuments(ids: string[]) {
- ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Emit(_socket, MessageStore.DeleteFields, ids);
+ ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Emit(_socket, MessageStore.DeleteFields, ids);
}
function _respondToDeleteImpl(ids: string | string[]) {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d41a96db2..f827ea81c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -970,7 +970,7 @@ export namespace Docs {
dataProps['acl-Guest'] = options['acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View);
dataProps.isSystem = viewProps.isSystem;
dataProps.isDataDoc = true;
- dataProps.author = ClientUtils.CurrentUserEmail;
+ dataProps.author = ClientUtils.CurrentUserEmail();
dataProps.author_date = new DateField();
if (fieldKey) {
dataProps[`${fieldKey}_modificationDate`] = new DateField();
@@ -990,7 +990,7 @@ export namespace Docs {
}
if (!noView) {
- const viewFirstProps: { [id: string]: any } = { author: ClientUtils.CurrentUserEmail };
+ const viewFirstProps: { [id: string]: any } = { author: ClientUtils.CurrentUserEmail() };
viewFirstProps['acl-Guest'] = options['_acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View);
let viewDoc: Doc;
// determines whether viewDoc should be created using placeholder Doc or default
@@ -1330,7 +1330,7 @@ export namespace Docs {
const doc = DockDocument(
configs.map(c => c.doc),
JSON.stringify(layoutConfig),
- ClientUtils.CurrentUserEmail === 'guest' ? options : { 'acl-Guest': SharingPermissions.View, ...options },
+ ClientUtils.CurrentUserEmail() === 'guest' ? options : { 'acl-Guest': SharingPermissions.View, ...options },
id
);
configs.forEach(c => {
@@ -1722,7 +1722,7 @@ export namespace DocUtils {
event: undoable(() => {
const newDoc = DocUtils.copyDragFactory(dragDoc);
if (newDoc) {
- newDoc.author = ClientUtils.CurrentUserEmail;
+ newDoc.author = ClientUtils.CurrentUserEmail();
newDoc.x = x;
newDoc.y = y;
EquationBox.SelectOnLoad = newDoc[Id];
@@ -1773,7 +1773,7 @@ export namespace DocUtils {
event: undoable(() => {
const newDoc = DocUtils.delegateDragFactory(dragDoc);
if (newDoc) {
- newDoc.author = ClientUtils.CurrentUserEmail;
+ newDoc.author = ClientUtils.CurrentUserEmail();
newDoc.x = x;
newDoc.y = y;
EquationBox.SelectOnLoad = newDoc[Id];
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 535f7cf9d..27ae5c9a0 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -586,7 +586,7 @@ pie title Minerals in my tap water
/// initializes the left sidebar panel view of the UserDoc
static setupUserDocView(doc: Doc, field:string) {
const reqdOpts:DocumentOptions = {
- _lockedPosition: true, _gridGap: 5, _forceActive: true, title: ClientUtils.CurrentUserEmail +"-view",
+ _lockedPosition: true, _gridGap: 5, _forceActive: true, title: ClientUtils.CurrentUserEmail() +"-view",
layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: dropActionType.same, ignoreClick: true, isSystem: true,
treeView_HideTitle: true, treeView_TruncateTitleWidth: 350
};
@@ -832,8 +832,8 @@ pie title Minerals in my tap water
static setupLinkDocs(doc: Doc, linkDatabaseId: string) {
if (!(CurrentUserUtils.newAccount ? undefined : DocCast(doc.myLinkDatabase))) {
const linkDocs = new Doc(linkDatabaseId, true);
- linkDocs.title = "LINK DATABASE: " + ClientUtils.CurrentUserEmail;
- linkDocs.author = ClientUtils.CurrentUserEmail;
+ linkDocs.title = "LINK DATABASE: " + ClientUtils.CurrentUserEmail();
+ linkDocs.author = ClientUtils.CurrentUserEmail();
linkDocs.isSystem = true;
linkDocs.data = new List<Doc>([]);
linkDocs["acl-Guest"] = SharingPermissions.Augment;
@@ -893,11 +893,11 @@ pie title Minerals in my tap water
reaction(() => DateCast(DocCast(doc.globalGroupDatabase).data_modificationDate),
async () => {
const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase).data);
- const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(ClientUtils.CurrentUserEmail)) || [];
+ const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(ClientUtils.CurrentUserEmail())) || [];
SetCachedGroups(["Guest", ...(mygroups?.map(g => StrCast(g.title))??[])]);
}, { fireImmediately: true });
doc.isSystem ?? (doc.isSystem = true);
- doc.title ?? (doc.title = ClientUtils.CurrentUserEmail);
+ doc.title ?? (doc.title = ClientUtils.CurrentUserEmail());
Doc.noviceMode ?? (Doc.noviceMode = true);
doc._showLabel ?? (doc._showLabel = true);
doc.textAlign ?? (doc.textAlign = "left");
@@ -975,7 +975,7 @@ pie title Minerals in my tap water
if (response) {
const result: { version: string, userDocumentId: string, sharingDocumentId: string, linkDatabaseId: string, email: string, cacheDocumentIds: string, resolvedPorts: string } = JSON.parse(response);
runInAction(() => { CurrentUserUtils.ServerVersion = result.version; });
- ClientUtils.CurrentUserEmail = result.email;
+ ClientUtils.SetCurrentUserEmail(result.email);
resolvedPorts = result.resolvedPorts as any;
DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts?.socket, result.email);
if (result.cacheDocumentIds)
@@ -1004,7 +1004,7 @@ pie title Minerals in my tap water
const userDoc = CurrentUserUtils.newAccount ? new Doc(info.userDocumentId, true) : field as Doc;
this.updateUserDocument(Doc.SetUserDoc(userDoc), info.sharingDocumentId, info.linkDatabaseId);
if (CurrentUserUtils.newAccount) {
- if (ClientUtils.CurrentUserEmail === "guest") {
+ if (ClientUtils.CurrentUserEmail() === "guest") {
DashboardView.createNewDashboard(undefined, "guest dashboard");
} else {
userDoc.activePage = "home";
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 67a61f17e..9a7786125 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -321,7 +321,7 @@ export class DocumentManager {
if (options.toggleTarget && (!options.didMove || docView.Document.hidden)) docView.Document.hidden = !docView.Document.hidden;
if (options.effect) docView.Document[Animation] = options.effect;
- if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && targetDoc.text_html) {
+ if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && targetDoc.text_html) {
// if the docView is a text anchor, the contextView is the PDF/Web/Text doc
contextView.setTextHtmlOverlay(StrCast(targetDoc.text_html), options.effect);
DocumentManager._overlayViews.add(contextView);
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 6b20b885b..c261c0f1e 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -136,7 +136,7 @@ export class GroupManager extends ObservableReactComponent<{}> {
hasEditAccess(groupDoc: Doc): boolean {
if (!groupDoc) return false;
const accessList: string[] = JSON.parse(StrCast(groupDoc.owners));
- return accessList.includes(ClientUtils.CurrentUserEmail) || this.adminGroupMembers?.includes(ClientUtils.CurrentUserEmail);
+ return accessList.includes(ClientUtils.CurrentUserEmail()) || this.adminGroupMembers?.includes(ClientUtils.CurrentUserEmail());
}
/**
@@ -148,7 +148,7 @@ export class GroupManager extends ObservableReactComponent<{}> {
const name = groupName.toLowerCase() === 'admin' ? 'Admin' : groupName;
const groupDoc = new Doc('GROUP:' + name, true);
groupDoc.title = name;
- groupDoc.owners = JSON.stringify([ClientUtils.CurrentUserEmail]);
+ groupDoc.owners = JSON.stringify([ClientUtils.CurrentUserEmail()]);
groupDoc.members = JSON.stringify(memberEmails);
this.addGroup(groupDoc);
}
@@ -177,7 +177,7 @@ export class GroupManager extends ObservableReactComponent<{}> {
Doc.RemoveDocFromList(this.GroupManagerDoc, 'data', group);
SharingManager.Instance.removeGroup(group);
const members = JSON.parse(StrCast(group.members));
- if (members.includes(ClientUtils.CurrentUserEmail)) {
+ if (members.includes(ClientUtils.CurrentUserEmail())) {
const index = DocListCast(this.GroupManagerDoc.data).findIndex(grp => grp === group);
index !== -1 && Cast(this.GroupManagerDoc.data, listSpec(Doc), [])?.splice(index, 1);
}
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index d1600468a..48d3ac046 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -33,7 +33,7 @@ export namespace Hypothesis {
// await SearchUtil.Search('web', true).then(
// action(async (res: SearchUtil.DocSearchResult) => {
// const docs = res.docs;
- // const filteredDocs = docs.filter(doc => doc.author === ClientUtils.CurrentUserEmail && doc.type === DocumentType.WEB && doc.data);
+ // const filteredDocs = docs.filter(doc => doc.author === ClientUtils.CurrentUserEmail() && doc.type === DocumentType.WEB && doc.data);
// filteredDocs.forEach(doc => {
// uri === Cast(doc.data, WebField)?.url.href && results.push(doc); // TODO check visited sites history?
// });
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index e2971895a..f983c29b7 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -128,7 +128,7 @@ export class SettingsManager extends React.Component<{}> {
if (this.playgroundMode) {
DocServer.Control.makeReadOnly();
addStyleSheetRule(SettingsManager._settingsStyle, 'topbar-inner-container', { background: 'red !important' });
- } else ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Control.makeEditable();
+ } else ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Control.makeEditable();
});
@undoBatch
@@ -537,7 +537,7 @@ export class SettingsManager extends React.Component<{}> {
<div className="settings-user">
<div style={{ color: SettingsManager.userBackgroundColor }}>{DashVersion}</div>
<div className="settings-username" style={{ color: SettingsManager.userBackgroundColor }}>
- {ClientUtils.CurrentUserEmail}
+ {ClientUtils.CurrentUserEmail()}
</div>
<Button text={Doc.GuestDashboard ? 'Exit' : 'Log Out'} type={Type.TERT} color={SettingsManager.userVariantColor} onClick={() => window.location.assign(ClientUtils.prepend('/logout'))} />
</div>
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 03f7e9b71..ade4cc218 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -137,7 +137,7 @@ export class SharingManager extends React.Component<{}> {
if (!this.populating && Doc.UserDoc()[Id] !== Utils.GuestID()) {
this.populating = true;
const userList = await RequestPromise.get(ClientUtils.prepend('/getUsers'));
- const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== ClientUtils.CurrentUserEmail);
+ const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== ClientUtils.CurrentUserEmail());
runInAction(() => {
FieldLoader.ServerLoadStatus.message = 'users';
});
@@ -234,7 +234,7 @@ export class SharingManager extends React.Component<{}> {
shareFromPropertiesSidebar = undoable((shareWith: string, permission: SharingPermissions, docs: Doc[], layout: boolean) => {
if (layout) this.layoutDocAcls = true;
if (shareWith !== 'Guest') {
- const user = this.users.find(({ user: { email } }) => email === (shareWith === 'Me' ? ClientUtils.CurrentUserEmail : shareWith));
+ const user = this.users.find(({ user: { email } }) => email === (shareWith === 'Me' ? ClientUtils.CurrentUserEmail() : shareWith));
docs.forEach(doc => {
if (user) this.setInternalSharing(user, permission, doc);
else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, doc, undefined, true);
@@ -499,19 +499,19 @@ export class SharingManager extends React.Component<{}> {
const sameAuthor = docs.every(doc => doc?.author === docs[0]?.author);
// the owner of the doc and the current user are placed at the top of the user list.
- const userKey = `acl-${normalizeEmail(ClientUtils.CurrentUserEmail)}`;
+ const userKey = `acl-${normalizeEmail(ClientUtils.CurrentUserEmail())}`;
const curUserPermission = StrCast(targetDoc[userKey]);
// const curUserPermission = HierarchyMapping.get(effectiveAcls[0])!.name
userListContents.unshift(
sameAuthor ? (
<div key={'owner'} className={'container'}>
- <span className="padding">{targetDoc?.author === ClientUtils.CurrentUserEmail ? 'Me' : StrCast(targetDoc?.author)}</span>
+ <span className="padding">{targetDoc?.author === ClientUtils.CurrentUserEmail() ? 'Me' : StrCast(targetDoc?.author)}</span>
<div className="edit-actions">
<div className={'permissions-dropdown'}>Owner</div>
</div>
</div>
) : null,
- sameAuthor && targetDoc?.author !== ClientUtils.CurrentUserEmail ? (
+ sameAuthor && targetDoc?.author !== ClientUtils.CurrentUserEmail() ? (
<div key={'me'} className={'container'}>
<span className={'padding'}>Me</span>
<div className="edit-actions">
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index d6fd339a9..02b3ee32c 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -134,7 +134,7 @@ export class ReportManager extends React.Component<{}> {
const req = await this.octokit.request('POST /repos/{owner}/{repo}/issues', {
owner: 'brown-dash',
repo: 'Dash-Web',
- title: formatTitle(this.formData.title, ClientUtils.CurrentUserEmail),
+ title: formatTitle(this.formData.title, ClientUtils.CurrentUserEmail()),
body: `${this.formData.description} ${formattedLinks.length > 0 ? `\n\nFiles:\n${formattedLinks.join('\n')}` : ''}`,
labels: ['from-dash-app', this.formData.type, this.formData.priority],
});
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1d286c987..14abd5f89 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -64,7 +64,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
getDashboards = (whichGroup: DashboardGroup) => {
if (whichGroup === DashboardGroup.MyDashboards) {
- return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard[DocData].author === ClientUtils.CurrentUserEmail);
+ return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard[DocData].author === ClientUtils.CurrentUserEmail());
}
return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig);
};
@@ -155,7 +155,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
: this.getDashboards(this.selectedDashboardGroup).map(dashboard => {
const href = ImageCast(dashboard.thumb)?.url?.href;
const shared = Object.keys(dashboard[DocAcl])
- .filter(key => key !== `acl-${normalizeEmail(ClientUtils.CurrentUserEmail)}` && !['acl-Me', 'acl-Guest'].includes(key))
+ .filter(key => key !== `acl-${normalizeEmail(ClientUtils.CurrentUserEmail())}` && !['acl-Me', 'acl-Guest'].includes(key))
.some(key => dashboard[DocAcl][key] !== AclPrivate);
return (
<div
@@ -255,7 +255,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
} else if (doc.readOnly) {
DocServer.Control.makeReadOnly();
} else {
- ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Control.makeEditable();
+ ClientUtils.CurrentUserEmail() !== 'guest' && DocServer.Control.makeEditable();
}
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8a060d0e0..13945cacf 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -122,7 +122,7 @@ export class MainView extends ObservableReactComponent<{}> {
}
@observable mainDoc: Opt<Doc> = undefined;
@computed private get mainContainer() {
- if (window.location.pathname.startsWith('/doc/') && ClientUtils.CurrentUserEmail === 'guest') {
+ if (window.location.pathname.startsWith('/doc/') && ClientUtils.CurrentUserEmail() === 'guest') {
DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main =>
runInAction(() => {
this.mainDoc = main as Doc;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 77e68866e..2a847e51a 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -405,7 +405,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
* @returns a row of the permissions panel
*/
sharingItem(name: string, admin: boolean, permission: string, showExpansionIcon?: boolean) {
- if (name === ClientUtils.CurrentUserEmail) {
+ if (name === ClientUtils.CurrentUserEmail()) {
name = 'Me';
}
return (
@@ -494,7 +494,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
});
// adds current user
- let userEmail = ClientUtils.CurrentUserEmail;
+ let userEmail = ClientUtils.CurrentUserEmail();
if (userEmail === 'guest') userEmail = 'Guest';
const userKey = `acl-${normalizeEmail(userEmail)}`;
if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail !== target.author) {
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index bcd82887c..db3f29fae 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -96,7 +96,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
return {
type: 'dashField',
attrs: { fieldKey: key, docId: '', hideKey: false, hideValue: false, editable: true },
- marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: ClientUtils.CurrentUserEmail, modified: 0 } }],
+ marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: ClientUtils.CurrentUserEmail(), modified: 0 } }],
};
});
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 15e309ca0..d8adfa68a 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -171,7 +171,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
doc._layout_showTitle,
props?.layout_showTitle?.() ||
(!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.FUNCPLOT, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any)
- ? doc.author === ClientUtils.CurrentUserEmail
+ ? doc.author === ClientUtils.CurrentUserEmail()
? StrCast(Doc.UserDoc().layout_showTitle)
: remoteDocHeader
: '')
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index cd401058f..7d93f4074 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -200,7 +200,7 @@ export function CollectionSubView<X>(moreProps?: X) {
let ind;
const doc = this.Document;
const id = Doc.UserDoc()[Id];
- const email = ClientUtils.CurrentUserEmail;
+ const email = ClientUtils.CurrentUserEmail();
const pos = { x: position[0], y: position[1] };
if (id && email) {
const proto = Doc.GetProto(doc);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index e266ccd14..20323a521 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -229,7 +229,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this.treeViewOpen = !this.treeViewOpen;
} else {
// choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding
- const bestEmbedding = docView.Document.author === ClientUtils.CurrentUserEmail && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document);
+ const bestEmbedding = docView.Document.author === ClientUtils.CurrentUserEmail() && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document);
this._props.addDocTab(bestEmbedding, OpenWhere.lightbox);
}
};
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index dbd2ebe0d..62a3e2467 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1512,7 +1512,7 @@ export class DocumentView extends DocComponent<DocumentViewProps & { CollectionF
// shows a stacking view collection (by default, but the user can change) of all documents linked to the source
public static showBackLinks(linkAnchor: Doc) {
- const docId = ClientUtils.CurrentUserEmail + Doc.GetProto(linkAnchor)[Id] + '-pivotish';
+ const docId = ClientUtils.CurrentUserEmail() + Doc.GetProto(linkAnchor)[Id] + '-pivotish';
// prettier-ignore
DocServer.GetRefField(docId).then(docx =>
LightboxView.Instance.SetLightboxDoc(
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c7543560d..a82f025f9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -580,7 +580,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
};
adoptAnnotation = (start: number, end: number, mark: Mark) => {
const view = this._editorView!;
- const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: ClientUtils.CurrentUserEmail });
+ const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: ClientUtils.CurrentUserEmail() });
view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark));
};
protected createDropTarget = (ele: HTMLDivElement) => {
@@ -722,7 +722,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-remote', { background: 'yellow' });
}
if (highlights.includes('My Text')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace(/\./g, '').replace(/@/g, ''), { background: 'moccasin' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail().replace(/\./g, '').replace(/@/g, ''), { background: 'moccasin' });
}
if (highlights.includes('Todo Items')) {
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-todo', { outline: 'black solid 1px' });
@@ -741,12 +741,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-ignore', { 'font-size': '1' });
}
if (highlights.includes('By Recent Minute')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail().replace('.', '').replace('@', ''), { opacity: '0.1' });
const min = Math.round(Date.now() / 1000 / 60);
numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-min-' + (min - i), { opacity: ((10 - i - 1) / 10).toString() }));
}
if (highlights.includes('By Recent Hour')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail().replace('.', '').replace('@', ''), { opacity: '0.1' });
const hr = Math.round(Date.now() / 1000 / 60 / 60);
numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-hr-' + (hr - i), { opacity: ((10 - i - 1) / 10).toString() }));
}
@@ -1489,7 +1489,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._props.select(false);
if (selLoadChar) {
const $from = this._editorView.state.selection.anchor ? this._editorView.state.doc.resolve(this._editorView.state.selection.anchor - 1) : undefined;
- const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
+ const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) });
const curMarks = this._editorView.state.storedMarks ?? $from?.marksAcross(this._editorView.state.selection.$head) ?? [];
const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark];
const tr1 = this._editorView.state.tr.setStoredMarks(storedMarks);
@@ -1503,7 +1503,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data
} else {
const $from = this._editorView.state.selection.anchor ? this._editorView.state.doc.resolve(this._editorView.state.selection.anchor - 1) : undefined;
- const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
+ const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) });
const curMarks = this._editorView.state.storedMarks ?? $from?.marksAcross(this._editorView.state.selection.$head) ?? [];
const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark];
const { tr } = this._editorView.state;
@@ -1534,7 +1534,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily) })] : []),
...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize) })] : []),
...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
- ...[schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
+ ...[schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) })],
];
this._editorView?.dispatch(this._editorView?.state.tr.setStoredMarks(docDefaultMarks));
};
@@ -1775,7 +1775,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
for (let i = state.selection.from; i <= state.selection.to; i++) {
const node = state.doc.resolve(i);
- if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== ClientUtils.CurrentUserEmail) && [AclAugment, AclSelfEdit].includes(GetEffectiveAcl(this.Document))) {
+ if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== ClientUtils.CurrentUserEmail()) && [AclAugment, AclSelfEdit].includes(GetEffectiveAcl(this.Document))) {
e.preventDefault();
}
}
@@ -1799,7 +1799,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
if ([AclEdit, AclAugment, AclAdmin].includes(GetEffectiveAcl(this.Document))) {
const modified = Math.floor(Date.now() / 1000);
const mark = state.selection.$to.marks().find(m => m.type === schema.marks.user_mark && m.attrs.modified === modified);
- _editorView.dispatch(state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(mark ?? schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified })));
+ _editorView.dispatch(state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(mark ?? schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified })));
}
break;
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 533fefa09..52d93ec38 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -10,7 +10,7 @@ import './FormattedTextBoxComment.scss';
import { schema } from './schema_rts';
export function findOtherUserMark(marks: readonly Mark[]): Mark | undefined {
- return marks.find(m => m.attrs.userid && m.attrs.userid !== ClientUtils.CurrentUserEmail);
+ return marks.find(m => m.attrs.userid && m.attrs.userid !== ClientUtils.CurrentUserEmail());
}
export function findUserMark(marks: readonly Mark[]): Mark | undefined {
return marks.find(m => m.attrs.userid);
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index e9ed2549e..c3a5a2c86 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -51,8 +51,8 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
case AclAugment:
{
const prevNode = state.selection.$cursor.nodeBefore;
- const prevUser = !prevNode ? ClientUtils.CurrentUserEmail : prevNode.marks[prevNode.marks.length - 1].attrs.userid;
- if (prevUser !== ClientUtils.CurrentUserEmail) {
+ const prevUser = !prevNode ? ClientUtils.CurrentUserEmail() : prevNode.marks[prevNode.marks.length - 1].attrs.userid;
+ if (prevUser !== ClientUtils.CurrentUserEmail()) {
return false;
}
}
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 78ea99592..5b5617484 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -433,8 +433,8 @@ export class RichTextRules {
return node
? state.tr
.removeMark(start, end, schema.marks.user_mark)
- .addMark(start, end, schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))
- .addMark(start, end, schema.marks.user_tag.create({ userid: ClientUtils.CurrentUserEmail, tag: tag, modified: Math.round(Date.now() / 1000 / 60) }))
+ .addMark(start, end, schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail(), modified: Math.floor(Date.now() / 1000) }))
+ .addMark(start, end, schema.marks.user_tag.create({ userid: ClientUtils.CurrentUserEmail(), tag: tag, modified: Math.round(Date.now() / 1000 / 60) }))
: state.tr;
}),
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 0f3306bef..d1c7b72a5 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -335,7 +335,7 @@ export const marks: { [index: string]: MarkSpec } = {
const min = Math.round(node.attrs.modified / 60);
const hr = Math.round(min / 60);
const day = Math.round(hr / 60 / 24);
- const remote = node.attrs.userid !== ClientUtils.CurrentUserEmail ? ' UM-remote' : '';
+ const remote = node.attrs.userid !== ClientUtils.CurrentUserEmail() ? ' UM-remote' : '';
return ['span', { class: 'UM-' + uid + remote + ' UM-min-' + min + ' UM-hr-' + hr + ' UM-day-' + day }, 0];
},
},
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 3fb914423..f8351c238 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -152,7 +152,7 @@ export const ReverseHierarchyMap: Map<string, { level: aclLevel; acl: symbol; im
export function updateCachedAcls(doc: Doc) {
if (doc) {
const target = (doc as any)?.__fieldTuples ?? doc;
- const permissions: { [key: string]: symbol } = !target.author || target.author === ClientUtils.CurrentUserEmail ? { 'acl-Me': AclAdmin } : {};
+ const permissions: { [key: string]: symbol } = !target.author || target.author === ClientUtils.CurrentUserEmail() ? { 'acl-Me': AclAdmin } : {};
Object.keys(target).forEach(key => {
key.startsWith('acl') && (permissions[key] = ReverseHierarchyMap.get(StrCast(target[key]))!.acl);
});
@@ -301,15 +301,16 @@ export class Doc extends RefField {
private set __fieldTuples(value) {
// called by deserializer to set all fields in one shot
this[FieldTuples] = value;
- // eslint-disable-next-line no-restricted-syntax
- for (const key in value) {
- const field = value[key];
- field !== undefined && (this[FieldKeys][key] = true);
- if (field instanceof ObjectField) {
- field[Parent] = this[Self];
- field[FieldChanged] = containedFieldChangedHandler(this[SelfProxy], key, field);
+ Object.keys(value).forEach(key => {
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
+ const field = value[key];
+ field !== undefined && (this[FieldKeys][key] = true);
+ if (field instanceof ObjectField) {
+ field[Parent] = this[Self];
+ field[FieldChanged] = containedFieldChangedHandler(this[SelfProxy], key, field);
+ }
}
- }
+ });
}
@observable private [FieldTuples]: any = {};
@@ -365,14 +366,11 @@ export class Doc extends RefField {
public async [HandleUpdate](diff: any) {
const set = diff.$set;
- const sameAuthor = this.author === ClientUtils.CurrentUserEmail;
- if (set) {
- for (const key in set) {
- const fprefix = 'fields.';
- if (!key.startsWith(fprefix)) {
- // eslint-disable-next-line no-continue
- continue;
- }
+ const sameAuthor = this.author === ClientUtils.CurrentUserEmail();
+ const fprefix = 'fields.';
+ Object.keys(set ?? {})
+ .filter(key => Object.prototype.hasOwnProperty.call(set, key) && key.startsWith(fprefix))
+ .forEach(async key => {
const fKey = key.substring(fprefix.length);
const fn = async () => {
const value = await SerializationHelper.Deserialize(set[key]);
@@ -395,15 +393,11 @@ export class Doc extends RefField {
} else {
this[CachedUpdates][fKey] = fn;
}
- }
- }
+ });
const unset = diff.$unset;
- if (unset) {
- for (const key in unset) {
- if (!key.startsWith('fields.')) {
- // eslint-disable-next-line no-continue
- continue;
- }
+ Object.keys(unset ?? {})
+ .filter(key => Object.prototype.hasOwnProperty.call(unset, key) && key.startsWith(fprefix))
+ .forEach(async key => {
const fKey = key.substring(7);
const fn = () => {
this[UpdatingFromServer] = true;
@@ -412,13 +406,11 @@ export class Doc extends RefField {
};
if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) {
delete this[CachedUpdates][fKey];
- // eslint-disable-next-line no-await-in-loop
await fn();
} else {
this[CachedUpdates][fKey] = fn;
}
- }
- }
+ });
}
}
@@ -519,15 +511,15 @@ export namespace Doc {
*/
export function assign<K extends string>(doc: Doc, fields: Partial<Record<K, Opt<FieldType>>>, skipUndefineds: boolean = false, isInitializing = false) {
isInitializing && (doc[Initializing] = true);
- for (const key in fields) {
- if (fields.hasOwnProperty(key)) {
- const value = fields[key];
+ Object.keys(fields).forEach(key => {
+ if (Object.prototype.hasOwnProperty.call(fields.hasOwnProperty, key)) {
+ const value = (fields as any)[key];
if (!skipUndefineds || value !== undefined) {
// Do we want to filter out undefineds?
doc[key] = value;
}
}
- }
+ });
isInitializing && (doc[Initializing] = false);
return doc;
}
@@ -640,7 +632,7 @@ export namespace Doc {
embedding.createdFrom = doc;
embedding.proto_embeddingId = doc[DocData].proto_embeddingId = Doc.GetEmbeddings(doc).length - 1;
!Doc.GetT(embedding, 'title', 'string', true) && (embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`));
- embedding.author = ClientUtils.CurrentUserEmail;
+ embedding.author = ClientUtils.CurrentUserEmail();
return embedding;
}
@@ -648,7 +640,7 @@ export namespace Doc {
export function BestEmbedding(doc: Doc) {
const dataDoc = doc[DocData];
const availableEmbeddings = Doc.GetEmbeddings(dataDoc);
- const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === ClientUtils.CurrentUserEmail);
+ const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === ClientUtils.CurrentUserEmail());
bestEmbedding && Doc.AddEmbedding(doc, doc);
return bestEmbedding ?? Doc.MakeEmbedding(doc);
}
@@ -708,7 +700,7 @@ export namespace Doc {
};
const docAtKey = doc[key];
if (key === 'author') {
- assignKey(ClientUtils.CurrentUserEmail);
+ assignKey(ClientUtils.CurrentUserEmail());
} else if (docAtKey instanceof Doc) {
if (pruneDocs.includes(docAtKey)) {
// prune doc and do nothing
@@ -717,7 +709,7 @@ export namespace Doc {
(key.includes('layout[') ||
key.startsWith('layout') || //
['embedContainer', 'annotationOn', 'proto'].includes(key) ||
- (['link_anchor_1', 'link_anchor_2'].includes(key) && doc.author === ClientUtils.CurrentUserEmail))
+ (['link_anchor_1', 'link_anchor_2'].includes(key) && doc.author === ClientUtils.CurrentUserEmail()))
) {
assignKey(await Doc.makeClone(docAtKey, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates));
} else {
@@ -886,7 +878,7 @@ export namespace Doc {
}
} else {
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
- const field = key === 'author' ? ClientUtils.CurrentUserEmail : ProxyField.WithoutProxy(() => doc[key]);
+ const field = key === 'author' ? ClientUtils.CurrentUserEmail() : ProxyField.WithoutProxy(() => doc[key]);
if (field instanceof RefField) {
if (field instanceof Doc) {
if (key === 'myLinkDatabase') {
@@ -934,7 +926,7 @@ export namespace Doc {
}
} else {
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
- const field = key === 'author' ? ClientUtils.CurrentUserEmail : ProxyField.WithoutProxy(() => doc[key]);
+ const field = key === 'author' ? ClientUtils.CurrentUserEmail() : ProxyField.WithoutProxy(() => doc[key]);
if (field instanceof RefField) {
copy[key] = field;
} else if (cfield instanceof ComputedField) {
@@ -973,7 +965,7 @@ export namespace Doc {
delegate[Initializing] = true;
updateCachedAcls(delegate);
delegate.proto = doc;
- delegate.author = ClientUtils.CurrentUserEmail;
+ delegate.author = ClientUtils.CurrentUserEmail();
Object.keys(doc)
.filter(key => key.startsWith('acl'))
.forEach(key => {
@@ -1004,7 +996,7 @@ export namespace Doc {
export function ApplyTemplate(templateDoc: Doc) {
if (templateDoc) {
const proto = new Doc();
- proto.author = ClientUtils.CurrentUserEmail;
+ proto.author = ClientUtils.CurrentUserEmail();
const target = Doc.MakeDelegate(proto);
const targetKey = StrCast(templateDoc.layout_fieldKey, 'layout');
const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + '(...' + _applyCount++ + ')');
@@ -1199,7 +1191,8 @@ export namespace Doc {
}
const UnhighlightWatchers: (() => void)[] = [];
- export let UnhighlightTimer: any;
+ let UnhighlightTimer: any;
+ export function IsUnhighlightTimerSet() { return UnhighlightTimer; } // prettier-ignore
export function AddUnHighlightWatcher(watcher: () => void) {
if (UnhighlightTimer) {
UnhighlightWatchers.push(watcher);
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 5ed10cf05..d7268f31a 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -84,7 +84,7 @@ const _setterImpl = action((target: any, prop: string | symbol | number, valueIn
const writeMode = DocServer.getFieldWriteMode(prop as string);
const fromServer = target[UpdatingFromServer];
- const sameAuthor = fromServer || receiver.author === ClientUtils.CurrentUserEmail;
+ const sameAuthor = fromServer || receiver.author === ClientUtils.CurrentUserEmail();
const writeToDoc =
sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || writeMode === DocServer.WriteMode.Playground || writeMode === DocServer.WriteMode.LivePlayground || (effectiveAcl === AclAugment && value instanceof RichTextField);
const writeToServer =
@@ -163,7 +163,7 @@ const getEffectiveAclCache = computedFn((target: any, user?: string) => getEffec
*/
export function GetEffectiveAcl(target: any, user?: string): symbol {
if (!target) return AclPrivate;
- if (target[UpdatingFromServer] || ClientUtils.CurrentUserEmail === 'guest') return AclAdmin;
+ if (target[UpdatingFromServer] || ClientUtils.CurrentUserEmail() === 'guest') return AclAdmin;
return getEffectiveAclCache(target, user); // all changes received from the server must be processed as Admin. return this directly so that the acls aren't cached (UpdatingFromServer is not observable)
}
@@ -186,7 +186,7 @@ function getEffectiveAcl(target: any, user?: string): symbol {
const targetAcls = target[DocAcl];
if (targetAcls?.['acl-Me'] === AclAdmin || GetCachedGroupByName('Admin')) return AclAdmin;
- const userChecked = user || ClientUtils.CurrentUserEmail; // if the current user is the author of the document / the current user is a member of the admin group
+ const userChecked = user || ClientUtils.CurrentUserEmail(); // if the current user is the author of the document / the current user is a member of the admin group
if (targetAcls && Object.keys(targetAcls).length) {
let effectiveAcl = AclPrivate;
Object.entries(targetAcls).forEach(([key, value]) => {
@@ -219,7 +219,7 @@ function getEffectiveAcl(target: any, user?: string): symbol {
*/
// eslint-disable-next-line default-param-last
export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, visited: Doc[] = [], allowUpgrade?: boolean, layoutOnly = false) {
- const selfKey = `acl-${normalizeEmail(ClientUtils.CurrentUserEmail)}`;
+ const selfKey = `acl-${normalizeEmail(ClientUtils.CurrentUserEmail())}`;
if (!target || visited.includes(target) || key === selfKey) return;
visited.push(target);
@@ -268,7 +268,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
* Copies parent's acl fields to the child
*/
export function inheritParentAcls(parent: Doc, child: Doc, layoutOnly: boolean) {
- [...Object.keys(parent), ...(ClientUtils.CurrentUserEmail !== parent.author ? ['acl-Owner'] : [])]
+ [...Object.keys(parent), ...(ClientUtils.CurrentUserEmail() !== parent.author ? ['acl-Owner'] : [])]
.filter(key => key.startsWith('acl'))
.forEach(key => {
// if the default acl mode is private, then don't inherit the acl-guest permission, but set it to private.