diff options
| author | bobzel <zzzman@gmail.com> | 2020-08-05 22:34:21 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2020-08-05 22:34:21 -0400 |
| commit | 1a9750cb8c2102cf425137f47f08fb6f85cbdfa2 (patch) | |
| tree | daca75216d265e69fc196813f5b3fc00f95d8d0c /src/client/util | |
| parent | cc905d329c88d7bdf9b7324a4f02ab92906ba7c8 (diff) | |
| parent | af3e6b316f30c8154462145d15c38a2e48b53cdc (diff) | |
Merge branch 'master' into presentation_updates
Diffstat (limited to 'src/client/util')
| -rw-r--r-- | src/client/util/CurrentUserUtils.ts | 37 | ||||
| -rw-r--r-- | src/client/util/Scripting.ts | 2 | ||||
| -rw-r--r-- | src/client/util/SearchUtil.ts | 2 | ||||
| -rw-r--r-- | src/client/util/SettingsManager.scss | 249 | ||||
| -rw-r--r-- | src/client/util/SettingsManager.tsx | 191 |
5 files changed, 377 insertions, 104 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4e59434b5..1f140e145 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -8,7 +8,7 @@ import { Doc, DocListCast, DocListCastAsync, DataSym } from "../../fields/Doc"; import { List } from "../../fields/List"; import { listSpec } from "../../fields/Schema"; import { ScriptField, ComputedField } from "../../fields/ScriptField"; -import { Cast, PromiseValue, StrCast, NumCast } from "../../fields/Types"; +import { Cast, PromiseValue, StrCast, NumCast, BoolCast } from "../../fields/Types"; import { nullAudio } from "../../fields/URLField"; import { DragManager } from "./DragManager"; import { Scripting } from "./Scripting"; @@ -45,7 +45,7 @@ export class CurrentUserUtils { if (doc["template-button-query"] === undefined) { const queryTemplate = Docs.Create.MulticolumnDocument( [ - Docs.Create.QueryDocument({ title: "query", _height: 200 }), + Docs.Create.SearchDocument({ _viewType: CollectionViewType.Schema, ignoreClick: true, forceActive: true, lockedPosition: true, title: "query", _height: 200 }), Docs.Create.FreeformDocument([], { title: "data", _height: 100 }) ], { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, hideFilterView: true } @@ -415,9 +415,6 @@ export class CurrentUserUtils { if (doc.emptyButton === undefined) { doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button" }); } - if (doc.emptySearch === undefined) { - doc.emptySearch = Docs.Create.QueryDocument({ _width: 200, title: "empty search" }); - } if (doc.emptyDocHolder === undefined) { doc.emptyDocHolder = Docs.Create.DocumentDocument( ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]") as any, @@ -512,6 +509,14 @@ export class CurrentUserUtils { ]; } + static setupSearchPanel(doc: Doc) { + if (doc["search-panel"] === undefined) { + doc["search-panel"] = new PrefetchProxy(Docs.Create.SearchDocument({ + _width: 500, _height: 400, backgroundColor: "dimGray", ignoreClick: true, + childDropAction: "alias", lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", + })) as any as Doc; + } + } static setupMenuPanel(doc: Doc) { if (doc.menuStack === undefined) { const menuBtns = CurrentUserUtils.menuBtnDescriptions().map(({ title, icon, click }) => @@ -652,7 +657,7 @@ export class CurrentUserUtils { // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. // when clicked, this panel will be displayed in the target container (ie, sidebarContainer) - static async setupToolsBtnPanel(doc: Doc, sidebarContainer: Doc) { + static async setupToolsBtnPanel(doc: Doc) { // setup a masonry view of all he creators const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc); const templateBtns = CurrentUserUtils.setupUserTemplateButtons(doc); @@ -750,6 +755,8 @@ export class CurrentUserUtils { })) as any as Doc; } } + + static setupUserDoc(doc: Doc) { if (doc["sidebar-userDoc"] === undefined) { doc.treeViewOpen = true; @@ -774,8 +781,8 @@ export class CurrentUserUtils { // setup the list of sidebar mode buttons which determine what is displayed in the sidebar static async setupSidebarButtons(doc: Doc) { - const sidebarContainer = CurrentUserUtils.setupSidebarContainer(doc); - await CurrentUserUtils.setupToolsBtnPanel(doc, sidebarContainer); + CurrentUserUtils.setupSidebarContainer(doc); + await CurrentUserUtils.setupToolsBtnPanel(doc); CurrentUserUtils.setupWorkspaces(doc); CurrentUserUtils.setupCatalog(doc); CurrentUserUtils.setupRecentlyClosed(doc); @@ -813,6 +820,11 @@ export class CurrentUserUtils { // the initial presentation Doc to use static setupDefaultPresentation(doc: Doc) { + if (doc["template-presentation"] === undefined) { + doc["template-presentation"] = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ + title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" + })); + } if (doc.activePresentation === undefined) { doc.activePresentation = Docs.Create.PresDocument(new List<Doc>(), { title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias", @@ -822,9 +834,9 @@ export class CurrentUserUtils { } // Right sidebar is where mobile uploads are contained - static setupRightSidebar(doc: Doc) { + static setupSharingSidebar(doc: Doc) { if (doc["sidebar-sharing"] === undefined) { - doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Mobile Uploads" })); + doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Sharing Sidebar" })); } } @@ -890,14 +902,17 @@ export class CurrentUserUtils { doc.fontFamily = StrCast(doc.fontFamily, "Arial"); doc.fontColor = StrCast(doc.fontColor, "black"); doc.fontHighlight = StrCast(doc.fontHighlight, ""); + doc.defaultColor = StrCast(doc.defaultColor, "white"); + doc.noviceMode = BoolCast(doc.noviceMode, true); doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); // doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); // Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]); this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates - this.setupRightSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing + this.setupSharingSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile this.setupMenuPanel(doc); + this.setupSearchPanel(doc); this.setupOverlays(doc); // documents in overlay layer this.setupDockedButtons(doc); // the bottom bar of font icons this.setupDefaultPresentation(doc); // presentation that's initially triggered diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index f1e6155d2..cb0a4bea0 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -134,7 +134,7 @@ export function scriptingGlobal(constructor: { new(...args: any[]): any }) { Scripting.addGlobal(constructor); } -const _scriptingGlobals: { [name: string]: any } = {}; +export const _scriptingGlobals: { [name: string]: any } = {}; let scriptingGlobals: { [name: string]: any } = _scriptingGlobals; const _scriptingDescriptions: { [name: string]: any } = {}; const _scriptingParams: { [name: string]: any } = {}; diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 0a01d8ac7..7b2c601fe 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -29,6 +29,8 @@ export namespace SearchUtil { rows?: number; fq?: string; allowAliases?: boolean; + "facet"?: string; + "facet.field"?: string; } export function Search(query: string, returnDocs: true, options?: SearchParams): Promise<DocSearchResult>; export function Search(query: string, returnDocs: false, options?: SearchParams): Promise<IdSearchResult>; diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 6923fe879..41bce8a1b 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -1,7 +1,7 @@ @import "../views/globalCssVariables"; .settings-interface { - background-color: whitesmoke !important; + //background-color: whitesmoke !important; color: grey; width: 450px; height: 300px; @@ -22,85 +22,232 @@ } } -.settings-interface { +.settings-title { + font-size: 25px; + font-weight: bold; + padding-right: 10px; + color: black; +} + +.settings-username { + font-size: 14px; + padding-right: 15px; + color: black; + margin-top: 10px; +} + +.settings-section { display: flex; - flex-direction: column; + border-bottom: 1px solid grey; + padding-bottom: 8px; + padding-top: 6px; - button { - width: 100%; - align-self: center; - background: #252b33; - margin-top: 4px; + .settings-section-title { + font-size: 16; + font-weight: bold; + text-align: left; + color: black; + width: 80; + margin-right: 50px; + } + + &:last-child { + border-bottom: none; + } +} + + +.password-content { + display: flex; + + .password-content-inputs { + width: 100; + + .password-inputs { + border: none; + margin-bottom: 8px; + width: 180; + color: black; + border-radius: 5px; + } + } + + .password-content-buttons { + margin-left: 84px; + width: 100; + + .password-submit { + margin-left: 85px; + } + + .password-forgot { + margin-left: 65px; + margin-top: -20px; + white-space: nowrap; + } + } +} + +.accounts-content { + display: flex; +} + +.modes-content { + display: flex; + + .modes-select { + width: 170px; + margin-right: 65px; + color: black; + border-radius: 5px; &:hover { - background: $main-accent; + cursor: pointer; } } - .delete-button { - background: rgb(227, 86, 86); + .modes-playground { + display: flex; + + .playground-check { + margin-right: 5px; + + &:hover { + cursor: pointer; + } + } + + .playground-text { + color: black; + } } +} - .close-button { - position: absolute; - right: 1em; - top: 1em; +.colorFlyout { + margin-top: 2px; + margin-right: 25px; + + &:hover { cursor: pointer; } - .settings-heading { - letter-spacing: .5em; + .colorFlyout-button { + width: 20px; + height: 20px; + border: 0.5px solid black; + border-radius: 5px; } +} +.preferences-content { + display: flex; + margin-top: 4px; - .settings-body { + .preferences-color { display: flex; - justify-content: space-between; - margin-top: -10; - .settings-type { - display: flex; - flex-direction: column; - flex-basis: 45%; + .preferences-color-text { + color: black; + font-size: 11; + margin-top: 4; + margin-right: 4; + } + } + .preferences-font { + display: flex; + + .preferences-font-text { + color: black; + font-size: 11; + margin-top: 4; + margin-right: 4; } - .settings-content { - padding-left: 1em; - padding-right: 1em; - display: flex; - flex-direction: column; - flex-basis: 70%; - justify-content: space-around; - text-align: left; - - ::placeholder { - color: $intermediate-color; - } + .font-select { + width: 100px; + color: black; + font-size: 9; + margin-right: 6; + border-radius: 5px; - input { - border-radius: 5px; - border: none; - padding: 4px; - min-width: 100%; - margin: 2px 0; + &:hover { + cursor: pointer; } + } - .error-text { - color: #C40233; - } + .size-select { + width: 60px; + color: black; + font-size: 9; + border-radius: 5px; - .success-text { - color: #009F6B; + &:hover { + cursor: pointer; } + } + } +} - p { - padding: 0 0 .1em .2em; - } +.settings-interface { + display: flex; + flex-direction: column; + + button { + width: auto; + align-self: center; + background: #252b33; + margin-right: 15px; + //margin-top: 4px; + + &:hover { + background: $main-accent; } } + // .delete-button { + // background: rgb(227, 86, 86); + // } + + .close-button { + position: absolute; + right: 1em; + top: 1em; + cursor: pointer; + } + + .settings-content { + background: #e4e4e4; + border-radius: 6px; + padding: 10px; + width: 560px; + } + + .settings-top { + display: flex; + margin-bottom: 10px; + } + + + .error-text { + color: #C40233; + width: 300; + margin-left: -20; + font-size: 10; + margin-bottom: 4; + margin-top: -3; + } + + .success-text { + width: 300; + margin-left: -20; + font-size: 10; + margin-bottom: 4; + margin-top: -3; + color: #009F6B; + } + .focus-span { text-decoration: underline; } @@ -138,8 +285,6 @@ color: black; } - - } } diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 6276fae96..68ed32c0f 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -1,4 +1,4 @@ -import { observable, runInAction, action } from "mobx"; +import { observable, runInAction, action, computed } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; import { observer } from "mobx-react"; @@ -15,6 +15,12 @@ import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; import { DocServer } from "../DocServer"; +import { BoolCast, StrCast, NumCast } from "../../fields/Types"; +import { undoBatch } from "./UndoManager"; +import { ColorState, SketchPicker } from "react-color"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; library.add(fa.faTimes); @@ -33,6 +39,9 @@ export default class SettingsManager extends React.Component<{}> { private new_password_ref = React.createRef<HTMLInputElement>(); private new_confirm_ref = React.createRef<HTMLInputElement>(); + + @computed get backgroundColor() { return Doc.UserDoc().defaultColor; } + public open = action(() => { SelectionManager.DeselectAll(); this.isOpen = true; @@ -107,50 +116,151 @@ export default class SettingsManager extends React.Component<{}> { addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "pink !important" }); } + @action + changeMode = (e: any) => { + if (e.currentTarget.value === "Novice") { + Doc.UserDoc().noviceMode = true; + } else { + Doc.UserDoc().noviceMode = false; + } + } + + @action + changeFontFamily = (e: any) => { + Doc.UserDoc().fontFamily = e.currentTarget.value; + } + + @action + changeFontSize = (e: any) => { + Doc.UserDoc().fontSize = e.currentTarget.value; + } + + @action @undoBatch + switchColor = (color: ColorState) => { + const val = String(color.hex); + Doc.UserDoc().defaultColor = val; + return true; + } + private get settingsInterface() { - return ( - <div className={"settings-interface"}> - <div className="settings-heading"> - <h1>settings</h1> - <div className={"close-button"} onClick={this.close}> - <FontAwesomeIcon icon={fa.faTimes} color="black" size={"lg"} /> - </div> - </div> - <div className="settings-body"> - <div className="settings-type"> - <button onClick={this.onClick} value="password">reset password</button> - <button onClick={this.noviceToggle} value="data">{`Set ${Doc.UserDoc().noviceMode ? "developer" : "novice"} mode`}</button> - <button onClick={this.togglePlaygroundMode}>{`${this.playgroundMode ? "Disable" : "Enable"} playground mode`}</button> - <button onClick={this.googleAuthorize} value="data">{`Link to Google`}</button> - <button onClick={this.hypothesisAuthorize} value="data">{`Link to Hypothes.is`}</button> - <button onClick={() => GroupManager.Instance.open()}>Manage groups</button> - <button onClick={() => window.location.assign(Utils.prepend("/logout"))}> - {CurrentUserUtils.GuestWorkspace ? "Exit" : "Log Out"} - </button> + + + const passwordContent = <div className="password-content"> + <div className="password-content-inputs"> + <input className="password-inputs" type="password" placeholder="current password" ref={this.curr_password_ref} /> + <input className="password-inputs" type="password" placeholder="new password" ref={this.new_password_ref} /> + <input className="password-inputs" type="password" placeholder="confirm new password" ref={this.new_confirm_ref} /> + </div> + <div className="password-content-buttons"> + {this.errorText ? <div className="error-text">{this.errorText}</div> : undefined} + {this.successText ? <div className="success-text">{this.successText}</div> : undefined} + <button className="password-submit" onClick={this.dispatchRequest}>submit</button> + <a className="password-forgot" style={{ marginLeft: 65, marginTop: -20 }} + href="/forgotPassword">forgot password?</a> + </div> + </div>; + + const modesContent = <div className="modes-content"> + <select className="modes-select" + onChange={e => this.changeMode(e)}> + <option key={"Novice"} value={"Novice"} selected={BoolCast(Doc.UserDoc().noviceMode)}> + Novice + </option> + <option key={"Developer"} value={"Developer"} selected={!BoolCast(Doc.UserDoc().noviceMode)}> + Developer + </option> + </select> + <div className="modes-playground"> + <input className="playground-check" type="checkbox" + checked={this.playgroundMode} + onChange={undoBatch(action(() => this.togglePlaygroundMode()))} + /><div className="playground-text">Playground Mode</div> + </div> + </div>; + + const accountsContent = <div className="accounts-content"> + <button onClick={this.googleAuthorize} value="data">{`Link to Google`}</button> + <button onClick={this.hypothesisAuthorize} value="data">{`Link to Hypothes.is`}</button> + <button onClick={() => GroupManager.Instance.open()}>Manage groups</button> + </div>; + + const colorBox = <SketchPicker onChange={this.switchColor} + presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', + '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', + '#FFFFFF', '#f1efeb', 'transparent']} + color={StrCast(this.backgroundColor)} />; + + const colorFlyout = <div className="colorFlyout"> + <Flyout anchorPoint={anchorPoints.LEFT_TOP} + content={colorBox}> + <div> + <div className="colorFlyout-button" style={{ backgroundColor: StrCast(this.backgroundColor) }} + onPointerDown={e => e.stopPropagation()} > + <FontAwesomeIcon icon="palette" size="sm" color={StrCast(this.backgroundColor)} /> </div> - {this.settingsContent === "password" ? - <div className="settings-content"> - <input placeholder="current password" ref={this.curr_password_ref} /> - <input placeholder="new password" ref={this.new_password_ref} /> - <input placeholder="confirm new password" ref={this.new_confirm_ref} /> - {this.errorText ? <div className="error-text">{this.errorText}</div> : undefined} - {this.successText ? <div className="success-text">{this.successText}</div> : undefined} - <button onClick={this.dispatchRequest}>submit</button> - <a style={{ marginLeft: 65, marginTop: -20 }} href="/forgotPassword">forgot password?</a> - - </div> - : undefined} - {this.settingsContent === "data" ? - <div className="settings-content"> - <p>WARNING: <br /> - THIS WILL ERASE ALL YOUR CURRENT DOCUMENTS STORED ON DASH. IF YOU WISH TO PROCEED, CLICK THE BUTTON BELOW.</p> - <button className="delete-button">DELETE</button> - </div> - : undefined} </div> + </Flyout> + </div>; + const fontFamilies: string[] = ["Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; + const fontSizes: string[] = ["7pt", "8pt", "9pt", "10pt", "12pt", "14pt", "16pt", "18pt", "20pt", "24pt", "32pt", "48pt", "72pt"]; + + const preferencesContent = <div className="preferences-content"> + <div className="preferences-color"> + <div className="preferences-color-text">Background Color</div> {colorFlyout} </div> - ); + <div className="preferences-font"> + <div className="preferences-font-text">Default Font</div> + <select className="font-select" + onChange={e => this.changeFontFamily(e)}> + {fontFamilies.map((font) => { + return <option key={font} value={font} selected={StrCast(Doc.UserDoc().fontFamily) === font}> + {font} + </option>; + })} + </select> + <select className="size-select" + onChange={e => this.changeFontSize(e)}> + {fontSizes.map((size) => { + return <option key={size} value={size} selected={StrCast(Doc.UserDoc().fontSize) === size}> + {size} + </option>; + })} + </select> + </div> + </div>; + + return (<div className="settings-interface"> + <div className="settings-top"> + <div className="settings-title">Settings</div> + <div className="settings-username">{Doc.CurrentUserEmail}</div> + <button onClick={() => window.location.assign(Utils.prepend("/logout"))} + style={{ right: 35, position: "absolute" }} > + {CurrentUserUtils.GuestWorkspace ? "Exit" : "Log Out"} + </button> + <div className="close-button" onClick={this.close}> + <FontAwesomeIcon icon={fa.faTimes} color="black" size={"lg"} /> + </div> + </div> + <div className="settings-content"> + <div className="settings-section"> + <div className="settings-section-title">Password</div> + <div className="settings-section-context">{passwordContent}</div> + </div> + <div className="settings-section"> + <div className="settings-section-title">Modes</div> + <div className="settings-section-context">{modesContent}</div> + </div> + <div className="settings-section"> + <div className="settings-section-title">Accounts</div> + <div className="settings-section-context">{accountsContent}</div> + </div> + <div className="settings-section" style={{ paddingBottom: 4 }}> + <div className="settings-section-title">Preferences</div> + <div className="settings-section-context">{preferencesContent}</div> + </div> + </div> + </div>); } render() { @@ -160,6 +270,7 @@ export default class SettingsManager extends React.Component<{}> { isDisplayed={this.isOpen} interactive={true} closeOnExternalClick={this.close} + dialogueBoxStyle={{ width: "600px", height: "340px" }} /> ); } |
