diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-12-02 18:01:02 +0530 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-12-02 18:01:02 +0530 |
commit | 3bbca467d5cadb367c34c5296e957bd1d388cfca (patch) | |
tree | 2b9e7429e342a89795f64ca9fc2d32c749ea12c3 /src | |
parent | 1f9baca276426444a4ebea06023402876f033ebe (diff) | |
parent | 23290bd8a8d1cb1f1254a7b600bdc6f540caf52e (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into acls_uv
Diffstat (limited to 'src')
20 files changed, 310 insertions, 132 deletions
diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index badba35f4..5ca54517c 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -33,9 +33,10 @@ padding-right: 15px; color: black; margin-top: 10px; + margin-bottom: 10px; /* right: 135; */ - position: absolute; - left: 243; + // position: absolute; + // left: 243; } .settings-section { @@ -61,30 +62,38 @@ .password-content { display: flex; + flex-direction: column; .password-content-inputs { width: 100; + // margin-bottom: 10px; + font-size: 10px; .password-inputs { - border: none; + border: 1px solid rgb(160, 160, 160); margin-bottom: 8px; - width: 180; + width: 130; color: black; border-radius: 5px; + padding:7px; + } } .password-content-buttons { - margin-left: 84px; - width: 100; + //margin-left: 84px; + //width: 100; + padding: 7px; .password-submit { - margin-left: 85px; + //margin-left: 85px; + margin-top: 5px; } .password-forgot { - margin-left: 65px; - margin-top: -20px; + //margin-left: 65px; + //margin-top: -20px; + font-size: 12px; white-space: nowrap; } } @@ -97,10 +106,12 @@ .modes-content { display: flex; margin-left: 10px; - font-size: 12; + font-size: 12px; .modes-select { // width: 170px; + width: 80%; + height: 35px; margin-right: 10px; color: black; border-radius: 5px; @@ -114,7 +125,8 @@ .default-acl { display: flex; margin-left: 10px; - font-size: 12; + margin-top: 10px; + font-size: 10px; .playground-check, .acl-check { @@ -134,6 +146,7 @@ .acl-text { color: black; margin-top: 2; + text-align: left; } } @@ -141,7 +154,7 @@ .colorFlyout { margin-top: 2px; - margin-right: 18px; + //margin-right: 18px; &:hover { cursor: pointer; @@ -156,67 +169,85 @@ } } -.preferences-content { +.prefs-content{ + text-align: left; +} + +.appearances-content { display: flex; margin-top: 4px; color: black; - font-size: 11; + font-size: 10px; .preferences-color { display: flex; margin-top: 2px; - width: 55; .preferences-color-text { - margin-top: 4; + margin-top: 3px; margin-right: 4; + flex: 1 1 auto; + text-align: left; + } + + .colorFlyout { + align-self: flex-end; } } .preferences-font { - display: flex; - height: 23px; + //height: 23px; margin-top: 2px; .preferences-font-text { color: black; margin-top: 4; margin-right: 4; + margin-bottom: 2px; + text-align: left; + } + + .preferences-font-controls { + display: flex; + justify-content: space-between; } .font-select { - width: 100px; + height: 35px; color: black; font-size: 9; margin-right: 6; border-radius: 5px; + width: 65%; &:hover { cursor: pointer; } } - .preferences-check { - color: black; - font-size: 9; - /* margin-top: 4; */ - margin-right: 4; - margin-bottom: -3; - margin-left: 5; - margin-top: -1px; - } - .size-select { - width: 60px; + height: 35px; color: black; font-size: 9; border-radius: 5px; + width: 30%; &:hover { cursor: pointer; } } } + + .preferences-check { + color: black; + margin-right: 4; + margin-bottom: -3; + margin-left: 5; + margin-top: -1px; + display: inline-block; + padding-left: 5px; + text-align: left; + } } .settings-interface { @@ -247,16 +278,17 @@ cursor: pointer; } - .logout-button { - right: 355; - position: absolute; - } + // .logout-button { + // right: 355; + // position: absolute; + // } .settings-content { background: #e4e4e4; - border-radius: 6px; + //border-radius: 6px; padding: 10px; - width: 560px; + //width: 560px; + flex: 1 1 auto; } .settings-top { @@ -323,6 +355,94 @@ } } +.settings-interface { + flex-direction: row; + position: relative; + min-height: 250px; + width: 100%; + + .settings-content { + background-color: #fdfdfd; + } +} + +.settings-panel { + position: relative; + min-width: 150px; + background-color: #e4e4e4; + + .settings-user { + position: absolute; + bottom: 10px; + text-align: center; + left: 0; + right: 0; + + .settings-username { + padding-right: 0px; + } + + .logout-button { + margin-right: 2px; + } + } +} + +.settings-tabs { + // font-size: 16px; + font-weight: 600; + color: black; + + .tab-control { + padding: 10px; + border-bottom: 1px solid #9f9e9e; + cursor: pointer; + + &.active { + background-color: #fdfdfd; + } + } +} + +.settings-section-context { + width: 100%; +} + +.tab-section { + display: none; + height: 200px; + + &.active { + display: block; + } +} + +.tab-content { + display: flex; + margin: 20px 0; + + .tab-column { + flex: 0 0 50%; + + .tab-column-title { + color: black; + font-size: 16px; + font-weight: bold; + margin-bottom: 16px; + } + + .tab-column-title, .tab-column-content { + padding-left: 16px; + } + + } + +} + +.tab-column button { + font-size: 9px; +} + @media only screen and (max-device-width: 480px) { .settings-interface { width: 80vw; @@ -342,4 +462,4 @@ .settings-interface .settings-heading { font-size: 25; } -}
\ No newline at end of file +} diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 9934f26d3..ff7ce68ee 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -29,9 +29,11 @@ export class SettingsManager extends React.Component<{}> { @observable private curr_password = ""; @observable private new_password = ""; @observable private new_confirm = ""; + @observable activeTab = "Accounts"; @computed get backgroundColor() { return Doc.UserDoc().activeCollectionBackground; } + constructor(props: {}) { super(props); SettingsManager.Instance = this; @@ -67,7 +69,7 @@ export class SettingsManager extends React.Component<{}> { else DocServer.Control.makeEditable(); }); - @computed get preferencesContent() { + @computed get colorsContent() { const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(this.backgroundColor)} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', @@ -91,41 +93,62 @@ export class SettingsManager extends React.Component<{}> { const fontFamilies = ["Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; const fontSizes = ["7px", "8px", "9px", "10px", "12px", "14px", "16px", "18px", "20px", "24px", "32px", "48px", "72px"]; - return <div className="preferences-content"> + return <div className="colors-content"> <div className="preferences-color"> - <div className="preferences-color-text">Back. Color</div> + <div className="preferences-color-text">Background Color</div> {colorFlyout} </div> <div className="preferences-color"> - <div className="preferences-color-text">User Color</div> + <div className="preferences-color-text">Border/Header Color</div> {userColorFlyout} </div> <div className="preferences-font"> - <div className="preferences-font-text">Font</div> - <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, "Times New Roman")} > - {fontFamilies.map(font => <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}> {font} </option>)} - </select> - <select className="size-select" style={{ marginRight: "10px" }} onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, "7px")}> - {fontSizes.map(size => <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}> {size} </option>)} - </select> - <div> - <div className="preferences-check">Show header</div> - <input type="checkbox" onChange={e => Doc.UserDoc().showTitle = Doc.UserDoc().showTitle ? undefined : "creationDate"} checked={Doc.UserDoc().showTitle !== undefined} /> - </div> - <div> - <div className="preferences-check">Full Toolbar</div> - <input type="checkbox" onChange={e => Doc.UserDoc()["documentLinksButton-fullMenu"] = !Doc.UserDoc()["documentLinksButton-fullMenu"]} - checked={BoolCast(Doc.UserDoc()["documentLinksButton-fullMenu"])} /> - </div> - <div> - <div className="preferences-check">Raise on drag</div> - <input type="checkbox" onChange={e => Doc.UserDoc()._raiseWhenDragged = !Doc.UserDoc()._raiseWhenDragged} - checked={BoolCast(Doc.UserDoc()._raiseWhenDragged)} /> + <div className="preferences-font-text">Default Font</div> + <div className="preferences-font-controls"> + <select className="size-select" onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, "7px")}> + {fontSizes.map(size => <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}> {size} </option>)} + </select> + <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, "Times New Roman")} > + {fontFamilies.map(font => <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}> {font} </option>)} + </select> </div> </div> </div>; } + @computed get formatsContent() { + return <div className="prefs-content"> + <div> + <input type="checkbox" onChange={e => Doc.UserDoc().showTitle = Doc.UserDoc().showTitle ? undefined : "creationDate"} checked={Doc.UserDoc().showTitle !== undefined} /> + <div className="preferences-check">Show doc header</div> + </div> + <div> + <input type="checkbox" onChange={e => Doc.UserDoc()["documentLinksButton-fullMenu"] = !Doc.UserDoc()["documentLinksButton-fullMenu"]} + checked={BoolCast(Doc.UserDoc()["documentLinksButton-fullMenu"])} /> + <div className="preferences-check">Show full toolbar</div> + </div> + <div> + <input type="checkbox" onChange={e => Doc.UserDoc()._raiseWhenDragged = !Doc.UserDoc()._raiseWhenDragged} + checked={BoolCast(Doc.UserDoc()._raiseWhenDragged)} /> + <div className="preferences-check">Raise on drag</div> + </div> + </div>; + } + + @computed get appearanceContent() { + + return <div className="tab-content appearances-content"> + <div className="tab-column"> + <div className="tab-column-title">Colors</div> + <div className="tab-column-content">{this.colorsContent}</div> + </div> + <div className="tab-column"> + <div className="tab-column-title">Formats</div> + <div className="tab-column-content">{this.formatsContent}</div> + </div> + </div>; + } + @action changeVal = (e: React.ChangeEvent, pass: string) => { const value = (e.target as any).value; @@ -145,58 +168,91 @@ export class SettingsManager extends React.Component<{}> { </div> <div className="password-content-buttons"> {!this.passwordResultText ? (null) : <div className={`${this.passwordResultText.startsWith("Error") ? "error" : "success"}-text`}>{this.passwordResultText}</div>} - <button className="password-submit" onClick={this.changePassword}>submit</button> <a className="password-forgot" href="/forgotPassword">forgot password?</a> + <button className="password-submit" onClick={this.changePassword}>submit</button> </div> </div>; } - @computed get modesContent() { - return <div className="modes-content"> - <select className="modes-select" onChange={this.selectUserMode} defaultValue={Doc.UserDoc().noviceMode ? "Novice" : "Developer"}> - <option key={"Novice"} value={"Novice"}> Novice </option> - <option key={"Developer"} value={"Developer"}> Developer</option> - </select> - <div className="modes-playground"> - <input className="playground-check" type="checkbox" checked={this.playgroundMode} onChange={this.playgroundModeToggle} /> - <div className="playground-text">Playground Mode</div> - </div> - <div className="default-acl"> - <input className="acl-check" type="checkbox" checked={BoolCast(Doc.UserDoc()?.defaultAclPrivate)} onChange={action(() => Doc.UserDoc().defaultAclPrivate = !Doc.UserDoc().defaultAclPrivate)} /> - <div className="acl-text">Default access private</div> - </div> + @computed get accountOthersContent() { + return <div className="account-others-content"> + <button onClick={this.googleAuthorize} value="data">Authorize Google Acc</button> </div>; } @computed get accountsContent() { - return <div className="accounts-content"> - <button onClick={this.googleAuthorize} value="data">Link to Google</button> - <button onClick={() => GroupManager.Instance?.open()}>Manage groups</button> + return <div className="tab-content accounts-content"> + <div className="tab-column"> + <div className="tab-column-title">Password</div> + <div className="tab-column-content">{this.passwordContent}</div> + </div> + <div className="tab-column"> + <div className="tab-column-title">Others</div> + <div className="tab-column-content">{this.accountOthersContent}</div> + </div> + </div>; + } + + @computed get modesContent() { + return <div className="tab-content modes-content"> + <div className="tab-column"> + <div className="tab-column-title">Modes</div> + <div className="tab-column-content"> + <select className="modes-select" onChange={this.selectUserMode} defaultValue={Doc.UserDoc().noviceMode ? "Novice" : "Developer"}> + <option key={"Novice"} value={"Novice"}> Novice </option> + <option key={"Developer"} value={"Developer"}> Developer</option> + </select> + <div className="modes-playground"> + <input className="playground-check" type="checkbox" checked={this.playgroundMode} onChange={this.playgroundModeToggle} /> + <div className="playground-text">Playground Mode</div> + </div> + </div> + </div> + <div className="tab-column"> + <div className="tab-column-title">Permissions</div> + <div className="tab-column-content"> + <button onClick={() => GroupManager.Instance?.open()}>Manage groups</button> + <div className="default-acl"> + <input className="acl-check" type="checkbox" checked={BoolCast(Doc.UserDoc()?.defaultAclPrivate)} onChange={action(() => Doc.UserDoc().defaultAclPrivate = !Doc.UserDoc().defaultAclPrivate)} /> + <div className="acl-text">Default access private</div> + </div> + </div> + </div> + </div>; } + private get settingsInterface() { - const pairs = [{ title: "Password", ele: this.passwordContent }, { title: "Modes", ele: this.modesContent }, - { title: "Accounts", ele: this.accountsContent }, { title: "Preferences", ele: this.preferencesContent }]; + // const pairs = [{ title: "Password", ele: this.passwordContent }, { title: "Modes", ele: this.modesContent }, + // { title: "Accounts", ele: this.accountsContent }, { title: "Preferences", ele: this.preferencesContent }]; + + const tabs = [{ title: "Accounts", ele: this.accountsContent }, { title: "Modes", ele: this.modesContent }, + { title: "Appearance", ele: this.appearanceContent }]; + return <div className="settings-interface"> - <div className="settings-top"> - <div className="settings-title">Settings</div> - <div className="settings-username">{Doc.CurrentUserEmail}</div> - <button className="logout-button" onClick={() => window.location.assign(Utils.prepend("/logout"))} > - {CurrentUserUtils.GuestDashboard ? "Exit" : "Log Out"} - </button> - <div className="close-button" onClick={this.close}> - <FontAwesomeIcon icon={"times"} color="black" size={"lg"} /> + <div className="settings-panel"> + <div className="settings-tabs"> + {tabs.map(tab => <div key={tab.title} className={"tab-control " + (this.activeTab === tab.title ? "active" : "inactive")} onClick={action(() => this.activeTab = tab.title)}>{tab.title}</div>)} + </div> + + <div className="settings-user"> + <div className="settings-username">{Doc.CurrentUserEmail}</div> + <button className="logout-button" onClick={() => window.location.assign(Utils.prepend("/logout"))} > + {CurrentUserUtils.GuestDashboard ? "Exit" : "Log Out"} + </button> </div> </div> + + <div className="close-button" onClick={this.close}> + <FontAwesomeIcon icon={"times"} color="black" size={"lg"} /> + </div> + <div className="settings-content"> - {pairs.map(pair => <div className="settings-section" key={pair.title}> - <div className="settings-section-title">{pair.title}</div> - <div className="settings-section-context">{pair.ele}</div> - </div> - )} + {tabs.map(tab => <div key={tab.title} className={"tab-section " + (this.activeTab === tab.title ? "active" : "inactive")}>{tab.ele}</div>)} </div> </div>; + } render() { @@ -205,6 +261,6 @@ export class SettingsManager extends React.Component<{}> { isDisplayed={this.isOpen} interactive={true} closeOnExternalClick={this.close} - dialogueBoxStyle={{ width: "600px", background: Cast(Doc.SharingDoc().userColor, "string", null) }} />; + dialogueBoxStyle={{ width: "500px", height: "300px", background: Cast(Doc.SharingDoc().userColor, "string", null) }} />; } }
\ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ce526f842..032d4d3bb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -295,7 +295,7 @@ export class MainView extends React.Component { <div className="mainView-libraryFlyout" style={{ minWidth: this._flyoutWidth, width: this._flyoutWidth }} > <div className="mainView-contentArea" > <DocumentView - Document={this._sidebarContent} + Document={this._sidebarContent.proto || this._sidebarContent} DataDoc={undefined} LibraryPath={emptyPath} addDocument={undefined} @@ -320,7 +320,6 @@ export class MainView extends React.Component { ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} relative={true} - forcedBackgroundColor={() => this.darkScheme ? "rgb(62,62,62)" : "lightgrey"} /> </div> {this.docButtons} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 2727ac2df..37e5b55eb 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -15,6 +15,7 @@ import { ScriptingRepl } from './ScriptingRepl'; import { DragManager } from "../util/DragManager"; import { List } from "../../fields/List"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; +import { TabDocView } from "./collections/TabDocView"; export type OverlayDisposer = () => void; @@ -195,7 +196,7 @@ export class OverlayView extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} - styleProvider={returnEmptyString} + styleProvider={TabDocView.styleProvider} addDocTab={returnFalse} pinToPres={emptyFunction} docFilters={returnEmptyFilter} diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index e32400385..5ef3de4bc 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -65,7 +65,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) </div> <div className="collectionCarouselView-caption" key="caption" style={{ - background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "color", this.props.layerProvider)), + background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider)), color: StrCast(this.layoutDoc._captionColor, StrCast(this.layoutDoc.color)), borderRadius: StrCast(this.layoutDoc._captionBorderRounding), }}> diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 439384e08..b4587dc13 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -216,7 +216,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll render() { TraceMobx(); if (!(this.doc instanceof Doc)) return (null); - const background = this.props.styleProvider?.(this.doc, this.props.renderDepth, "color", this.props.layerProvider); + const background = this.props.styleProvider?.(this.doc, this.props.renderDepth, "backgroundColor", this.props.layerProvider); const paddingX = `${NumCast(this.doc._xPadding, 10)}px`; const paddingTop = `${NumCast(this.doc._yPadding, 20)}px`; // const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && !this._isChildActive ? "none" : undefined; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 7f8f57088..82b6d8605 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -301,7 +301,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { } } - @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, TabDocView.styleProvider(this._document, 0, "color"))); } + @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, TabDocView.styleProvider(this._document, 0, "backgroundColor"))); } @computed get renderBounds() { const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0]; const xbounds = bounds[2] - bounds[0]; @@ -374,7 +374,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { <Tooltip title={<div className="dash-tooltip">{"toggle minimap"}</div>}> <div className="miniMap-hidden" onPointerDown={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} - style={{ background: TabDocView.styleProvider(this._document, 0, "color") }} > + style={{ background: TabDocView.styleProvider(this._document, 0, "backgroundColor") }} > <FontAwesomeIcon icon={"globe-asia"} size="lg" /> </div> </Tooltip> @@ -437,7 +437,7 @@ export class TabDocView extends React.Component<TabDocViewProps> { // public static styleProvider = (doc: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean): any => { switch (property) { - case "color": { + case "backgroundColor": { if (Doc.UserDoc().renderStyle === "comic") return undefined; let docColor = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor)); if (!docColor) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ea630b67a..0ba13192d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -395,7 +395,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P getClusterColor = (doc: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => { let clusterColor = this.props.styleProvider?.(doc, this.props.renderDepth + 1, property, layerProvider); - if (property !== "color") return clusterColor; + if (property !== "backgroundColor") return clusterColor; const cluster = NumCast(doc?.cluster); if (this.Document._useClusters) { if (this._clusterSets.length <= cluster) { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 4f6c5cebe..6323a6100 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -623,9 +623,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD ContainingCollectionDoc={this.props.Document} parentActive={returnTrue} bringToFront={emptyFunction} - styleProvider={returnTransparent} ContentScaling={returnOne} - forcedBackgroundColor={returnTransparent} + styleProvider={(doc: Opt<Doc>, renderDepth: number, property: string) => property === "backgroundColor" ? "transparent" : undefined} pointerEvents={"none"} LayoutTemplate={undefined} LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index cc3ed7973..84f08b217 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -255,14 +255,14 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF } render() { TraceMobx(); - const backgroundColor = this.props.styleProvider?.(this.Document, this.props.renderDepth, "color", this.props.layerProvider); + const backgroundColor = this.props.styleProvider?.(this.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider); const borderRounding = StrCast(Doc.Layout(this.layoutDoc).borderRounding) || StrCast(this.layoutDoc.borderRounding) || StrCast(this.Document.borderRounding) || undefined; return <div className="collectionFreeFormDocumentView-container" style={{ boxShadow: this.Opacity === 0 ? undefined : // if it's not visible, then no shadow this.layoutDoc.z ? `#9c9396 ${StrCast(this.layoutDoc.boxShadow, "10px 10px 0.9vw")}` : // if it's a floating doc, give it a big shadow - this.props.backgroundHalo?.(this.props.Document) && this.props.Document.type !== DocumentType.INK ? (`${this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "color", this.props.layerProvider)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(Cast(this.layoutDoc.layers, listSpec("string"), []).includes("background") ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent + this.props.backgroundHalo?.(this.props.Document) && this.props.Document.type !== DocumentType.INK ? (`${this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(Cast(this.layoutDoc.layers, listSpec("string"), []).includes("background") ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent Cast(this.layoutDoc.layers, listSpec("string"), []).includes('background') ? undefined : // if it's a background & has a cluster color, make the shadow spread really big StrCast(this.layoutDoc.boxShadow, ""), borderRadius: borderRounding, diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx index a20423fdc..58f4df823 100644 --- a/src/client/views/nodes/DocHolderBox.tsx +++ b/src/client/views/nodes/DocHolderBox.tsx @@ -184,7 +184,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do onContextMenu={this.specificContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} style={{ - background: this.props.styleProvider?.(containedDoc, this.props.renderDepth, "color", this.props.layerProvider), + background: this.props.styleProvider?.(containedDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider), border: `#00000021 solid ${this.xPad}px`, borderTop: `#0000005e solid ${this.yPad}px`, borderBottom: `#0000005e solid ${this.yPad}px`, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 18ebb569a..79ee0291d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -12,7 +12,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; -import { emptyFunction, OmitKeys, returnOne, returnTransparent, returnVal, Utils, returnFalse } from "../../../Utils"; +import { emptyFunction, OmitKeys, returnOne, returnTransparent, returnVal, Utils, returnFalse, returnTrue } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -95,7 +95,7 @@ export interface DocumentViewProps { pinToPres: (document: Doc) => void; backgroundHalo?: (doc: Doc) => boolean; styleProvider?: (doc: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => any; - forcedBackgroundColor?: (doc: Doc) => string | undefined; + forceHideLinkButton?: () => boolean; opacity?: () => number | undefined; ChromeHeight?: () => number; dontRegisterView?: boolean; @@ -959,7 +959,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu layoutKey={this.finalLayoutKey} /> {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} {/* {this.allAnchors} */} - {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) : + {this.props.forceHideLinkButton?.() || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) : <DocumentLinksButton View={this} links={this.allLinks} Offset={this.linkOffset} />} {!this.props.Document.numUsersShared && !this.props.Document.numGroupsShared ? (null) : @@ -1019,7 +1019,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu PanelHeight={this.anchorPanelHeight} ContentScaling={returnOne} dontRegisterView={false} - forcedBackgroundColor={returnTransparent} + forceHideLinkButton={returnTrue} + styleProvider={(doc: Opt<Doc>, renderDepth: number, property: string) => property === "backgroundColor" ? "transparent" : undefined} removeDocument={this.hideLinkAnchor} pointerEvents={"none"} LayoutTemplate={undefined} @@ -1107,7 +1108,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu if (!(this.props.Document instanceof Doc)) return (null); if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null); if (this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "hidden", this.props.layerProvider)) return null; - const backgroundColor = this.props.forcedBackgroundColor?.(this.Document) || this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "color", this.props.layerProvider); + const backgroundColor = this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider); const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null))); const finalOpacity = this.props.opacity ? this.props.opacity() : opacity; const finalColor = this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor; @@ -1148,7 +1149,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding && highlightStyles[fullDegree] === "dashed" ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, boxShadow: highlighting && borderRounding && highlightStyles[fullDegree] !== "dashed" ? `0 0 0 ${localScale}px ${highlightColors[fullDegree]}` : - this.Document.isLinkButton && !this.props.dontRegisterView && this.props.forcedBackgroundColor?.(this.Document) !== "transparent" ? + this.Document.isLinkButton && !this.props.dontRegisterView && !this.props.forceHideLinkButton?.() ? StrCast(this.layoutDoc._linkButtonShadow, "lightblue 0em 0em 1em") : this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, @@ -1159,7 +1160,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu }}> {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <> {this.innards} - <div className="documentView-contentBlocker" /> + <div className="documentView-conentBlocker" /> </> : this.innards} {!this.props.treeViewDoc && this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, this.isSelected() ? "decorations:selected" : "decorations", this.props.layerProvider) || (null)} diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 4db421e7a..ab401213c 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -161,7 +161,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc } render() { - const facetCollection = this.props.Document.proto as Doc; + const facetCollection = this.props.Document as Doc; const flyout = <div className="filterBox-flyout" style={{ width: `100%`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}> {this._allFacets.map(facet => <label className="filterBox-flyout-facet" key={`${facet}`} onClick={e => this.facetClick(facet)}> <input type="checkbox" onChange={e => { }} checked={DocListCast(this.props.Document[this.props.fieldKey]).some(d => d.title === facet)} /> diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index d4b6f1a27..dfbd89c88 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -61,7 +61,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( render() { const label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); const color = StrCast(this.layoutDoc.color, this._foregroundColor); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, "color", this.props.layerProvider); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider); const shape = StrCast(this.layoutDoc.iconShape, label ? "round" : "circle"); const icon = StrCast(this.dataDoc.icon, "user") as any; const presSize = shape === 'round' ? 25 : 30; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index c5ff42a1a..4ac932c24 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -70,7 +70,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean): boolean { const { script, type, onDelegate } = kvpScript; //const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates - const target = forceOnDelegate || onDelegate ? doc : Doc.GetProto(doc); + const target = forceOnDelegate || onDelegate ? doc : doc.proto || doc; let field: Field; if (type === "computed") { field = new ComputedField(script); diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index edad14e96..913c07eb2 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -17,7 +17,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>( public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } render() { return <div className={`linkBox-container${this.active() ? "-interactive" : ""}`} - style={{ background: this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "color", this.props.layerProvider) }} > + style={{ background: this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider) }} > <CollectionTreeView {...this.props} ChromeHeight={returnZero} diff --git a/src/client/views/nodes/ScriptingBox.scss b/src/client/views/nodes/ScriptingBox.scss index a937364a8..8d76f2b1d 100644 --- a/src/client/views/nodes/ScriptingBox.scss +++ b/src/client/views/nodes/ScriptingBox.scss @@ -213,12 +213,12 @@ .scriptingBox-button { font-size: xx-small; - width: 50%; + width: 33%; resize: auto; } - .scriptingBox-button-third { - width: 33%; + .scriptingBox-button-finish { + width: 25%; } } }
\ No newline at end of file diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 1a5edc1d9..f1f2cd7d3 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -628,13 +628,13 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc // toolbar (with compile and apply buttons) for scripting UI renderScriptingTools() { - const buttonStyle = "scriptingBox-button" + (this.rootDoc.layoutKey === "layout_onClick" ? "third" : ""); + const buttonStyle = "scriptingBox-button" + (StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? "-finish" : ""); return <div className="scriptingBox-toolbar"> - <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button> - <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button> - <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onSave(); e.stopPropagation(); }}>Save</button> + <button className={buttonStyle} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button> + <button className={buttonStyle} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button> + <button className={buttonStyle} onPointerDown={e => { this.onSave(); e.stopPropagation(); }}>Save</button> - {this.rootDoc.layoutKey !== "layout_onClick" ? (null) : + {!StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? (null) : // onClick, onChecked, etc need a Finish button to return to their default layout <button className={buttonStyle} onPointerDown={e => { this.onFinish(); e.stopPropagation(); }}>Finish</button>} </div>; } @@ -662,11 +662,11 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc // toolbar (with edit and run buttons and error message) for params UI renderTools(toolSet: string, func: () => void) { - const buttonStyle = "scriptingBox-button" + (this.rootDoc.layoutKey === "layout_onClick" ? "third" : ""); + const buttonStyle = "scriptingBox-button" + (StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? "-finish" : ""); return <div className="scriptingBox-toolbar"> <button className={buttonStyle} onPointerDown={e => { this.onEdit(); e.stopPropagation(); }}>Edit</button> <button className={buttonStyle} onPointerDown={e => { func(); e.stopPropagation(); }}>{toolSet}</button> - {this.rootDoc.layoutKey !== "layout_onClick" ? (null) : + {!StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? (null) : <button className={buttonStyle} onPointerDown={e => { this.onFinish(); e.stopPropagation(); }}>Finish</button>} </div>; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 5017d21f1..97a45892a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1472,7 +1472,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public static LiveTextUndo: UndoManager.Batch | undefined; public static HadSelection: boolean = false; onBlur = (e: any) => { - RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined); + if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) { + RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined); + } FormattedTextBox.HadSelection = window.getSelection()?.toString() !== ""; this.endUndoTypingBatch(); this.doLinkOnDeselect(); diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 8d4bd4b8b..899897a6d 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -312,7 +312,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc <div className="presItem-number"> {`${this.indexInPres + 1}.`} </div>} - {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`} style={{ backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "color", this.props.layerProvider) }}> + {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`} style={{ backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider) }}> <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 185) : toolbarWidth - 95, cursor: isSelected ? 'text' : 'grab' }}> <EditableView ref={this._titleRef} |