aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/PropertiesView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r--src/client/views/PropertiesView.tsx1160
1 files changed, 627 insertions, 533 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index ae29382c1..e4ca3daeb 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1,3 +1,6 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable prettier/prettier */
import { IconLookup } from '@fortawesome/fontawesome-svg-core';
import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -8,9 +11,10 @@ import { IReactionDisposer, action, computed, makeObservable, observable, reacti
import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorResult, SketchPicker } from 'react-color';
-import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils';
-import { Doc, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
+import * as Icons from 'react-icons/bs'; // {BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
+import { Doc, Field, FieldResult, FieldType, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { InkField } from '../../fields/InkField';
@@ -19,10 +23,8 @@ import { ComputedField } from '../../fields/ScriptField';
import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
-import { DocumentManager } from '../util/DocumentManager';
import { GroupManager } from '../util/GroupManager';
import { LinkManager } from '../util/LinkManager';
-import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
import { Transform } from '../util/Transform';
@@ -36,11 +38,12 @@ import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector
import { PropertiesDocContextSelector } from './PropertiesDocContextSelector';
import { PropertiesSection } from './PropertiesSection';
import './PropertiesView.scss';
-import { DefaultStyleProvider } from './StyleProvider';
-import { DocumentView, OpenWhere } from './nodes/DocumentView';
+import { DefaultStyleProvider, SetFilterOpener as SetPropertiesFilterOpener } from './StyleProvider';
+import { DocumentView } from './nodes/DocumentView';
import { StyleProviderFuncType } from './nodes/FieldView';
-import { KeyValueBox } from './nodes/KeyValueBox';
+import { OpenWhere } from './nodes/OpenWhere';
import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
+
const _global = (window /* browser */ || global) /* node */ as any;
interface PropertiesViewProps {
@@ -54,11 +57,18 @@ interface PropertiesViewProps {
export class PropertiesView extends ObservableReactComponent<PropertiesViewProps> {
private _widthUndo?: UndoManager.Batch;
+ // eslint-disable-next-line no-use-before-define
public static Instance: PropertiesView | undefined;
constructor(props: any) {
super(props);
makeObservable(this);
PropertiesView.Instance = this;
+ SetPropertiesFilterOpener(
+ action(() => {
+ this.CloseAll();
+ this.openFilters = true;
+ })
+ );
}
@computed get MAX_EMBED_HEIGHT() {
@@ -66,7 +76,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get selectedDoc() {
- return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
+ return DocumentView.SelectedSchemaDoc() || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
}
@computed get selectedLink() {
@@ -74,12 +84,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get selectedLayoutDoc() {
- return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
+ return DocumentView.SelectedSchemaDoc() || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
}
@computed get selectedDocumentView() {
- if (SelectionManager.Views.length) return SelectionManager.Views[0];
- if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.Document);
- return undefined;
+ return DocumentView.Selected().lastElement();
}
@computed get isPres(): boolean {
return this.selectedDoc?.type === DocumentType.PRES;
@@ -101,14 +109,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable openTransform: boolean = true;
@observable openFilters: boolean = false;
- //Pres Trails booleans:
+ // Pres Trails booleans:
@observable openPresTransitions: boolean = true;
@observable openPresProgressivize: boolean = false;
@observable openPresVisibilityAndDuration: boolean = false;
@observable openAddSlide: boolean = false;
@observable openSlideOptions: boolean = false;
- @observable inOptions: boolean = false;
@observable _controlButton: boolean = false;
private _disposers: { [name: string]: IReactionDisposer } = {};
@@ -176,42 +183,47 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const rows: JSX.Element[] = [];
if (this.dataDoc && this.selectedDoc) {
const ids = new Set<string>(reqdKeys);
- const docs: Doc[] = SelectionManager.Views.length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ const docs: Doc[] =
+ DocumentView.Selected().length < 2 //
+ ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc]
+ : DocumentView.Selected().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
docs.forEach(doc =>
Object.keys(doc)
.filter(filter)
.forEach(key => doc[key] !== ComputedField.undefined && key && ids.add(key))
);
- // prettier-ignore
- Array.from(ids).sort().map(key => {
- const multiple = Array.from(docs.reduce((set,doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
- const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
- const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as Field);
- const contentElement = (
- <EditableView
- key="editableView"
- contents={displayContents}
- height={13}
- fontSize={10}
- GetValue={() => editableContents}
- SetValue={(value: string) => {
- value !== '-multiple-' && docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />);
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- });
+ Array.from(ids)
+ .sort()
+ .forEach(key => {
+ const multiple = Array.from(docs.reduce((set, doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
+ const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
+ const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as FieldType);
+ const contentElement = (
+ <EditableView
+ key="editableView"
+ contents={displayContents}
+ height={13}
+ fontSize={10}
+ GetValue={() => editableContents}
+ SetValue={(value: string) => {
+ value !== '-multiple-' && docs.map(doc => Doc.SetField(doc, key, value, true));
+ return true;
+ }}
+ />
+ );
+ rows.push(
+ <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
+ <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
+ &nbsp;
+ {contentElement}
+ </div>
+ );
+ });
rows.push(
<div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.userBackgroundColor, textAlign: 'center' }}>
- <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
+ <EditableView key="editableView" oneLine contents="add key:value or #tags" height={13} fontSize={10} GetValue={returnEmptyString} SetValue={this.setKeyValue} />
</div>
);
}
@@ -224,23 +236,29 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get noviceFields() {
const noviceReqFields = ['author', 'author_date', 'tags', '_layout_curPage'];
- return this.editableFields(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl')), noviceReqFields);
+ return this.editableFields(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('acl_')), noviceReqFields);
}
@undoBatch
setKeyValue = (value: string) => {
- const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+ const docs =
+ DocumentView.Selected().length < 2 && this.selectedDoc
+ ? [this.layoutFields
+ ? Doc.Layout(this.selectedDoc) //
+ : this.dataDoc!]
+ : DocumentView.Selected().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc)); // prettier-ignore
docs.forEach(doc => {
if (value.indexOf(':') !== -1) {
const newVal = value[0].toUpperCase() + value.substring(1, value.length);
const splits = newVal.split(':');
- KeyValueBox.SetField(doc, splits[0], splits[1], true);
+ Doc.SetField(doc, splits[0], splits[1], true);
const tags = StrCast(doc.tags, ':');
if (tags.includes(`${splits[0]}:`) && splits[1] === 'undefined') {
- KeyValueBox.SetField(doc, 'tags', `"${tags.replace(splits[0] + ':', '')}"`, true);
+ Doc.SetField(doc, 'tags', `"${tags.replace(splits[0] + ':', '')}"`, true);
}
return true;
- } else if (value[0] === '#') {
+ }
+ if (value[0] === '#') {
const tags = StrListCast(doc.tags);
if (!tags.includes(value)) {
tags.push(value);
@@ -248,6 +266,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
return true;
}
+ return undefined;
});
return false;
};
@@ -255,44 +274,43 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable transform: Transform = Transform.Identity();
getTransform = () => this.transform;
propertiesDocViewRef = (ref: HTMLDivElement) => {
- const observer = new _global.ResizeObserver(
- action((entries: any) => {
+ const resizeObserver = new _global.ResizeObserver(
+ action(() => {
const cliRect = ref.getBoundingClientRect();
this.transform = new Transform(-cliRect.x, -cliRect.y, 1);
})
);
- ref && observer.observe(ref);
+ ref && resizeObserver.observe(ref);
};
@computed get contexts() {
- return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this._props.addDocTab} />;
+ return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle addDocTab={this._props.addDocTab} />;
}
@computed get contextCount() {
if (this.selectedDocumentView) {
const target = this.selectedDocumentView.Document;
return Doc.GetEmbeddings(target).length - 1;
- } else {
- return 0;
}
+ return 0;
}
@computed get links() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor ?? this.selectedDoc;
- return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this._props.addDocTab} />;
+ return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle addDocTab={this._props.addDocTab} />;
}
@computed get linkCount() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor ?? this.selectedDoc;
- var counter = 0;
+ let counter = 0;
- LinkManager.Links(selAnchor).forEach((l, i) => counter++);
+ Doc.Links(selAnchor).forEach(() => counter++);
return counter;
}
@computed get layoutPreview() {
- if (SelectionManager.Views.length > 1) {
+ if (DocumentView.Selected().length > 1) {
return '-- multiple selected --';
}
if (this.selectedDoc) {
@@ -308,7 +326,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
fitContentsToBox={returnTrue}
styleProvider={DefaultStyleProvider}
containerViewPath={returnEmptyDoclist}
- dontCenter={'y'}
+ dontCenter="y"
isDocumentActive={returnFalse}
isContentActive={emptyFunction}
NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
@@ -326,13 +344,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
whenChildContentsActiveChanged={emptyFunction}
addDocTab={returnFalse}
pinToPres={emptyFunction}
- dontRegisterView={true}
+ dontRegisterView
/>
</div>
);
- } else {
- return null;
}
+ return null;
}
/**
@@ -340,7 +357,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
*/
@undoBatch
changePermissions = (e: any, user: string) => {
- const docs = SelectionManager.Views.length < 2 ? [this.selectedDoc] : SelectionManager.Views.map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
+ const docs = DocumentView.Selected().length < 2 ? [this.selectedDoc] : DocumentView.Selected().map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls);
};
@@ -352,9 +369,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
if (permission === '-multiple-') dropdownValues.unshift(permission);
return (
<select className="propertiesView-permissions-select" value={permission} onChange={e => this.changePermissions(e, user)}>
- {dropdownValues.map(permission => (
- <option className="propertiesView-permisssions-select" key={permission} value={permission}>
- {concat(ReverseHierarchyMap.get(permission)?.image, ' ', permission)}
+ {dropdownValues.map(permissionVal => (
+ <option className="propertiesView-permisssions-select" key={permissionVal} value={permissionVal}>
+ {concat(ReverseHierarchyMap.get(permissionVal)?.image, ' ', permissionVal)}
</option>
))}
</select>
@@ -381,7 +398,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<div className="expansion-button">
<IconButton
- icon={<FontAwesomeIcon icon={'ellipsis-h'} />}
+ icon={<FontAwesomeIcon icon="ellipsis-h" />}
size={Size.XSMALL}
color={SettingsManager.userColor}
onClick={action(() => {
@@ -397,10 +414,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
/**
* @returns a row of the permissions panel
*/
- sharingItem(name: string, admin: boolean, permission: string, showExpansionIcon?: boolean) {
- if (name == Doc.CurrentUserEmail) {
- name = 'Me';
- }
+ sharingItem(nameIn: string, admin: boolean, permission: string, showExpansionIcon?: boolean) {
+ const name = nameIn === ClientUtils.CurrentUserEmail() ? 'Me' : nameIn;
return (
<div
className="propertiesView-sharingTable-item"
@@ -415,7 +430,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
{/* {name !== "Me" ? this.notifyIcon : null} */}
<div className="propertiesView-sharingTable-item-permission">
{this.colorACLDropDown(name, admin, permission, false)}
- {(permission === 'Owner' && name == 'Me') || showExpansionIcon ? this.expansionIcon : null}
+ {(permission === 'Owner' && name === 'Me') || showExpansionIcon ? this.expansionIcon : null}
</div>
</div>
);
@@ -425,10 +440,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
* @returns a colored dropdown bar reflective of the permission
*/
colorACLDropDown(name: string, admin: boolean, permission: string, showGuestOptions: boolean) {
- var shareImage = ReverseHierarchyMap.get(permission)?.image;
+ const shareImage = ReverseHierarchyMap.get(permission)?.image;
return (
<div>
- <div className={'propertiesView-shareDropDown'}>
+ <div className="propertiesView-shareDropDown">
<div className={`propertiesView-shareDropDown${permission}`}>
<div>{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div>
</div>
@@ -440,9 +455,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
/**
* Sorting algorithm to sort users.
*/
- sortUsers = (u1: String, u2: String) => {
- return u1 > u2 ? -1 : u1 === u2 ? 0 : 1;
- };
+ sortUsers = (u1: String, u2: String) => (u1 > u2 ? -1 : u1 === u2 ? 0 : 1);
/**
* Sorting algorithm to sort groups.
@@ -458,45 +471,45 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
*/
@computed get sharingTable() {
// all selected docs
- const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views.map(docView => docView.Document);
+ const docs = DocumentView.Selected().length < 2 && this.selectedDoc ? [this.selectedDoc] : DocumentView.SelectedDocs();
const target = docs[0];
- const showAdmin = GetEffectiveAcl(target) == AclAdmin;
+ const showAdmin = GetEffectiveAcl(target) === AclAdmin;
const individualTableEntries = [];
const usersAdded: string[] = []; // all shared users being added - organized by denormalized email
const seldoc = this.layoutDocAcls ? this.selectedLayoutDoc : this.selectedDoc?.[DocData];
// adds each user to usersAdded
SharingManager.Instance.users.forEach(eachUser => {
- var userOnDoc = true;
+ let userOnDoc = true;
if (seldoc) {
- if (Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === '' || Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === undefined) {
+ if (Doc.GetT(seldoc, 'acl_' + normalizeEmail(eachUser.user.email), 'string', true) === '' || Doc.GetT(seldoc, 'acl_' + normalizeEmail(eachUser.user.email), 'string', true) === undefined) {
userOnDoc = false;
}
}
- if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email !== 'guest' && eachUser.user.email != target.author) {
+ if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email !== 'guest' && eachUser.user.email !== target.author) {
usersAdded.push(eachUser.user.email);
}
});
// sorts and then adds each user to the table
usersAdded.sort(this.sortUsers);
- usersAdded.map(userEmail => {
- const userKey = `acl-${normalizeEmail(userEmail)}`;
- var aclField = Doc.GetT(this.layoutDocAcls ? target : Doc.GetProto(target), userKey, 'string', true);
- var permission = StrCast(aclField);
+ usersAdded.forEach(userEmail => {
+ const userKey = `acl_${normalizeEmail(userEmail)}`;
+ const aclField = Doc.GetT(this.layoutDocAcls ? target : Doc.GetProto(target), userKey, 'string', true);
+ const permission = StrCast(aclField);
individualTableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission!, false)); // adds each user
});
// adds current user
- var userEmail = Doc.CurrentUserEmail;
- if (userEmail == 'guest') userEmail = 'Guest';
- const userKey = `acl-${normalizeEmail(userEmail)}`;
- if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail != target.author) {
- var permission;
+ let userEmail = ClientUtils.CurrentUserEmail();
+ if (userEmail === 'guest') userEmail = 'Guest';
+ const userKey = `acl_${normalizeEmail(userEmail)}`;
+ if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail !== target.author) {
+ let permission;
if (this.layoutDocAcls) {
if (target[DocAcl][userKey]) permission = HierarchyMapping.get(target[DocAcl][userKey])?.name;
- else if (target['embedContainer']) permission = StrCast(Doc.GetProto(DocCast(target['embedContainer']))[userKey]);
+ else if (target.embedContainer) permission = StrCast(Doc.GetProto(DocCast(target.embedContainer))[userKey]);
else permission = StrCast(Doc.GetProto(target)?.[userKey]);
} else permission = StrCast(target[userKey]);
individualTableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission!, false)); // adds each user
@@ -509,15 +522,15 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const groupTableEntries: JSX.Element[] = [];
const groupList = GroupManager.Instance?.allGroups || [];
groupList.sort(this.sortGroups);
- groupList.map(group => {
- if (group.title != 'Guest' && this.selectedDoc) {
- const groupKey = 'acl-' + normalizeEmail(StrCast(group.title));
- if (this.selectedDoc[groupKey] != '' && this.selectedDoc[groupKey] != undefined) {
- var permission;
+ groupList.forEach(group => {
+ if (group.title !== 'Guest' && this.selectedDoc) {
+ const groupKey = 'acl_' + normalizeEmail(StrCast(group.title));
+ if (this.selectedDoc[groupKey] !== '' && this.selectedDoc[groupKey] !== undefined) {
+ let permission;
if (this.layoutDocAcls) {
if (target[DocAcl][groupKey]) {
permission = HierarchyMapping.get(target[DocAcl][groupKey])?.name;
- } else if (target['embedContainer']) permission = StrCast(Doc.GetProto(DocCast(target['embedContainer']))[groupKey]);
+ } else if (target.embedContainer) permission = StrCast(Doc.GetProto(DocCast(target.embedContainer))[groupKey]);
else permission = StrCast(Doc.GetProto(target)?.[groupKey]);
} else permission = StrCast(target[groupKey]);
groupTableEntries.unshift(this.sharingItem(StrCast(group.title), showAdmin, permission!, false));
@@ -526,27 +539,27 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
});
// guest permission
- const guestPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target))['acl-Guest']);
+ const guestPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target)).acl_Guest);
return (
<div>
<div>
- <br></br> Individuals with Access to this Document
+ <br /> Individuals with Access to this Document
</div>
<div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
- {<div> {individualTableEntries}</div>}
+ <div> {individualTableEntries}</div>
</div>
{groupTableEntries.length > 0 ? (
<div>
<div>
- <br></br> Groups with Access to this Document
+ <br /> Groups with Access to this Document
</div>
<div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
- {<div> {groupTableEntries}</div>}
+ <div> {groupTableEntries}</div>
</div>
</div>
) : null}
- <br></br> Guest
+ <br /> Guest
<div>{this.colorACLDropDown('Guest', showAdmin, guestPermission!, true)}</div>
</div>
);
@@ -558,7 +571,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@action
- toggleCheckbox = () => (this.layoutFields = !this.layoutFields);
+ toggleCheckbox = () => {
+ this.layoutFields = !this.layoutFields;
+ };
@computed get color() {
return SettingsManager.userColor;
@@ -574,25 +589,21 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get editableTitle() {
const titles = new Set<string>();
- SelectionManager.Views.forEach(dv => titles.add(StrCast(dv.Document.title)));
+ DocumentView.Selected().forEach(dv => titles.add(StrCast(dv.Document.title)));
const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
return (
<div>
- <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />
+ <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel="Title" fillWidth />
{LinkManager.Instance.currentLinkAnchor ? (
<p className="propertiesView-titleExtender">
- <>
- <b>Anchor:</b>
- {LinkManager.Instance.currentLinkAnchor.title}
- </>
+ <b>Anchor:</b>
+ {StrCast(LinkManager.Instance.currentLinkAnchor.title)}
</p>
) : null}
{this.selectedLink?.title ? (
<p className="propertiesView-titleExtender">
- <>
- <b>Link:</b>
- {this.selectedLink.title}
- </>
+ <b>Link:</b>
+ {StrCast(this.selectedLink.title)}
</p>
) : null}
</div>
@@ -600,9 +611,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get currentType() {
- const documentType = StrCast(this.selectedDoc?.type);
- var currentType: string = documentType;
- var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType);
+ const docType = StrCast(this.selectedDoc?.type) as DocumentType;
+ const colType = StrCast(this.selectedDoc?.type_collection) as CollectionViewType;
+ const capitalizedDocType = ClientUtils.cleanDocumentType(docType, colType);
return (
<div>
@@ -618,7 +629,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get currentComponent() {
- var iconName = StrCast(this.selectedDoc?.systemIcon);
+ const iconName = StrCast(this.selectedDoc?.systemIcon);
if (iconName) {
const Icon = Icons[iconName as keyof typeof Icons];
@@ -629,11 +640,11 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@undoBatch
setTitle = (value: string | number) => {
- if (SelectionManager.Views.length > 1) {
- SelectionManager.Views.map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
+ if (DocumentView.Selected().length > 1) {
+ DocumentView.Selected().map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
} else if (this.dataDoc) {
if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true);
- else KeyValueBox.SetField(this.dataDoc, 'title', value as string, true);
+ else Doc.SetField(this.dataDoc, 'title', value as string, true);
}
};
@@ -650,13 +661,11 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const ys = ink.map(p => p.Y);
const left = Math.min(...xs);
const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
_centerPoints.push({ X: left, Y: top });
}
}
- var index = 0;
+ let index = 0;
if (doc.type === DocumentType.INK && doc.x && doc.y && layout._width && layout._height && doc.data) {
layout.rotation = NumCast(layout.rotation) + angle;
const inks = Cast(doc.stroke, InkField)?.inkData;
@@ -687,11 +696,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
get controlPointsButton() {
return (
<div className="inking-button">
- <Tooltip title={<div className="dash-tooltip">{'Edit points'}</div>}>
+ <Tooltip title={<div className="dash-tooltip">Edit points</div>}>
<div
className="inking-button-points"
style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? 'black' : '' }}
- onPointerDown={action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton))}>
+ onPointerDown={action(() => {
+ InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton;
+ })}>
<FontAwesomeIcon icon="bezier-curve" size="lg" />
</div>
</Tooltip>
@@ -699,152 +710,129 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => {
- return (
- <div
- className="inputBox"
- style={{
- marginRight: title === 'X:' ? '19px' : '',
- marginLeft: title === '∠:' ? '39px' : '',
- }}>
- <div className="inputBox-title"> {title} </div>
- <input
- className="inputBox-input"
- type="text"
- value={value}
- style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
- onChange={e => setter(e.target.value)}
- onKeyDown={e => e.stopPropagation()}
- />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
- <FontAwesomeIcon icon="caret-up" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
- <FontAwesomeIcon icon="caret-down" size="sm" />
- </div>
+ inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => (
+ <div
+ className="inputBox"
+ style={{
+ marginRight: title === 'X:' ? '19px' : '',
+ marginLeft: title === '∠:' ? '39px' : '',
+ }}>
+ <div className="inputBox-title"> {title} </div>
+ <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} onKeyDown={e => e.stopPropagation()} />
+ <div className="inputBox-button">
+ <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <FontAwesomeIcon icon="caret-up" size="sm" />
+ </div>
+ <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
- );
- };
+ </div>
+ );
- inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
- return (
- <div className="inputBox-duo">
- {this.inputBox(key, value, setter, title1)}
- {title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)}
- </div>
- );
- };
+ inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => (
+ <div className="inputBox-duo">
+ {this.inputBox(key, value, setter, title1)}
+ {title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)}
+ </div>
+ );
@action
upDownButtons = (dirs: string, field: string) => {
const selDoc = this.selectedDoc;
if (!selDoc) return;
- //prettier-ignore
+ // prettier-ignore
switch (field) {
case 'Xps': selDoc.x = NumCast(this.selectedDoc?.x) + (dirs === 'up' ? 10 : -10); break;
case 'Yps': selDoc.y = NumCast(this.selectedDoc?.y) + (dirs === 'up' ? 10 : -10); break;
case 'stk': selDoc.stroke_width = NumCast(this.selectedDoc?.[DocData].stroke_width) + (dirs === 'up' ? 0.1 : -0.1); break;
- case 'wid':
- const oldWidth = NumCast(selDoc._width);
- const oldHeight = NumCast(selDoc._height);
- const oldX = NumCast(selDoc.x);
- const oldY = NumCast(selDoc.y);
- selDoc._width = oldWidth + (dirs === 'up' ? 10 : -10);
- if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
- const ink = Cast(selDoc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number; Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = NumCast(selDoc.x) - oldX + (ink[j].X * NumCast(selDoc._width)) / oldWidth;
- const newY = NumCast(selDoc.y) - oldY + (ink[j].Y * NumCast(selDoc._height)) / oldHeight;
- newPoints.push({ X: newX, Y: newY });
+ case 'wid': {
+ const oldWidth = NumCast(selDoc._width);
+ const oldHeight = NumCast(selDoc._height);
+ const oldX = NumCast(selDoc.x);
+ const oldY = NumCast(selDoc.y);
+ selDoc._width = oldWidth + (dirs === 'up' ? 10 : -10);
+ if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
+ const ink = Cast(selDoc.data, InkField)?.inkData;
+ if (ink) {
+ const newPoints: { X: number; Y: number }[] = [];
+ for (let j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = NumCast(selDoc.x) - oldX + (ink[j].X * NumCast(selDoc._width)) / oldWidth;
+ const newY = NumCast(selDoc.y) - oldY + (ink[j].Y * NumCast(selDoc._height)) / oldHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ selDoc.data = new InkField(newPoints);
}
- selDoc.data = new InkField(newPoints);
}
}
break;
- case 'hgt':
- const oWidth = NumCast(selDoc._width);
- const oHeight = NumCast(selDoc._height);
- const oX = NumCast(selDoc.x);
- const oY = NumCast(selDoc.y);
- selDoc._height = oHeight + (dirs === 'up' ? 10 : -10);
- if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
- const ink = Cast(selDoc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number; Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = NumCast(selDoc.x) - oX + (ink[j].X * NumCast(selDoc._width)) / oWidth;
- const newY = NumCast(selDoc.y) - oY + (ink[j].Y * NumCast(selDoc._height)) / oHeight;
- newPoints.push({ X: newX, Y: newY });
+ case 'hgt': {
+ const oWidth = NumCast(selDoc._width);
+ const oHeight = NumCast(selDoc._height);
+ const oX = NumCast(selDoc.x);
+ const oY = NumCast(selDoc.y);
+ selDoc._height = oHeight + (dirs === 'up' ? 10 : -10);
+ if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
+ const ink = Cast(selDoc.data, InkField)?.inkData;
+ if (ink) {
+ const newPoints: { X: number; Y: number }[] = [];
+ for (let j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = NumCast(selDoc.x) - oX + (ink[j].X * NumCast(selDoc._width)) / oWidth;
+ const newY = NumCast(selDoc.y) - oY + (ink[j].Y * NumCast(selDoc._height)) / oHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ selDoc.data = new InkField(newPoints);
}
- selDoc.data = new InkField(newPoints);
}
}
break;
+ default: { /* empty */ }
}
};
getField(key: string) {
- return Field.toString(this.selectedDoc?.[DocData][key] as Field);
+ return Field.toString(this.selectedDoc?.[DocData][key] as FieldType);
}
- @computed get shapeXps() {
- return NumCast(this.selectedDoc?.x);
- }
- @computed get shapeYps() {
- return NumCast(this.selectedDoc?.y);
- }
- @computed get shapeHgt() {
- return NumCast(this.selectedDoc?._height);
- }
- @computed get shapeWid() {
- return NumCast(this.selectedDoc?._width);
- }
- @computed get strokeThk() {
- return NumCast(this.selectedDoc?.[DocData].stroke_width);
- }
- set shapeXps(value) {
- this.selectedDoc && (this.selectedDoc.x = Math.round(value * 100) / 100);
- }
- set shapeYps(value) {
- this.selectedDoc && (this.selectedDoc.y = Math.round(value * 100) / 100);
- }
- set shapeWid(value) {
- this.selectedDoc && (this.selectedDoc._width = Math.round(value * 100) / 100);
- }
- set shapeHgt(value) {
- this.selectedDoc && (this.selectedDoc._height = Math.round(value * 100) / 100);
- }
- set strokeThk(value) {
- this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Math.round(value * 100) / 100);
- }
+ @computed get shapeXps() { return NumCast(this.selectedDoc?.x); } // prettier-ignore
+ set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeYps() { return NumCast(this.selectedDoc?.y); } // prettier-ignore
+ set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeWid() { return NumCast(this.selectedDoc?._width); } // prettier-ignore
+ set shapeWid(value) { this.selectedDoc && (this.selectedDoc._width = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeHgt() { return NumCast(this.selectedDoc?._height); } // prettier-ignore
+ set shapeHgt(value) { this.selectedDoc && (this.selectedDoc._height = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get strokeThk(){ return NumCast(this.selectedDoc?.[DocData].stroke_width); } // prettier-ignore
+ set strokeThk(value) { this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Math.round(value * 100) / 100); } // prettier-ignore
@computed get hgtInput() {
return this.inputBoxDuo(
'hgt',
this.shapeHgt,
- undoable((val: string) => !isNaN(Number(val)) && (this.shapeHgt = +val), 'set height'),
+ undoable((val: string) => {
+ !Number(val) && (this.shapeHgt = +val);
+ }, 'set height'),
'H:',
'wid',
this.shapeWid,
- undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = +val), 'set width'),
+ undoable((val: string) => {
+ !isNaN(Number(val)) && (this.shapeWid = +val);
+ }, 'set width'),
'W:'
);
}
@computed get XpsInput() {
+ // prettier-ignore
return this.inputBoxDuo(
'Xps',
this.shapeXps,
- undoable((val: string) => val !== '0' && !isNaN(Number(val)) && (this.shapeXps = +val), 'set x coord'),
+ undoable((val: string) => { val !== '0' && !isNaN(Number(val)) && (this.shapeXps = +val); }, 'set x coord'),
'X:',
'Yps',
this.shapeYps,
- undoable((val: string) => val !== '0' && !isNaN(Number(val)) && (this.shapeYps = +val), 'set y coord'),
+ undoable((val: string) => { val !== '0' && !isNaN(Number(val)) && (this.shapeYps = +val); }, 'set y coord'),
'Y:'
);
}
@@ -854,22 +842,14 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
private _lastDash: any = '2';
- @computed get colorFil() {
- return StrCast(this.selectedDoc?.[DocData].fillColor);
- }
- @computed get colorStk() {
- return StrCast(this.selectedDoc?.[DocData].color);
- }
- set colorFil(value) {
- this.selectedDoc && (this.selectedDoc[DocData].fillColor = value ? value : undefined);
- }
- set colorStk(value) {
- this.selectedDoc && (this.selectedDoc[DocData].color = value ? value : undefined);
- }
+ @computed get colorFil() { return StrCast(this.selectedDoc?.[DocData].fillColor); } // prettier-ignore
+ set colorFil(value) { this.selectedDoc && (this.selectedDoc[DocData].fillColor = value || undefined); } // prettier-ignore
+ @computed get colorStk() { return StrCast(this.selectedDoc?.[DocData].color); } // prettier-ignore
+ set colorStk(value) { this.selectedDoc && (this.selectedDoc[DocData].color = value || undefined); } // prettier-ignore
colorButton(value: string, type: string, setter: () => void) {
return (
- <div className="color-button" key="color" onPointerDown={action(e => setter())}>
+ <div className="color-button" key="color" onPointerDown={action(() => setter())}>
<div
className="color-button-preview"
style={{
@@ -888,7 +868,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<SketchPicker
onChange={undoable(
- action((color: ColorResult) => setter(color.hex)),
+ action((col: ColorResult) => setter(col.hex)),
'set stroke color property'
)}
presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
@@ -911,10 +891,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get fillPicker() {
- return this.colorPicker(this.colorFil, (color: string) => (this.colorFil = color));
+ return this.colorPicker(this.colorFil, (color: string) => { this.colorFil = color; }); // prettier-ignore
}
@computed get linePicker() {
- return this.colorPicker(this.colorStk, (color: string) => (this.colorStk = color));
+ return this.colorPicker(this.colorStk, (color: string) => { this.colorStk = color; }); // prettier-ignore
}
@computed get strokeAndFill() {
@@ -936,60 +916,41 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- @computed get dashdStk() {
- return this.selectedDoc?.stroke_dash || '';
- }
- @computed get widthStk() {
- return this.getField('stroke_width') || '1';
- }
- @computed get markScal() {
- return Number(this.getField('stroke_markerScale') || '1');
- }
- @computed get markHead() {
- return this.getField('stroke_startMarker') || '';
- }
- @computed get markTail() {
- return this.getField('stroke_endMarker') || '';
- }
+ @computed get dashdStk() { return this.selectedDoc?.stroke_dash || ''; } // prettier-ignore
set dashdStk(value) {
value && (this._lastDash = value);
this.selectedDoc && (this.selectedDoc[DocData].stroke_dash = value ? this._lastDash : undefined);
}
- set markScal(value) {
- this.selectedDoc && (this.selectedDoc[DocData].stroke_markerScale = Number(value));
- }
+ @computed get widthStk() { return this.getField('stroke_width') || '1'; } // prettier-ignore
set widthStk(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Number(value));
}
+ @computed get markScal() { return Number(this.getField('stroke_markerScale') || '1'); } // prettier-ignore
+ set markScal(value) {
+ this.selectedDoc && (this.selectedDoc[DocData].stroke_markerScale = Number(value));
+ }
+ @computed get markHead() { return this.getField('stroke_startMarker') || ''; } // prettier-ignore
set markHead(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_startMarker = value);
}
+ @computed get markTail() { return this.getField('stroke_endMarker') || ''; } // prettier-ignore
set markTail(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_endMarker = value);
}
- @computed get stkInput() {
- return this.regInput('stk', this.widthStk, (val: string) => (this.widthStk = val));
- }
- @computed get markScaleInput() {
- return this.regInput('scale', this.markScal.toString(), (val: string) => (this.markScal = Number(val)));
- }
-
- regInput = (key: string, value: any, setter: (val: string) => {}) => {
- return (
- <div className="inputBox">
- <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
- <FontAwesomeIcon icon="caret-up" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
- <FontAwesomeIcon icon="caret-down" size="sm" />
- </div>
+ regInput = (key: string, value: any, setter: (val: string) => {}) => (
+ <div className="inputBox">
+ <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
+ <div className="inputBox-button">
+ <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <FontAwesomeIcon icon="caret-up" size="sm" />
+ </div>
+ <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
- );
- };
+ </div>
+ );
@action
CloseAll = () => {
@@ -1005,18 +966,55 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get widthAndDash() {
return (
+ // prettier-ignore
<div className="widthAndDash">
- <div className="width">{this.getNumber('Thickness', '', 0, Math.max(50, this.strokeThk), this.strokeThk, (val: number) => !isNaN(val) && (this.strokeThk = val), 50, 1)}</div>
- <div className="width">{this.getNumber('Arrow Scale', '', 0, Math.max(10, this.markScal), this.markScal, (val: number) => !isNaN(val) && (this.markScal = val), 10, 1)}</div>
+ <div className="width">
+ {this.getNumber(
+ 'Thickness',
+ '',
+ 0,
+ Math.max(50, this.strokeThk),
+ this.strokeThk,
+ (val: number) => { !isNaN(val) && (this.strokeThk = val); },
+ 50,
+ 1
+ )}
+ </div>
+ <div className="width">
+ {this.getNumber(
+ 'Arrow Scale',
+ '',
+ 0,
+ Math.max(10, this.markScal),
+ this.markScal,
+ (val: number) => { !isNaN(val) && (this.markScal = val); },
+ 10,
+ 1
+ )}
+ </div>
<div className="arrows">
<div className="arrows-head">
<div className="arrows-head-title">Arrow Head: </div>
- <input key="markHead" className="arrows-head-input" type="checkbox" checked={this.markHead !== ''} onChange={undoBatch(action(() => (this.markHead = this.markHead ? '' : 'arrow')))} />
+ <input
+ key="markHead"
+ className="arrows-head-input"
+ type="checkbox"
+ checked={this.markHead !== ''}
+ onChange={undoBatch(action(() => { this.markHead = this.markHead ? '' : 'arrow'; }))}
+ />
</div>
<div className="arrows-tail">
<div className="arrows-tail-title">Arrow End: </div>
- <input key="markTail" className="arrows-tail-input" type="checkbox" checked={this.markTail !== ''} onChange={undoBatch(action(() => (this.markTail = this.markTail ? '' : 'arrow')))} />
+ <input
+ key="markTail"
+ className="arrows-tail-input"
+ type="checkbox"
+ checked={this.markTail !== ''}
+ onChange={undoBatch(
+ action(() => { this.markTail = this.markTail ? '' : 'arrow'; })
+ )}
+ />
</div>
</div>
<div className="dashed">
@@ -1045,50 +1043,53 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
setFinalNumber = () => {
this._sliderBatch?.end();
};
- getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any, autorange?: number, autorangeMinVal?: number) => {
- return (
- <div key={label + this.selectedDoc?.title}>
- <NumberInput formLabel={label} formLabelPlacement={'left'} type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} />
- <Slider
- key={label}
- onPointerDown={e => (this._sliderBatch = UndoManager.StartBatch('slider ' + label))}
- multithumb={false}
- color={this.color}
- size={Size.XSMALL}
- min={min}
- max={max}
- autorangeMinVal={autorangeMinVal}
- autorange={autorange}
- number={number}
- unit={unit}
- decimals={1}
- setFinalNumber={this.setFinalNumber}
- setNumber={setNumber}
- fillWidth
- />
- </div>
- );
- };
+ getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any, autorange?: number, autorangeMinVal?: number) => (
+ <div key={label + (this.selectedDoc?.title ?? '')}>
+ <NumberInput formLabel={label} formLabelPlacement="left" type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} />
+ <Slider
+ key={label}
+ onPointerDown={() => {
+ this._sliderBatch = UndoManager.StartBatch('slider ' + label);
+ }}
+ multithumb={false}
+ color={this.color}
+ size={Size.XSMALL}
+ min={min}
+ max={max}
+ autorangeMinVal={autorangeMinVal}
+ autorange={autorange}
+ number={number}
+ unit={unit}
+ decimals={1}
+ setFinalNumber={this.setFinalNumber}
+ setNumber={setNumber}
+ fillWidth
+ />
+ </div>
+ );
+ setVal = (func: (doc: Doc, val: number) => void) => (val: number) => this.selectedDoc && !isNaN(val) && func(this.selectedDoc, val);
@computed get transformEditor() {
return (
+ // prettier-ignore
<div className="transform-editor">
- {!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.isStack ? null : this.getNumber('yMargin', ' px', 0, 500, NumCast(this.selectedDoc!.yMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.yMargin = val))}
- {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), (val: number) => !isNaN(val) && (this.selectedDoc!.xPadding = this.selectedDoc!.yPadding = val))}
+ {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), this.setVal((doc: Doc, val: number) => { doc.gridGap = val; })) }
+ {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), this.setVal((doc: Doc, val: number) => { doc.xMargin = val; })) }
+ {!this.isStack ? null : this.getNumber('yMargin', ' px', 0, 500, NumCast(this.selectedDoc!.yMargin), this.setVal((doc: Doc, val: number) => { doc.yMargin = val; })) }
+ {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), this.setVal((doc: Doc, val: number) => { doc.xPadding = doc.yPadding = 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)}
- {this.getNumber('X', ' px', this.shapeXps - 500, this.shapeXps + 500, this.shapeXps, (val: number) => !isNaN(val) && (this.shapeXps = val), 1000)}
- {this.getNumber('Y', ' px', this.shapeYps - 500, this.shapeYps + 500, this.shapeYps, (val: number) => !isNaN(val) && (this.shapeYps = val), 1000)}
+ {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, this.setVal((doc: Doc, val:number) => {this.shapeWid = val}), 1000, 1)}
+ {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, this.setVal((doc: Doc, val:number) => {this.shapeHgt = val}), 1000, 1)}
+ {this.getNumber('X', ' px', this.shapeXps - 500, this.shapeXps + 500, this.shapeXps, this.setVal((doc: Doc, val:number) => {this.shapeXps = val}), 1000)}
+ {this.getNumber('Y', ' px', this.shapeYps - 500, this.shapeYps + 500, this.shapeYps, this.setVal((doc: Doc, val:number) => {this.shapeYps = val}), 1000)}
</div>
);
}
@computed get optionsSubMenu() {
return (
- <PropertiesSection title="Options" inSection={this.inOptions} isOpen={this.openOptions} setInSection={bool => (this.inOptions = bool)} setIsOpen={bool => (this.openOptions = bool)} onDoubleClick={this.CloseAll}>
+ // prettier-ignore
+ <PropertiesSection title="Options" isOpen={this.openOptions} setIsOpen={bool => { this.openOptions = bool; }} onDoubleClick={this.CloseAll}>
<PropertiesButtons />
</PropertiesSection>
);
@@ -1096,12 +1097,23 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get sharingSubMenu() {
return (
- <PropertiesSection title="Sharing and Permissions" isOpen={this.openSharing} setIsOpen={bool => (this.openSharing = bool)} onDoubleClick={() => this.CloseAll()}>
+ // prettier-ignore
+ <PropertiesSection
+ title="Sharing and Permissions"
+ isOpen={this.openSharing}
+ setIsOpen={bool => { this.openSharing = bool; }}
+ onDoubleClick={this.CloseAll}>
<>
{/* <div className="propertiesView-buttonContainer"> */}
<div className="propertiesView-acls-checkbox">
Layout Permissions
- <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} />
+ <Checkbox
+ color="primary"
+ onChange={action(() => {
+ this.layoutDocAcls = !this.layoutDocAcls;
+ })}
+ checked={this.layoutDocAcls}
+ />
</div>
{/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}>
<button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}>
@@ -1141,7 +1153,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get filtersSubMenu() {
return (
- <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => (this.openFilters = bool)} onDoubleClick={() => this.CloseAll()}>
+ // prettier-ignore
+ <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => { this.openFilters = bool; }} onDoubleClick={this.CloseAll}>
<div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}>
<FilterPanel Document={this.selectedDoc ?? Doc.ActiveDashboard!} />
</div>
@@ -1151,11 +1164,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get inkSubMenu() {
return (
+ // prettier-ignore
<>
- <PropertiesSection title="Appearance" isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection title="Appearance" isOpen={this.openAppearance} setIsOpen={bool => { this.openAppearance = bool; }} onDoubleClick={this.CloseAll}>
{this.selectedLayoutDoc?.layout_isSvg ? this.appearanceEditor : null}
</PropertiesSection>
- <PropertiesSection title="Transform" isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection title="Transform" isOpen={this.openTransform} setIsOpen={bool => { this.openTransform = bool; }} onDoubleClick={this.CloseAll}>
{this.transformEditor}
</PropertiesSection>
</>
@@ -1164,7 +1178,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get fieldsSubMenu() {
return (
- <PropertiesSection title="Fields & Tags" isOpen={this.openFields} setIsOpen={bool => (this.openFields = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection
+ title="Fields & Tags"
+ isOpen={this.openFields}
+ setIsOpen={bool => {
+ this.openFields = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>
</PropertiesSection>
);
@@ -1172,7 +1192,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get contextsSubMenu() {
return (
- <PropertiesSection title="Other Contexts" isOpen={this.openContexts} setIsOpen={bool => (this.openContexts = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection
+ title="Other Contexts"
+ isOpen={this.openContexts}
+ setIsOpen={bool => {
+ this.openContexts = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.contextCount > 0 ? this.contexts : 'There are no other contexts.'}
</PropertiesSection>
);
@@ -1180,7 +1206,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get linksSubMenu() {
return (
- <PropertiesSection title="Linked To" isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.CloseAll}>
+ <PropertiesSection
+ title="Linked To"
+ isOpen={this.openLinks}
+ setIsOpen={bool => {
+ this.openLinks = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.linkCount > 0 ? this.links : 'There are no current links.'}
</PropertiesSection>
);
@@ -1188,14 +1220,20 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get layoutSubMenu() {
return (
- <PropertiesSection title="Layout" isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.CloseAll}>
+ <PropertiesSection
+ title="Layout"
+ isOpen={this.openLayout}
+ setIsOpen={bool => {
+ this.openLayout = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.layoutPreview}
</PropertiesSection>
);
}
@computed get description() {
- return Field.toString(this.selectedLink?.link_description as any as Field);
+ return Field.toString(this.selectedLink?.link_description as any as FieldType);
}
@computed get relationship() {
return StrCast(this.selectedLink?.link_relationship);
@@ -1250,12 +1288,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
// if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes
} else if (linkRelationshipList && value !== prevRelationship) {
const index = linkRelationshipList.indexOf(value);
- //increment size of new relationship size
+ // increment size of new relationship size
if (index !== -1 && index < linkRelationshipSizes.length) {
const pvalue = linkRelationshipSizes[index];
linkRelationshipSizes[index] = pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1;
}
- //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation)
+ // decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation)
if (linkRelationshipList.includes(prevRelationship)) {
const pindex = linkRelationshipList.indexOf(prevRelationship);
if (pindex !== -1 && pindex < linkRelationshipSizes.length) {
@@ -1265,21 +1303,25 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
}
this.relationshipButtonColor = 'rgb(62, 133, 55)';
- setTimeout(
- action(() => (this.relationshipButtonColor = '')),
- 750
- );
+ setTimeout(action(() => { this.relationshipButtonColor = ''; }), 750); // prettier-ignore
return true;
}
+ return undefined;
});
- changeFollowBehavior = undoable((loc: Opt<string>) => this.sourceAnchor && (this.sourceAnchor.followLinkLocation = loc), 'change follow behavior');
+ changeFollowBehavior = undoable((loc: Opt<string>) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkLocation = loc);
+ }, 'change follow behavior');
@undoBatch
- changeAnimationBehavior = action((behavior: string) => this.sourceAnchor && (this.sourceAnchor.followLinkAnimEffect = behavior));
+ changeAnimationBehavior = action((behavior: string) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkAnimEffect = behavior);
+ });
@undoBatch
- changeEffectDirection = action((effect: PresEffectDirection) => this.sourceAnchor && (this.sourceAnchor.followLinkAnimDirection = effect));
+ changeEffectDirection = action((effect: PresEffectDirection) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkAnimDirection = effect);
+ });
animationDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
const lanch = this.sourceAnchor;
@@ -1300,7 +1342,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
document.getElementById('link_description_input')?.blur();
};
- onDescriptionKey = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
+ onDescriptionKey = () => {
// if (e.key === 'Enter') {
// this.setDescripValue(this.description);
// document.getElementById('link_description_input')?.blur();
@@ -1320,20 +1362,26 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
};
toggleLinkProp = (e: React.PointerEvent, prop: string) => {
- setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]))));
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ undoBatch(action(() => { this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]); })) // prettier-ignore
+ );
};
@computed get destinationAnchor() {
const ldoc = this.selectedLink;
const lanch = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor;
- if (ldoc && lanch) return LinkManager.getOppositeAnchor(ldoc, lanch) ?? lanch;
+ if (ldoc && lanch) return Doc.getOppositeAnchor(ldoc, lanch) ?? lanch;
return ldoc ? DocCast(ldoc.link_anchor_2) : ldoc;
}
@computed get sourceAnchor() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor;
- return selAnchor ?? (this.selectedLink && this.destinationAnchor ? LinkManager.getOppositeAnchor(this.selectedLink, this.destinationAnchor) : this.selectedLink);
+ return selAnchor ?? (this.selectedLink && this.destinationAnchor ? Doc.getOppositeAnchor(this.selectedLink, this.destinationAnchor) : this.selectedLink);
}
toggleAnchorProp = (e: React.PointerEvent, prop: string, anchor?: Doc, value: any = true, ovalue: any = false, cb: (val: any) => any = val => val) => {
@@ -1343,12 +1391,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
e,
returnFalse,
emptyFunction,
- undoBatch(
- action(() => {
- anchor[prop] = anchor[prop] === value ? ovalue : value;
- this.selectedDoc && cb(anchor[prop]);
- })
- )
+ undoBatch(action(() => {
+ anchor[prop] = anchor[prop] === value ? ovalue : value;
+ this.selectedDoc && cb(anchor[prop]);
+ })) // prettier-ignore
);
};
@@ -1357,7 +1403,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<input
style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
- autoComplete={'off'}
+ autoComplete="off"
id="link_relationship_input"
value={StrCast(this.selectedLink?.link_relationship)}
onKeyDown={this.onRelationshipKey}
@@ -1398,7 +1444,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const zoom = Number((NumCast(this.sourceAnchor?.followLinkZoomScale, 1) * 100).toPrecision(3));
const targZoom = this.sourceAnchor?.followLinkZoom;
const indent = 30;
- const hasSelectedAnchor = this.selectedLink !== this.selectedDoc && LinkManager.Links(this.sourceAnchor).includes(this.selectedLink!);
+ const hasSelectedAnchor = this.selectedLink !== this.selectedDoc && Doc.Links(this.sourceAnchor).includes(this.selectedLink!);
return (
<>
@@ -1425,7 +1471,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<option value={OpenWhere.addRight}>Opening in new right pane</option>
<option value={OpenWhere.replaceLeft}>Replacing left tab</option>
<option value={OpenWhere.replaceRight}>Replacing right tab</option>
- <option value={OpenWhere.lightbox}>Opening in lightbox</option>
+ <option value={OpenWhere.lightboxAlways}>Opening in lightbox always</option>
+ <option value={OpenWhere.lightbox}>Opening in lightbox if not visible</option>
<option value={OpenWhere.add}>Opening in new tab</option>
<option value={OpenWhere.replace}>Replacing current tab</option>
<option value={OpenWhere.inParent}>Opening in same collection</option>
@@ -1459,11 +1506,14 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
'10',
NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000,
true,
- (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)),
+ (val: string) =>
+ PresBox.SetTransitionTime(val, (timeInMS: number) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS);
+ }),
indent
)}{' '}
<div
- className={'slider-headers'}
+ className="slider-headers"
style={{
display: 'grid',
justifyContent: 'space-between',
@@ -1478,111 +1528,147 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
</div>{' '}
<div className="propertiesView-input inline">
<p>Play Target Audio</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Play Target Video</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Zoom Text Selections</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Toggle Follow to Outer Context</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Toggle Target (Show/Hide)</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Ease Transitions</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Capture Offset to Target</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => {
- this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined);
- this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined);
- }}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => {
+ this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined);
+ this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined);
+ }}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Center Target (no zoom)</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}>
<p>Zoom %</p>
<div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}>
- <input className="presBox-input" style={{ width: '100%', color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} readOnly={true} type="number" value={zoom} />
+ <input className="presBox-input" style={{ width: '100%', color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} readOnly type="number" value={zoom} />
<div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}>
<div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}>
- <FontAwesomeIcon icon={'caret-up'} />
+ <FontAwesomeIcon icon="caret-up" />
</div>
<div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}>
- <FontAwesomeIcon icon={'caret-down'} />
+ <FontAwesomeIcon icon="caret-down" />
</div>
</div>
</div>
- <button
- style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
+ </button>
+ }
</div>
{!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)}
<div
- className={'slider-headers'}
+ className="slider-headers"
style={{
display: !targZoom ? 'none' : 'grid',
justifyContent: 'space-between',
@@ -1594,7 +1680,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}}>
<div className="slider-text">0%</div>
<div className="slider-text">100%</div>
- </div>{' '}
+ </div>
</div>
)}
</>
@@ -1622,128 +1708,136 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
</div>
</div>
);
- } else {
- if (this.selectedDoc && !this.isPres) {
- return (
- <div
- className="propertiesView"
- style={{
- background: SettingsManager.userBackgroundColor,
- color: SettingsManager.userColor,
- width: this._props.width,
- minWidth: this._props.width,
- }}>
- <div className="propertiesView-propAndInfoGrouping">
- <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
- Properties
- <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
- <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} />
- </div>
+ }
+ if (this.selectedDoc && !this.isPres) {
+ return (
+ <div
+ className="propertiesView"
+ style={{
+ background: SettingsManager.userBackgroundColor,
+ color: SettingsManager.userColor,
+ width: this._props.width,
+ minWidth: this._props.width,
+ }}>
+ <div className="propertiesView-propAndInfoGrouping">
+ <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
+ Properties
+ <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
+ <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} />
</div>
</div>
+ </div>
- <div className="propertiesView-name">{this.editableTitle}</div>
- <div className="propertiesView-type"> {this.currentType} </div>
- {this.fieldsSubMenu}
- {this.optionsSubMenu}
- {this.linksSubMenu}
- {!this.selectedLink || !this.openLinks ? null : this.linkProperties}
- {this.inkSubMenu}
- {this.contextsSubMenu}
- {isNovice ? null : this.sharingSubMenu}
- {this.filtersSubMenu}
- {isNovice ? null : this.layoutSubMenu}
+ <div className="propertiesView-name">{this.editableTitle}</div>
+ <div className="propertiesView-type"> {this.currentType} </div>
+ {this.fieldsSubMenu}
+ {this.optionsSubMenu}
+ {this.linksSubMenu}
+ {!this.selectedLink || !this.openLinks ? null : this.linkProperties}
+ {this.inkSubMenu}
+ {this.contextsSubMenu}
+ {isNovice ? null : this.sharingSubMenu}
+ {this.filtersSubMenu}
+ {isNovice ? null : this.layoutSubMenu}
+ </div>
+ );
+ }
+ if (this.isPres && PresBox.Instance) {
+ const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
+ const type = [DocumentType.AUDIO, DocumentType.VID].find(dt => dt === DocCast(PresBox.Instance.activeItem?.annotationOn)?.type)
+ ? DocCast(PresBox.Instance.activeItem?.annotationOn)?.type
+ : PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
+ return (
+ <div className="propertiesView" style={{ width: this._props.width }}>
+ <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
+ Presentation
</div>
- );
- }
- if (this.isPres && PresBox.Instance) {
- const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
- const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
- ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
- : PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
- return (
- <div className="propertiesView" style={{ width: this._props.width }}>
- <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
- Presentation
+ <div className="propertiesView-name" style={{ borderBottom: 0 }}>
+ {this.editableTitle}
+ <div className="propertiesView-presSelected">
+ <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div>
+ <div className="propertiesView-selectedList">{PresBox.Instance.listOfSelected}</div>
</div>
- <div className="propertiesView-name" style={{ borderBottom: 0 }}>
- {this.editableTitle}
- <div className="propertiesView-presSelected">
- <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div>
- <div className="propertiesView-selectedList">{PresBox.Instance.listOfSelected}</div>
- </div>
- </div>
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Transitions
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ </div>
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresTransitions = !this.openPresTransitions;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon="rocket" /> &nbsp; Transitions
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresTransitions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
</div>
- )}
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibility
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresTransitions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon="rocket" /> &nbsp; Visibility
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
</div>
- )}
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Progressivize
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresProgressivize = !this.openPresProgressivize;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon="rocket" /> &nbsp; Progressivize
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresProgressivize ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
</div>
- )}
- {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresProgressivize ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openSlideOptions = !this.openSlideOptions;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openSlideOptions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
</div>
- )}
- </div>
- );
- }
+ {this.openSlideOptions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
+ </div>
+ )}
+ </div>
+ );
}
+ return null;
}
}