diff options
41 files changed, 974 insertions, 501 deletions
diff --git a/.gitignore b/.gitignore index 43b63a362..7a3c82ee6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ src/server/session_manager/logs/**/*.log *.pfx *.properties debug.log -.vscodeignore
\ No newline at end of file +.vscodeignore +Dockerfile diff --git a/deploy/assets/favicon.png b/deploy/assets/favicon.png Binary files differnew file mode 100644 index 000000000..59595b910 --- /dev/null +++ b/deploy/assets/favicon.png diff --git a/deploy/index.html b/deploy/index.html index dda0c6457..d96215391 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -1,114 +1,22 @@ <html style="overflow: hidden;"> <head> - <title>Dash Web</title> - <link href="https://fonts.googleapis.com/css?family=Fjalla+One|Hind+Siliguri:300" rel="stylesheet"> - <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500' rel='stylesheet'> + <title>Dash</title> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link + href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&family=Lato:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Merriweather:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Roboto:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" + rel="stylesheet"> + <link rel="shortcut icon" type="image/jpg" href="./assets/favicon.png" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script> - - <script> - function getCookie(cname) { - var name = cname + "="; - var ca = document.cookie.split(';'); - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) == ' ') { - c = c.substring(1); - } - if (c.indexOf(name) == 0) { - return Number(c.substring(name.length, c.length)); - } - } - return 3000; - } - </script> - <style> - .dash-loader { - display: flex; - align-content: center; - justify-content: center; - background-color: #AEDDF8; - transition: 3s; - z-index: 10; - width: 100vw; - height: 100vh; - } - - .dash-loader-container { - display: grid; - grid-auto-rows: auto 30px auto; - } - - .dash-progress-bar { - width: 200px; - height: 5px; - align-self: center; - margin-top: 20px; - background-color: #ececec; - border-radius: 5px; - overflow: hidden; - } - - .dash-progress { - width: 0%; - height: 20px; - background-color: #5b9fdd; - transition: 0.1s; - } - - .dash-animation-container { - width: 10vw; - height: 10vw; - display: flex; - align-items: center; - justify-content: center; - border-radius: 100%; - background-color: #5B9FDD; - justify-self: center; - align-self: flex-end; - } - - .dash-loader-text { - font-size: 15px; - font-family: "Roboto"; - text-align: center; - color: #5B9FDD; - } - - .dash-d-path { - stroke-dasharray: 1000; - stroke-dashoffset: 1000; - animation: dash-d-path 3s linear infinite; - } - - @keyframes dash-d-path { - 0% { - stroke-dashoffset: 1000; - } - - 20% { - stroke-dashoffset: 0; - } - - 70% { - stroke-dashoffset: 0; - } - - 90% { - stroke-dashoffset: 1000; - } - - 100% { - stroke-dashoffset: 1000; - } - } - </style> + <script src="loader.js"></script> + <link rel="stylesheet" href="./loader.css" /> </head> <body style="display:flex" id="dash-body"> - <div class="dash-loader" id="loader" style="z-index:10; width:100%; height:100%;"> + <div class="dash-loader" id="loader"> <div class="dash-loader-container"> <div class="dash-animation-container"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" @@ -127,7 +35,7 @@ console.log("Last Load = " + load); let dashmesg = (width, msg) => { if (document.getElementById("dash-progress")) document.getElementById("dash-progress").style.width = width - if (document.getElementById("dash-progress")) document.getElementById("dash-progress").innerHTML = msg + if (document.getElementById("dash-progress")) document.getElementById("dash-loader-text").innerHTML = msg } setTimeout(() => dashmesg("10%", "Loading Dash..."), load / 10); setTimeout(() => dashmesg("33%", "Preparing dashboards..."), load / 3); diff --git a/deploy/loader.css b/deploy/loader.css new file mode 100644 index 000000000..4be0cc98c --- /dev/null +++ b/deploy/loader.css @@ -0,0 +1,85 @@ +.dash-loader { + display: flex; + align-content: center; + justify-content: center; + background-color: #BDDDF5; + transition: 3s; + z-index: 10; + z-index:10; + width:100%; + height:100%; +} + +.dash-loader-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + align-content: center; +} + +.dash-progress-bar { + width: 200px; + height: 5px; + align-self: center; + margin-top: 20px; + background-color: #ececec; + border-radius: 5px; + overflow: hidden; +} + +.dash-progress { + width: 0%; + height: 20px; + background-color: #4476F7; + transition: 0.1s; +} + +.dash-animation-container { + width: 10vw; + height: 10vw; + display: flex; + align-items: center; + justify-content: center; + border-radius: 100%; + background-color: #4476F7; + justify-self: center; +} + +.dash-loader-text { + font-size: 15px; + font-family: "Roboto"; + font-weight: bold; + text-align: center; + color: #4476F7; + user-select: none; + -webkit-user-select: none; +} + +.dash-d-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-d-path 3s linear infinite; +} + +@keyframes dash-d-path { + 0% { + stroke-dashoffset: 1000; + } + + 20% { + stroke-dashoffset: 0; + } + + 70% { + stroke-dashoffset: 0; + } + + 90% { + stroke-dashoffset: 1000; + } + + 100% { + stroke-dashoffset: 1000; + } +}
\ No newline at end of file diff --git a/deploy/loader.js b/deploy/loader.js new file mode 100644 index 000000000..0be421e14 --- /dev/null +++ b/deploy/loader.js @@ -0,0 +1,14 @@ +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == ' ') { + c = c.substring(1); + } + if (c.indexOf(name) == 0) { + return Number(c.substring(name.length, c.length)); + } + } + return 3000; +}
\ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e863b4198..72b52616a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -45,14 +45,14 @@ import { LabelBox } from "../views/nodes/LabelBox"; import { LinkBox } from "../views/nodes/LinkBox"; import { LinkDescriptionPopup } from "../views/nodes/LinkDescriptionPopup"; import { PDFBox } from "../views/nodes/PDFBox"; -import { PresBox } from "../views/nodes/PresBox"; +import { PresBox } from "../views/nodes/trails/PresBox"; import { ScreenshotBox } from "../views/nodes/ScreenshotBox"; import { ScriptingBox } from "../views/nodes/ScriptingBox"; import { SliderBox } from "../views/nodes/SliderBox"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; import { VideoBox } from "../views/nodes/VideoBox"; import { WebBox } from "../views/nodes/WebBox"; -import { PresElementBox } from "../views/presentationview/PresElementBox"; +import { PresElementBox } from "../views/nodes/trails/PresElementBox"; import { SearchBox } from "../views/search/SearchBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 22504f102..62fab1b23 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -35,6 +35,8 @@ import { UndoManager } from "./UndoManager"; import { SnappingManager } from "./SnappingManager"; import { InkTool } from "../../fields/InkField"; import { computedFn } from "mobx-utils"; +import { ColorScheme } from "./SettingsManager"; +import { Colors } from "../views/global/globalEnums"; export let resolvedPorts: { server: number, socket: number }; @@ -472,7 +474,7 @@ export class CurrentUserUtils { { toolTip: "Tap to create a videoWall", title: "Wall", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWall as Doc }, { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true }, { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc }, - { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, + // { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true }, { toolTip: "Tap to create a scripting box in a new pane, drag for a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScript as Doc }, { toolTip: "Tap to create a mobile view in a new pane, drag for a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, { toolTip: "Tap to create a custom header note document, drag for a custom header note", title: "Custom", icon: "window-maximize", click: 'openOnRight(delegateDragFactory(this.dragFactory))', drag: 'delegateDragFactory(this.dragFactory)', dragFactory: doc.emptyHeader as Doc }, @@ -534,8 +536,8 @@ export class CurrentUserUtils { { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc }, // { title: "Filter", target: Cast(doc.currentFilter, Doc, null), icon: "filter", click: 'selectMainMenu(self)' }, { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' }, - { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' }, - { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' }, + // { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' }, + // { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' }, { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' }, ]; } @@ -561,7 +563,6 @@ export class CurrentUserUtils { dontUndo: true, title, target, - backgroundColor: "black", _dropAction: "alias", _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]), _width: 60, @@ -576,8 +577,10 @@ export class CurrentUserUtils { title: "menuItemPanel", childDropAction: "alias", _chromeHidden: true, + backgroundColor: Colors.DARK_GRAY, + boxShadow: "rgba(0,0,0,0)", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), - backgroundColor: "black", ignoreClick: true, + ignoreClick: true, _gridGap: 0, _yMargin: 0, _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true @@ -587,8 +590,6 @@ export class CurrentUserUtils { PromiseValue(Cast(doc.menuStack, Doc)).then(stack => { stack && PromiseValue(stack.data).then(btns => { DocListCastAsync(btns).then(bts => bts?.forEach(btn => { - btn.color = "white"; - btn._backgroundColor = ""; btn.dontUndo = true; btn.system = true; if (btn.title === "Catalog" || btn.title === "My Files") { // migration from Catalog to My Files @@ -759,7 +760,7 @@ export class CurrentUserUtils { await doc.myDashboards; if (doc.myDashboards === undefined) { doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "My Dashboards", _height: 400, childHideLinkButton: true, + title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true @@ -775,7 +776,7 @@ export class CurrentUserUtils { await doc.myPresentations; if (doc.myPresentations === undefined) { doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "My Presentations", _height: 100, + title: "My Trails", _showTitle: "title", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true @@ -794,7 +795,7 @@ export class CurrentUserUtils { doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileRoot as Doc, doc.myFileOrphans as Doc], { - title: "My Documents", _height: 100, + title: "My Documents", _showTitle: "title", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, @@ -808,7 +809,7 @@ export class CurrentUserUtils { // setup Recently Closed library item if (doc.myRecentlyClosedDocs === undefined) { doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "Recently Closed", treeViewShowClearButton: true, childHideLinkButton: true, + title: "Recently Closed", _showTitle: "title", treeViewShowClearButton: true, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true @@ -839,7 +840,7 @@ export class CurrentUserUtils { doc.treeViewOpen = true; doc.treeViewExpandedView = "fields"; doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], { - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true })) as any as Doc; @@ -859,6 +860,7 @@ export class CurrentUserUtils { static async setupSidebarButtons(doc: Doc) { CurrentUserUtils.setupSidebarContainer(doc); await CurrentUserUtils.setupToolsBtnPanel(doc); + CurrentUserUtils.setupImportSidebar(doc); CurrentUserUtils.setupDashboards(doc); CurrentUserUtils.setupPresentations(doc); CurrentUserUtils.setupFilesystem(doc); @@ -891,6 +893,7 @@ export class CurrentUserUtils { (doc["dockedBtn-undo"] as Doc).dontUndo = true; (doc["dockedBtn-redo"] as Doc).dontUndo = true; } + // sets up the default set of documents to be shown in the Overlay layer static setupOverlays(doc: Doc) { if (doc.myOverlayDocs === undefined) { @@ -924,7 +927,8 @@ export class CurrentUserUtils { if (!sharedDocs) { sharedDocs = Docs.Create.StackingDocument([], { title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "none", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, - _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, _chromeHidden: true, + _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, + _chromeHidden: true, boxShadow: "0 0", }, sharingDocumentId + "outer", sharingDocumentId); (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Add; } @@ -939,14 +943,14 @@ export class CurrentUserUtils { static setupImportSidebar(doc: Doc) { if (doc.myImportDocs === undefined) { doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { - title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, + title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeHidden: true, })); } if (doc.myImportPanel === undefined) { const uploads = Cast(doc.myImportDocs, Doc, null); const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true }); - doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true })); + doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, _showTitle: "title", ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true, boxShadow: "0 0" })); } } @@ -1007,10 +1011,14 @@ export class CurrentUserUtils { const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || []; SnappingManager.SetCachedGroups(["Public", ...mygroups?.map(g => StrCast(g.title))]); }, { fireImmediately: true }); + // Document properties on load doc.system = true; + doc.darkScheme = ColorScheme.Dark; doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode; doc.title = Doc.CurrentUserEmail; doc._raiseWhenDragged = true; + doc._showLabel = false; + doc._showMenuLabel = true; doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)"); doc.activeInkWidth = StrCast(doc.activeInkWidth, "1"); doc.activeInkBezier = StrCast(doc.activeInkBezier, "0"); @@ -1201,7 +1209,7 @@ export class CurrentUserUtils { const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); Doc.AddDocToList(myPresentations, "data", presentation); userDoc.activePresentation = presentation; - const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); + const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`); const createDashboard = ScriptField.MakeScript(`createNewDashboard()`); @@ -1257,6 +1265,4 @@ Scripting.addGlobal(function createNewPresentation() { return MainView.Instance. Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, "returns all the links to the document or its annotations", "(doc: any)"); Scripting.addGlobal(function importDocument() { return CurrentUserUtils.importDocument(); }, - "imports files from device directly into the import sidebar"); -Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }, - "toggle between regular rendeing and an informal sketch/comic style"); + "imports files from device directly into the import sidebar");
\ No newline at end of file diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 777394b05..3987497b8 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -18,6 +18,12 @@ const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; +export enum ColorScheme { + Dark = "Dark", + Light = "Light", + System = "Match System" +} + @observer export class SettingsManager extends React.Component<{}> { public static Instance: SettingsManager; @@ -32,7 +38,7 @@ export class SettingsManager extends React.Component<{}> { @observable activeTab = "Accounts"; @computed get backgroundColor() { return Doc.UserDoc().activeCollectionBackground; } - + @computed get colorScheme() { return Doc.UserDoc().colorScheme; } constructor(props: {}) { super(props); @@ -69,6 +75,28 @@ export class SettingsManager extends React.Component<{}> { else DocServer.Control.makeEditable(); }); + @undoBatch + @action + changeColorScheme = action((e: React.ChangeEvent) => { + const scheme: ColorScheme = (e.currentTarget as any).value; + switch (scheme) { + case ColorScheme.Light: + Doc.UserDoc().colorScheme = ColorScheme.Light; + addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "#d3d3d3 !important" }); + break; + case ColorScheme.Dark: + Doc.UserDoc().colorScheme = ColorScheme.Dark; + addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "black !important" }); + break; + case ColorScheme.System: default: + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { + Doc.UserDoc().colorScheme = e.matches ? ColorScheme.Dark : ColorScheme.Light; + }); + break; + } + }); + + @computed get colorsContent() { const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(this.backgroundColor)} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', @@ -90,8 +118,7 @@ export class SettingsManager extends React.Component<{}> { </Flyout> </div>; - 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"]; + const colorSchemes = [ColorScheme.Light, ColorScheme.Dark, ColorScheme.System]; return <div className="colors-content"> <div className="preferences-color"> @@ -102,14 +129,11 @@ export class SettingsManager extends React.Component<{}> { <div className="preferences-color-text">Border/Header Color</div> {userColorFlyout} </div> - <div className="preferences-font"> - <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>)} + <div className="preferences-colorScheme"> + <div className="preferences-color-text">Color Scheme</div> + <div className="preferences-color-controls"> + <select className="scheme-select" onChange={this.changeColorScheme} defaultValue={StrCast(Doc.UserDoc().colorScheme)}> + {colorSchemes.map(scheme => <option key={scheme} value={scheme}> {scheme} </option>)} </select> </div> </div> @@ -132,6 +156,16 @@ export class SettingsManager extends React.Component<{}> { checked={BoolCast(Doc.UserDoc()._raiseWhenDragged)} /> <div className="preferences-check">Raise on drag</div> </div> + <div> + <input type="checkbox" onChange={e => Doc.UserDoc()._showLabel = !Doc.UserDoc()._showLabel} + checked={BoolCast(Doc.UserDoc()._showLabel)} /> + <div className="preferences-check">Show tool button labels</div> + </div> + <div> + <input type="checkbox" onChange={e => Doc.UserDoc()._showMenuLabel = !Doc.UserDoc()._showMenuLabel} + checked={BoolCast(Doc.UserDoc()._showMenuLabel)} /> + <div className="preferences-check">Show menu button labels</div> + </div> </div>; } @@ -149,6 +183,27 @@ export class SettingsManager extends React.Component<{}> { </div>; } + @computed get textContent() { + + const fontFamilies = ["Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text", "Roboto"]; + const fontSizes = ["7px", "8px", "9px", "10px", "12px", "14px", "16px", "18px", "20px", "24px", "32px", "48px", "72px"]; + + return ( + <div className="tab-content appearances-content"> + <div className="preferences-font"> + <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>); + } + @action changeVal = (e: React.ChangeEvent, pass: string) => { const value = (e.target as any).value; @@ -228,7 +283,7 @@ export class SettingsManager extends React.Component<{}> { // { 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 }]; + { title: "Appearance", ele: this.appearanceContent }, { title: "Text", ele: this.textContent }]; return <div className="settings-interface"> <div className="settings-panel"> diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index 2bac03af4..e23bf27c1 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -6,7 +6,8 @@ z-index: 10001; height: $antimodemenu-height; background: $dark-gray; - box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); + border-bottom: $standard-border; + // box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); // border-radius: 0px 6px 6px 6px; z-index: 1001; display: flex; diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index a5d80cd22..1e5380971 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../fields/Doc"; +import { Doc, DocCastAsync } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast, StrCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents, simulateMouseClick } from "../../Utils"; @@ -24,7 +24,7 @@ import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import { TemplateMenu } from "./TemplateMenu"; import React = require("react"); -import { PresBox } from './nodes/PresBox'; +import { PresBox } from './nodes/trails/PresBox'; import { undoBatch } from '../util/UndoManager'; import { CollectionViewType } from './collections/CollectionView'; const higflyout = require("@hig/flyout"); @@ -348,16 +348,17 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV if (!this.view0) return (null); const isText = this.view0.props.Document[this.view0.LayoutFieldKey] instanceof RichTextField; + const doc = this.view0?.props.Document; const considerPull = isText && this.considerGoogleDocsPull; const considerPush = isText && this.considerGoogleDocsPush; return <div className="documentButtonBar"> <div className="documentButtonBar-button"> <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} /> </div> - {DocumentLinksButton.StartLink || !Doc.UserDoc()["documentLinksButton-fullMenu"] ? <div className="documentButtonBar-button"> + {(DocumentLinksButton.StartLink || Doc.UserDoc()["documentLinksButton-fullMenu"]) && DocumentLinksButton.StartLink != doc ? <div className="documentButtonBar-button"> <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} /> </div> : (null)} - {!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) : <div className="documentButtonBar-button"> + {/*!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) : <div className="documentButtonBar-button"> {this.templateButton} </div> /*<div className="documentButtonBar-button"> diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 07ca0257c..ba1c91720 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -22,10 +22,6 @@ height: 100%; } -.mainContent-div-flyout { - left: calc(-1 * var(--flyoutHandleWidth)); -} - // add nodes menu. Note that the + button is actually an input label, not an actual button. .mainView-docButtons { position: absolute; @@ -111,14 +107,21 @@ user-select: none; } +.properties-container { + height: 100%; + position: relative; + left: 100%; + top: calc(-100% - 36px); + z-index: 3000; +} + .mainView-propertiesDragger { //background-color: rgb(140, 139, 139); - background-color: $light-gray; + background-color: $medium-gray; height: 55px; width: 17px; position: absolute; top: 50%; - border: 1px black solid; border-radius: 0; border-top-left-radius: 10px; border-bottom-left-radius: 10px; @@ -141,18 +144,6 @@ } } -.mainiView-propertiesView { - display: flex; - flex-direction: column; - height: 100%; - position: absolute; - right: 0; - top: 0; - border-left: solid 1px; - z-index: 100000; - cursor: auto; -} - .mainView-innerContent, .mainView-innerContent-dark { display: contents; flex-direction: row; @@ -171,7 +162,7 @@ } .propertiesView { - right: 0; + left: 0; position: absolute; z-index: 2; background-color: $medium-gray; @@ -220,6 +211,7 @@ .mainView-menuPanel { min-width: var(--menuPanelWidth); background-color: $dark-gray; + border-right: $standard-border; .collectionStackingView { scrollbar-width: none; @@ -419,31 +411,4 @@ display: block; width: 500px; height: 1000px; -} - -.lm_drag_tab { - padding: 0; - width: 15px !important; - height: 15px !important; - position: relative !important; - display: inline-flex !important; - align-items: center; - top: 0 !important; - right: unset !important; - left: 0 !important; -} -.lm_close_tab { - padding: 0; - width: 15px !important; - height: 15px !important; - position: relative !important; - display: inline-flex !important; - align-items: center; - top: 0 !important; - right: unset !important; - left: 0 !important; -} -.lm_tab, .lm_tab_active { - display: flex !important; - padding-right: 0 !important; }
\ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f34851b00..49f4f7a6e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -63,6 +63,8 @@ import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { SearchBox } from './search/SearchBox'; import { DefaultStyleProvider, DashboardStyleProvider, StyleProp } from './StyleProvider'; +import { TopBar } from './topbar/TopBar'; +import { Colors } from './global/globalEnums'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -78,7 +80,7 @@ export class MainView extends React.Component { @observable private _sidebarContent: any = this.userDoc?.sidebar; @observable private _flyoutWidth: number = 0; - @computed private get topOffset() { return (CollectionMenu.Instance?.Pinned ? 35 : 0) + Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } + @computed private get topOffset() { return Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } //TODO remove @computed private get leftOffset() { return this.menuPanelWidth() - 2; } @computed private get userDoc() { return Doc.UserDoc(); } @computed private get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } @@ -178,12 +180,12 @@ export class MainView extends React.Component { const targets = document.elementsFromPoint(e.x, e.y); if (targets.length) { const targClass = targets[0].className.toString(); - if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { - const check = targets.some((thing) => - (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || - thing.className === "collectionSchema-header-menuOptions")); - !check && SearchBox.Instance.resetSearch(true); - } + // if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { + // const check = targets.some((thing) => + // (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || + // thing.className === "collectionSchema-header-menuOptions")); + // !check && SearchBox.Instance.resetSearch(true); + // } !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu(); } @@ -192,7 +194,7 @@ export class MainView extends React.Component { initEventListeners = () => { window.addEventListener("drop", e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page window.addEventListener("dragover", e => e.preventDefault(), false); - document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); + // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined)); document.addEventListener("pointerdown", this.globalPointerDown); document.addEventListener("click", (e: MouseEvent) => { if (!e.cancelBubble) { @@ -242,8 +244,9 @@ export class MainView extends React.Component { } getPWidth = () => this._panelWidth - this.propertiesWidth(); - getPHeight = () => this._panelHeight; + getPHeight = () => this._panelHeight - (CollectionMenu.Instance?.Pinned ? 35 : 0); getContentsHeight = () => this._panelHeight; + getMenuPanelHeight = () => this._panelHeight + (CollectionMenu.Instance?.Pinned ? 35 : 0); @computed get mainDocView() { return <DocumentView key="main" @@ -275,10 +278,12 @@ export class MainView extends React.Component { @computed get dockingContent() { return <div key="docking" className={`mainContent-div${this._flyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }} + // style={{ minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, width: `calc(100% - ${this._flyoutWidth + this.propertiesWidth()}px)` }}> + // FIXME update with property panel width style={{ minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined, - width: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)` + //TODO:glr width: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)` }}> {!this.mainContainer ? (null) : this.mainDocView} </div>; @@ -358,7 +363,7 @@ export class MainView extends React.Component { removeDocument={returnFalse} ScreenToLocalTransform={this.sidebarScreenToLocal} PanelWidth={this.menuPanelWidth} - PanelHeight={this.getContentsHeight} + PanelHeight={this.getMenuPanelHeight} renderDepth={0} docViewPath={returnEmptyDoclist} focus={DocUtils.DefaultFocus} @@ -401,20 +406,27 @@ export class MainView extends React.Component { } @computed get mainInnerContent() { + const width = this.propertiesWidth() + this._flyoutWidth + this.menuPanelWidth(); + const transform = this._flyoutWidth ? 'translate(-28px, 0px)' : undefined; return <> {this.menuPanel} <div key="inner" className={`mainView-innerContent${this.darkScheme ? "-dark" : ""}`}> {this.flyout} - <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined, }} onPointerDown={this.onFlyoutPointerDown} > + <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} > <FontAwesomeIcon icon="chevron-left" color={this.darkScheme ? "white" : "black"} style={{ opacity: "50%" }} size="sm" /> </div> + <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)`, transform: transform }}> + <CollectionMenu /> - {this.dockingContent} + {this.dockingContent} - <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1 }}> - <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.darkScheme ? "white" : "black"} size="sm" /> + <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._flyoutWidth ? 0 : this.propertiesWidth() - 1 }}> + <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.darkScheme ? Colors.WHITE : Colors.BLACK} size="sm" /> + </div> + <div className="properties-container"> + {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.getContentsHeight()} />} + </div> </div> - {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.getContentsHeight()} />} </div> </>; } @@ -525,35 +537,8 @@ export class MainView extends React.Component { @computed get search() { TraceMobx(); - return <div className="mainView-searchPanel"> - <SearchBox Document={CurrentUserUtils.MySearchPanelDoc} - DataDoc={CurrentUserUtils.MySearchPanelDoc} - fieldKey="data" - dropAction="move" - isSelected={returnTrue} - isContentActive={returnTrue} - select={returnTrue} - setHeight={returnFalse} - addDocument={undefined} - addDocTab={this.addDocTabFunc} - pinToPres={emptyFunction} - rootSelected={returnTrue} - styleProvider={DefaultStyleProvider} - layerProvider={undefined} - removeDocument={undefined} - ScreenToLocalTransform={Transform.Identity} - PanelWidth={this.getPWidth} - PanelHeight={this.getPHeight} - renderDepth={0} - focus={DocUtils.DefaultFocus} - docViewPath={returnEmptyDoclist} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} /> + return <div className="mainView-topbar"> + <TopBar /> </div>; } @@ -605,7 +590,6 @@ export class MainView extends React.Component { <GoogleAuthenticationManager /> <DocumentDecorations boundsLeft={this.leftOffset} boundsTop={this.topOffset} /> {this.search} - <CollectionMenu /> {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null} {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)} {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 4df3e4f00..8136edf04 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -24,7 +24,7 @@ import { EditableView } from "./EditableView"; import { InkStrokeProperties } from "./InkStrokeProperties"; import { DocumentView, StyleProviderFunc } from "./nodes/DocumentView"; import { KeyValueBox } from "./nodes/KeyValueBox"; -import { PresBox } from "./nodes/PresBox"; +import { PresBox } from "./nodes/trails/PresBox"; import { PropertiesButtons } from "./PropertiesButtons"; import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; import "./PropertiesView.scss"; diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss index 56346b68b..140be2140 100644 --- a/src/client/views/_nodeModuleOverrides.scss +++ b/src/client/views/_nodeModuleOverrides.scss @@ -1,8 +1,49 @@ +@import "./global/globalCssVariables"; // this file is for overriding all the css from installed node modules // goldenlayout stuff div .lm_header { background: $dark-gray; + overflow: hidden; +} + +/* Width */ +.lm_header::-webkit-scrollbar { + -webkit-appearance: none; + display: none; +} + +/* Width */ +.lm_header:hover::-webkit-scrollbar { + -webkit-appearance: none; + display: block; + height: 0px; +} + +/* Track */ +.lm_header:hover::-webkit-scrollbar-track { + -webkit-appearance: none; + display: none; +} + +/* Handle */ +.lm_header:hover::-webkit-scrollbar-thumb { + -webkit-appearance: none; + background: $dark-gray; +} + +/* Handle on hover */ +.lm_header:hover::-webkit-scrollbar-thumb:hover { + -webkit-appearance: none; + background: $dark-gray; +} + +.lm_tabs { + display: flex; + position: absolute; + width: calc(100% - 60px); + overflow: scroll; + background: $dark-gray; } .lm_tab { @@ -15,7 +56,14 @@ div .lm_header { } .lm_header .lm_controls { - right: 1em !important; + align-items: center; + position: absolute; + background-color: $dark-gray; + border-radius: 5px; + display: flex; + justify-content: space-evenly; + height: 18px; + width: 65px; } // @TODO the ril__navgiation buttons in the img gallery are a lil messed up but I can't figure out diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index a054f0ae1..b8180fe24 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,40 +1,46 @@ -@import "../../views/global/globalCssVariables.scss"; +@import "../global/globalCssVariables.scss"; .lm_title { - margin-top: 3px; - border-radius: 5px; - border: solid 0px dimgray; - border-width: 2px 2px 0px; - height: 20px; - transform: translate(0px, -3px); + -webkit-appearance: none; + display: inline-block; + align-self: center; + align-items: center; + height: 100%; + overflow: hidden; + text-overflow: ellipsis; + background: transparent; + border: solid 0px transparent; cursor: grab; + color: $black; } .lm_title.focus-visible { + -webkit-appearance: none; cursor: text; } .lm_title_wrap { overflow: hidden; - height: 19px; - margin-top: -2px; - display: inline-block; + align-items: center; + align-self: center; + background: transparent; + width: max-content; + height: 100%; + display: flex; } .lm_active .lm_title { - border: solid 1px lightgray; -} - -.lm_header .lm_tab .lm_close_tab { - position: absolute; - text-align: center; + -webkit-appearance: none; + // font-weight: 700; } .lm_header .lm_tab { - padding-right: 20px; - margin-top: -1px; - border-bottom: 1px black; + padding: 0px; + opacity: 0.7; + box-shadow: none; + height: 19px; + // border-bottom: 1px black; .collectionDockingView-gear { display: none; @@ -42,9 +48,13 @@ } .lm_header .lm_tab.lm_active { - padding-right: 20px; - margin-top: 1px; - border-bottom: unset; + padding: 0; + opacity: 1; + margin: 0; + box-shadow: none; + height: 22px; + margin-right: 2px; + // border-bottom: unset; .collectionDockingView-gear { display: inline-block; @@ -55,6 +65,41 @@ display: inline; } +.lm_drag_tab { + padding: 0; + width: 15px !important; + height: 15px !important; + position: relative !important; + display: inline-flex !important; + align-items: center; + top: 0 !important; + right: unset !important; + left: 0 !important; +} + +.lm_close_tab { + padding: 0; + align-self: center; + margin-right: 5px; + background-color: black; + border-radius: 3px; + opacity: 1 !important; + width: 15px !important; + height: 15px !important; + position: relative !important; + display: inline-flex !important; + align-items: center; + top: 0 !important; + right: unset !important; + left: 0 !important; +} + +.lm_tab, +.lm_tab_active { + display: flex !important; + padding-right: 0 !important; +} + .collectiondockingview-container { width: 100%; height: 100%; @@ -82,16 +127,17 @@ } .lm_content { - background: white; + background: $white; } .lm_controls>li { - opacity: 0.6; - transform: scale(1.2); + opacity: 1; + transform: scale(1); } .lm_controls .lm_popout { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAAAAABHICnvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAHdElNRQfkCBsXMgbrEyzaAAAAT0lEQVQY02NgIAcIu8tgEW3/u4IDQ5B14/8LQlhFhckVFfCJjIyIOfP/QWpEZGSQJFS05s9fIPj3/z+YmseCTxS7CZS7DI+PsYcOjpAkDAA6H0KZxzDzlgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0wOC0yN1QyMzo1MDowNi0wNDowMDvgVpQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMDgtMjdUMjM6NTA6MDYtMDQ6MDBKve4oAAAAAElFTkSuQmCC) + transform: rotate(45deg); + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=); } .lm_maximised .lm_controls .lm_maximise { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 388f9a909..a8471f8e2 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -445,4 +445,4 @@ Scripting.addGlobal(function openInLightbox(doc: any) { LightboxView.AddDocTab(d "opens up document in a lightbox", "(doc: any)"); Scripting.addGlobal(function openOnRight(doc: any) { return CollectionDockingView.AddSplit(doc, "right"); }, "opens up document in tab on right side of the screen", "(doc: any)"); -Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); }); +Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); });
\ No newline at end of file diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index c0fc774d3..f04b19ef7 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -38,10 +38,10 @@ border: unset; .collectionMenu-divider { - height: 85%; + height: 100%; margin-left: 3px; margin-right: 3px; - width: 1.5px; + width: 2px; background-color: $medium-gray; } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 6e6fabd0d..a9b978c4e 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -29,7 +29,7 @@ import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocumentView } from "../nodes/DocumentView"; import { RichTextMenu } from "../nodes/formattedText/RichTextMenu"; -import { PresBox } from "../nodes/PresBox"; +import { PresBox } from "../nodes/trails/PresBox"; import "./CollectionMenu.scss"; import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { TabDocView } from "./TabDocView"; diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss index 9acbc4f85..a963f1cb9 100644 --- a/src/client/views/collections/TabDocView.scss +++ b/src/client/views/collections/TabDocView.scss @@ -1,19 +1,62 @@ input.lm_title:focus, -input.lm_title -{ +input.lm_title { max-width: unset !important; + outline: none; transition-delay: unset; - width: 100%; + width: max-content; cursor: text; } + input.lm_title { transition-delay: 0.35s; - width: 100px; + width: max-content; cursor: pointer; } -.tabDocView-drag { - margin: auto; + +.lm_iconWrap { + display: flex; + color: black; + width: 15px; + height: 15px; + align-items: center; + align-self: center; + justify-content: center; + margin: 3px; + border-radius: 20%; + + .moreInfoDot { + background-color: white; + border-radius: 100%; + width: 3px; + height: 3px; + margin: 0.5px; + } +} + +.ffMenu { + display: grid; + grid-auto-rows: 35px; + grid-auto-columns: auto auto auto auto auto; + right: 10px; + bottom: 50px; + position: absolute; + min-height: 35px; + height: max-content; + border: solid 2px black; + border-radius: 5px; + background-color: #bddbe6; + width: max-content; + min-width: 35px; + + .ffMenuButton { + display: flex; + width: 35px; + height: 35px; + align-items: center; + justify-content: center; + } } + .miniMap-hidden, .miniMap { position: absolute; @@ -37,6 +80,7 @@ input.lm_title { } } } + .miniMap-hidden { position: absolute; bottom: 0; @@ -46,7 +90,8 @@ input.lm_title { transform: translate(20px, 20px) rotate(45deg); border-radius: 30px; padding: 2px; - > svg { + + >svg { margin-top: 3px; transform: translate(0px, 7px); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 7e2f7811e..d82810652 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -1,3 +1,4 @@ +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import 'golden-layout/src/css/goldenlayout-base.css'; @@ -9,9 +10,9 @@ import * as ReactDOM from 'react-dom'; import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from '../../../fields/FieldSymbols'; import { FieldId } from "../../../fields/RefField"; -import { Cast, NumCast, StrCast, BoolCast } from "../../../fields/Types"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; +import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -24,15 +25,15 @@ import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from "../../util/UndoManager"; import { LightboxView } from '../LightboxView'; import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView"; -import { FieldViewProps } from '../nodes/FieldView'; -import { PinProps, PresBox, PresMovement } from '../nodes/PresBox'; +import { PinProps, PresBox, PresMovement } from '../nodes/trails'; import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider'; import { CollectionDockingView } from './CollectionDockingView'; import { CollectionDockingViewMenu } from './CollectionDockingViewMenu'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import { CollectionViewType, CollectionView } from './CollectionView'; +import { CollectionView, CollectionViewType } from './CollectionView'; import "./TabDocView.scss"; import React = require("react"); +import Color = require('color'); const _global = (window /* browser */ || global /* node */) as any; interface TabDocViewProps { @@ -52,6 +53,14 @@ export class TabDocView extends React.Component<TabDocViewProps> { @computed get layoutDoc() { return this._document && Doc.Layout(this._document); } @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor))); } + @computed get tabTextColor() { return this._document?.type === DocumentType.PRES ? "black" : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color))); } + // @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]; + // const ybounds = bounds[3] - bounds[1]; + // const dim = Math.max(xbounds, ybounds); + // return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim }; + // } get stack() { return (this.props as any).glContainer.parent.parent; } get tab() { return (this.props as any).glContainer.tab; } @@ -65,15 +74,25 @@ export class TabDocView extends React.Component<TabDocViewProps> { tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true); tab.DashDoc = doc; CollectionDockingView.Instance.tabMap.add(tab); - + const iconType: IconProp = Doc.toIcon(doc); // setup the title element and set its size according to the # of chars in the title. Show the full title when clicked. const titleEle = tab.titleElement[0]; + const iconWrap = document.createElement("div"); + const closeWrap = document.createElement("div"); + + titleEle.size = StrCast(doc.title).length + 3; titleEle.value = doc.title; titleEle.onchange = undoBatch(action((e: any) => { titleEle.size = e.currentTarget.value.length + 3; Doc.GetProto(doc).title = e.currentTarget.value; })); + + const dragBtnDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction); + }; + + if (tab.element[0].children[1].children.length === 1) { const toggle = document.createElement("div"); toggle.style.width = "10px"; @@ -83,18 +102,42 @@ export class TabDocView extends React.Component<TabDocViewProps> { toggle.style.borderTopRightRadius = "7px"; toggle.style.position = "relative"; toggle.style.display = "inline-block"; - toggle.style.background = "gray"; - toggle.style.borderLeft = "solid 1px black"; + toggle.style.background = "transparent"; toggle.onclick = (e: MouseEvent) => { if (tab.contentItem === tab.header.parent.getActiveContentItem()) { tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : StyleLayers.Background; } }; - tab.element[0].style.borderTopRightRadius = "8px"; - tab.element[0].children[1].appendChild(toggle); - tab._disposers.layerDisposer = reaction(() => - ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), - ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true }); + iconWrap.className = "lm_iconWrap"; + iconWrap.id = "lm_iconWrap"; + closeWrap.className = "lm_iconWrap"; + closeWrap.id = "lm_closeWrap"; + closeWrap.onclick = (e: MouseEvent) => { + tab.header.parent.contentItem.remove(); + Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true); + }; + const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />; + const closeIcon = <FontAwesomeIcon icon={"times"} />; + ReactDOM.render(docIcon, iconWrap); + ReactDOM.render(closeIcon, closeWrap); + // tab.element[0].append(closeWrap); + tab.element[0].prepend(iconWrap); + tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), + ({ layer, color }) => { + const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color + titleEle.style.color = textColor; + titleEle.style.backgroundColor = "transparent"; + iconWrap.style.color = textColor; + closeWrap.style.color = textColor; + moreInfoDrag.style.backgroundColor = textColor; + tab.element[0].style.background = !layer ? color : "dimgrey"; + }, { fireImmediately: true }); + // TODO:glr fix + // tab.element[0].style.borderTopRightRadius = "8px"; + // tab.element[0].children[1].appendChild(toggle); + // tab._disposers.layerDisposer = reaction(() => + // ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), + // ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true }); } // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: MouseEvent) => { @@ -103,13 +146,11 @@ export class TabDocView extends React.Component<TabDocViewProps> { tab.setActive(true); } }; - const dragBtnDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([dragHdl], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction); - }; + // select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected titleEle.onpointerdown = action((e: any) => { - if (e.target.className !== "lm_close_tab") { + if (e.target.className !== "lm_iconWrap") { if (this.view) SelectionManager.SelectView(this.view, false); else this._activated = true; if (Date.now() - titleEle.lastClick < 1000) titleEle.select(); @@ -123,25 +164,25 @@ export class TabDocView extends React.Component<TabDocViewProps> { const toggle = tab.element[0].children[1].children[0] as HTMLInputElement; selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch"); - toggle.style.fontWeight = selected ? "bold" : ""; - toggle.style.textTransform = selected ? "uppercase" : ""; + // toggle.style.fontWeight = selected ? "bold" : ""; + // toggle.style.textTransform = selected ? "uppercase" : ""; })); //attach the selection doc buttons menu to the drag handle const stack = tab.contentItem.parent; - const dragHdl = document.createElement("div"); - dragHdl.className = "lm_drag_tab"; + const moreInfoDrag = document.createElement("div"); + moreInfoDrag.className = "lm_iconWrap"; tab._disposers.buttonDisposer = reaction(() => this.view, view => - view && [ReactDOM.render(<span className="tabDocView-drag" onPointerDown={dragBtnDown}><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, dragHdl), tab._disposers.buttonDisposer?.()], + view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()], { fireImmediately: true }); - tab.reactComponents = [dragHdl]; - tab.closeElement.before(dragHdl); + // tab.reactComponents = [moreInfoDrag]; + // tab.element[0].children[3].before(moreInfoDrag); // highlight the tab when the tab document is brushed in any part of the UI tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => { titleEle.value = title; - titleEle.style.padding = degree ? 0 : 2; - titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; + // titleEle.style.padding = degree ? 0 : 2; + // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`; }, { fireImmediately: true }); // clean up the tab when it is closed @@ -221,9 +262,9 @@ export class TabDocView extends React.Component<TabDocViewProps> { })).observe(this.props.glContainer._element[0]); this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged); this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(undefined); - this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }), - ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""), - { fireImmediately: true }); + // this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }), + // ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""), + // { fireImmediately: true }); } componentWillUnmount() { @@ -243,10 +284,10 @@ export class TabDocView extends React.Component<TabDocViewProps> { } // adds a tab to the layout based on the locaiton parameter which can be: - // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, + // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, // add[:{left,right,top,bottom}] - e.g., "add" will add a tab to the current stack, "add:right" will add a tab on the right - // replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents, - // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, + // replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents, + // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name, // "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack addDocTab = (doc: Doc, location: string) => { @@ -460,4 +501,4 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> { </div> </div>; } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8ef0057bd..143d8e070 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -38,7 +38,7 @@ import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDo import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from "../../nodes/DocumentView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; -import { PresBox } from "../../nodes/PresBox"; +import { PresBox } from "../../nodes/trails/PresBox"; import { StyleLayers, StyleProp } from "../../StyleProvider"; import { CollectionDockingView } from "../CollectionDockingView"; import { CollectionSubView } from "../CollectionSubView"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1f4fcb2a5..846d28214 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -19,7 +19,8 @@ import { Transform } from "../../../util/Transform"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { ContextMenu } from "../../ContextMenu"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; -import { PresBox, PresMovement } from "../../nodes/PresBox"; +import { PresBox } from "../../nodes/trails/PresBox"; +import { PresMovement } from "../../nodes/trails/PresEnums"; import { PreviewCursor } from "../../PreviewCursor"; import { CollectionDockingView } from "../CollectionDockingView"; import { SubCollectionViewProps } from "../CollectionSubView"; diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss index ead5e166e..72adc171b 100644 --- a/src/client/views/global/globalCssVariables.scss +++ b/src/client/views/global/globalCssVariables.scss @@ -21,8 +21,6 @@ $large-padding: 32px; //icon sizes $icon-size: 28px; -$antimodemenu-height: 36px; - // fonts $sans-serif: "Noto Sans", sans-serif; $large-header: 16px; @@ -33,11 +31,16 @@ $small-text: 9px; // misc values $border-radius: 0.3em; $search-thumnail-size: 130; +$topbar-height: 32px; +$antimodemenu-height: 36px; // dragged items $contextMenu-zindex: 100000; // context menu shows up over everything $radialMenu-zindex: 100000; // context menu shows up over everything +// borders +$standard-border: solid 1px #9F9F9F; + $searchpanel-height: 32px; $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc $docDecorations-zindex: 998; // then doc decorations appear over everything else diff --git a/src/client/views/global/globalEnums.tsx b/src/client/views/global/globalEnums.tsx index 1e0381c33..2aeb8e338 100644 --- a/src/client/views/global/globalEnums.tsx +++ b/src/client/views/global/globalEnums.tsx @@ -31,4 +31,8 @@ export enum Padding { export enum IconSizes { ICON_SIZE = "28px", +} + +export enum Borders { + STANDARD = "solid 1px #9F9F9F" }
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 9b75cd8f9..3d2cdf5a4 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -11,7 +11,7 @@ import { CollectionFreeFormView } from "../collections/collectionFreeForm/Collec import { CollectionSchemaView } from "../collections/collectionSchema/CollectionSchemaView"; import { CollectionView } from "../collections/CollectionView"; import { InkingStroke } from "../InkingStroke"; -import { PresElementBox } from "../presentationview/PresElementBox"; +import { PresElementBox } from "../nodes/trails/PresElementBox"; import { SearchBox } from "../search/SearchBox"; import { DashWebRTCVideo } from "../webcam/DashWebRTCVideo"; import { YoutubeBox } from "./../../apis/youtube/YoutubeBox"; @@ -32,7 +32,7 @@ import { LabelBox } from "./LabelBox"; import { LinkAnchorBox } from "./LinkAnchorBox"; import { LinkBox } from "./LinkBox"; import { PDFBox } from "./PDFBox"; -import { PresBox } from "./PresBox"; +import { PresBox } from "./trails/PresBox"; import { ScreenshotBox } from "./ScreenshotBox"; import { ScriptingBox } from "./ScriptingBox"; import { SliderBox } from "./SliderBox"; diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index daffaf9e7..1fc71b5f8 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -44,16 +44,15 @@ } .documentLinksButton-endLink { - border: red solid 2px; - + border: $medium-blue 2px dashed; + color: $medium-blue; &:hover { - background: deepskyblue; + background: $light-gray; transform: scale(1.05); cursor: pointer; } } .documentLinksButton-startLink { - border: red solid 2px; - background-color: rgba(255, 192, 203, 0.5); + background-color: $medium-blue; }
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a6d07374a..e3cbade38 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -20,6 +20,7 @@ import './DocumentLinksButton.scss'; import { DocServer } from "../../DocServer"; import { LightboxView } from "../LightboxView"; import { cat } from "shelljs"; +import { Colors } from "../global/globalEnums"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; @@ -252,8 +253,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp <div className={"documentLinksButton"} onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick} style={{ - backgroundColor: this.props.InMenu ? "" : "#add8e6", - color: this.props.InMenu ? "white" : "black", + backgroundColor: this.props.InMenu ? "" : Colors.LIGHT_BLUE, + color: this.props.InMenu ? Colors.WHITE : "black", width: btnDim, height: btnDim, }} > @@ -267,17 +268,25 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp <div className={"documentLinksButton-endLink"} style={{ width: btnDim, height: btnDim, - backgroundColor: DocumentLinksButton.StartLink ? "" : "grey", + backgroundColor: DocumentLinksButton.StartLink ? "" : Colors.LIGHT_GRAY, opacity: DocumentLinksButton.StartLink ? "" : "50%", border: DocumentLinksButton.StartLink ? "" : "none", cursor: DocumentLinksButton.StartLink ? "pointer" : "default" }} onPointerDown={DocumentLinksButton.StartLink && this.completeLink} - onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)} /> + onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}> + {this.props.StartLink ? + <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> + : link} + </div> : (null) } {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? - <div className={"documentLinksButton-startLink"} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }} /> + <div className={"documentLinksButton-startLink"} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }}> + {this.props.StartLink ? + <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> + : link} + </div> : (null) } </div >; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 60fa462ad..80a014926 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -43,7 +43,7 @@ import { DocumentLinksButton } from './DocumentLinksButton'; import "./DocumentView.scss"; import { LinkAnchorBox } from './LinkAnchorBox'; import { LinkDocPreview } from "./LinkDocPreview"; -import { PresBox } from './PresBox'; +import { PresBox } from './trails/PresBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); import { ScriptingBox } from "./ScriptingBox"; diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 6ae4b9726..0d415e238 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -14,6 +14,7 @@ import { DocComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './FontIconBox.scss'; +import { Colors } from '../global/globalEnums'; const FontIconSchema = createSchema({ icon: "string", }); @@ -47,7 +48,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( const icon = StrCast(this.dataDoc.icon, "user") as any; const presSize = shape === 'round' ? 25 : 30; const presTrailsIcon = <img src={`/assets/${"presTrails.png"}`} - style={{ width: presSize, height: presSize, filter: `invert(${color === "white" ? "100%" : "0%"})`, marginBottom: "5px" }} />; + style={{ width: presSize, height: presSize, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})`, marginBottom: "5px" }} />; const button = <button className={`menuButton-${shape}`} onContextMenu={this.specificContextMenu} style={{ backgroundColor: backgroundColor, }}> <div className="menuButton-wrap"> diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 59b2d3753..d1c91cbb9 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -963,7 +963,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { this.createHighlighterButton(), this.createLinkButton(), this.createBrushButton(), - <div className="richTextMenu-divider" key="divider 2" />, + <div className="collectionMenu-divider" key="divider 2" />, this.createButton("align-left", "Align Left", this.activeAlignment === "left", this.alignLeft), this.createButton("align-center", "Align Center", this.activeAlignment === "center", this.alignCenter), this.createButton("align-right", "Align Right", this.activeAlignment === "right", this.alignRight), @@ -976,7 +976,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { const row2 = <div className="antimodeMenu-row row-2" key="row2"> {this.collapsed ? this.getDragger() : (null)} <div key="row 2" style={{ display: this.collapsed ? "none" : undefined }}> - <div className="richTextMenu-divider" key="divider 3" /> + <div className="collectionMenu-divider" key="divider 3" /> {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => { this.activeFontSize = val; SelectionManager.Views().map(dv => dv.props.Document._fontSize = val); @@ -985,12 +985,12 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { this.activeFontFamily = val; SelectionManager.Views().map(dv => dv.props.Document._fontFamily = val); })), - <div className="richTextMenu-divider" key="divider 4" />, + <div className="collectionMenu-divider" key="divider 4" />, this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})), this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer), this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote), - this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule), - <div className="richTextMenu-divider" key="divider 5" />,]} + this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule) + ]} </div> {/* <div key="collapser"> {<div key="collapser"> diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss index 5d1c5f4eb..06932d145 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/trails/PresBox.scss @@ -1,4 +1,4 @@ -@import "../global/globalCssVariables"; +@import "../../global/globalCssVariables"; .presBox-cont { cursor: auto; @@ -889,7 +889,7 @@ height: 13; font-size: 12; display: flex; - background-color: #white; + background-color: $white; } .subtitle { @@ -926,7 +926,7 @@ .presBox-buttons { position: relative; width: 100%; - background: gray; + background: $medium-gray; min-height: 35px; padding-top: 5px; padding-bottom: 5px; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index f3fb6ff17..5cb9866f8 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -5,67 +5,33 @@ import { action, computed, IReactionDisposer, observable, ObservableMap, reactio import { observer } from "mobx-react"; import { ColorState, SketchPicker } from "react-color"; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; -import { Doc, DocListCast, DocListCastAsync, FieldResult } from "../../../fields/Doc"; -import { documentSchema } from "../../../fields/documentSchemas"; -import { InkTool } from "../../../fields/InkField"; -import { List } from "../../../fields/List"; -import { PrefetchProxy } from "../../../fields/Proxy"; -import { listSpec, makeInterface } from "../../../fields/Schema"; -import { ScriptField } from "../../../fields/ScriptField"; -import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; -import { returnFalse, returnOne, returnTrue, emptyFunction } from '../../../Utils'; -import { Docs } from "../../documents/Documents"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { DocumentManager } from "../../util/DocumentManager"; -import { Scripting } from "../../util/Scripting"; -import { SelectionManager } from "../../util/SelectionManager"; -import { undoBatch, UndoManager } from "../../util/UndoManager"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionView, CollectionViewType } from "../collections/CollectionView"; -import { TabDocView } from "../collections/TabDocView"; -import { ViewBoxBaseComponent } from "../DocComponent"; -import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView"; -import { FieldView, FieldViewProps } from './FieldView'; +import { Doc, DocListCast, DocListCastAsync, FieldResult } from "../../../../fields/Doc"; +import { documentSchema } from "../../../../fields/documentSchemas"; +import { InkTool } from "../../../../fields/InkField"; +import { List } from "../../../../fields/List"; +import { PrefetchProxy } from "../../../../fields/Proxy"; +import { listSpec, makeInterface } from "../../../../fields/Schema"; +import { ScriptField } from "../../../../fields/ScriptField"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types"; +import { emptyFunction, returnFalse, returnOne, returnTrue } from '../../../../Utils'; +import { Docs } from "../../../documents/Documents"; +import { DocumentType } from "../../../documents/DocumentTypes"; +import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; +import { DocumentManager } from "../../../util/DocumentManager"; +import { Scripting } from "../../../util/Scripting"; +import { SelectionManager } from "../../../util/SelectionManager"; +import { undoBatch, UndoManager } from "../../../util/UndoManager"; +import { CollectionDockingView } from "../../collections/CollectionDockingView"; +import { CollectionView, CollectionViewType } from "../../collections/CollectionView"; +import { TabDocView } from "../../collections/TabDocView"; +import { ViewBoxBaseComponent } from "../../DocComponent"; +import { Colors } from "../../global/globalEnums"; +import { LightboxView } from "../../LightboxView"; +import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentView"; +import { FieldView, FieldViewProps } from '../FieldView'; import "./PresBox.scss"; import Color = require("color"); -import { LightboxView } from "../LightboxView"; - -export enum PresMovement { - Zoom = "zoom", - Pan = "pan", - Jump = "jump", - None = "none", -} - -export enum PresEffect { - Zoom = "Zoom", - Lightspeed = "Lightspeed", - Fade = "Fade in", - Flip = "Flip", - Rotate = "Rotate", - Bounce = "Bounce", - Roll = "Roll", - None = "None", - Left = "left", - Right = "right", - Center = "center", - Top = "top", - Bottom = "bottom" -} - -enum PresStatus { - Autoplay = "auto", - Manual = "manual", - Edit = "edit" -} - -export enum PresColor { - LightBlue = "#AEDDF8", - DarkBlue = "#5B9FDD", - LightBackground = "#ececec", - SlideBackground = "#d5dce2", -} +import { PresEffect, PresStatus, PresMovement } from "./PresEnums"; export class PinProps { audioRange?: boolean; @@ -1198,9 +1164,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> {this.scrollable ? "Scroll to pinned view" : !isPinWithView ? "No movement" : "Pan & Zoom to pinned view"} </div> : - <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}> + <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}> {this.setMovementName(activeItem.presMovement, activeItem)} - <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? PresColor.DarkBlue : 'black' }} icon={"angle-down"} /> + <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={"angle-down"} /> <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}> <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.None ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.None)}>None</div> <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Zoom ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Zoom)}>Pan {"&"} Zoom</div> @@ -1245,7 +1211,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-doubleButton"> {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideBefore ? "active" : ""}`} onClick={() => this.updateHideBefore(activeItem)}>Hide before</div></Tooltip>} {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideAfter ? "active" : ""}`} onClick={() => this.updateHideAfter(activeItem)}>Hide after</div></Tooltip>} - <Tooltip title={<><div className="dash-tooltip">{"Open in lightbox view"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? PresColor.LightBlue : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Lightbox</div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Open in lightbox view"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? Colors.LIGHT_BLUE : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Lightbox</div></Tooltip> </div> {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <> <div className="ribbon-doubleButton" > @@ -1280,9 +1246,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> {isPresCollection ? (null) : <div className="ribbon-box"> Effects - <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown; })} style={{ borderBottomLeftRadius: this.openEffectDropdown ? 0 : 5, border: this.openEffectDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}> + <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown; })} style={{ borderBottomLeftRadius: this.openEffectDropdown ? 0 : 5, border: this.openEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}> {effect} - <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? PresColor.DarkBlue : 'black' }} icon={"angle-down"} /> + <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={"angle-down"} /> <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}> <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.None || !targetDoc.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div> <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div> @@ -1299,11 +1265,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> </div> <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}> - <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${PresColor.LightBlue}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${Colors.LIGHT_BLUE}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip> </div> </div>} <div className="ribbon-final-box"> @@ -1356,7 +1322,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <> {this.panable || this.scrollable || this.targetDoc.type === DocumentType.COMPARISON ? 'Pinned view' : (null)} <div className="ribbon-doubleButton"> - <Tooltip title={<><div className="dash-tooltip">{activeItem.presPinView ? "Turn off pin with view" : "Turn on pin with view"}</div></>}><div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? PresColor.LightBlue : "" }} + <Tooltip title={<><div className="dash-tooltip">{activeItem.presPinView ? "Turn off pin with view" : "Turn on pin with view"}</div></>}><div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? Colors.LIGHT_BLUE : "" }} onClick={() => { activeItem.presPinView = !activeItem.presPinView; targetDoc.presPinView = activeItem.presPinView; @@ -1496,7 +1462,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="slider-text" style={{ fontWeight: 500 }}> Start time (s) </div> - <div id={"startTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}> + <div id={"startTime"} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}> <input className="presBox-input" style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }} type="number" value={NumCast(activeItem.presStartTime)} @@ -1508,7 +1474,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="slider-text" style={{ fontWeight: 500 }}> Duration (s) </div> - <div className="slider-number" style={{ backgroundColor: PresColor.LightBlue }}> + <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}> {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10} </div> </div> @@ -1516,7 +1482,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="slider-text" style={{ fontWeight: 500 }}> End time (s) </div> - <div id={"endTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}> + <div id={"endTime"} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}> <input className="presBox-input" style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }} type="number" value={NumCast(activeItem.presEndTime)} @@ -1534,16 +1500,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this._batch = UndoManager.StartBatch("presEndTime"); const endBlock = document.getElementById("endTime"); if (endBlock) { - endBlock.style.color = PresColor.LightBackground; - endBlock.style.backgroundColor = PresColor.DarkBlue; + endBlock.style.color = Colors.LIGHT_GRAY; + endBlock.style.backgroundColor = Colors.MEDIUM_BLUE; } }} onPointerUp={() => { this._batch?.end(); const endBlock = document.getElementById("endTime"); if (endBlock) { - endBlock.style.color = "black"; - endBlock.style.backgroundColor = PresColor.LightBackground; + endBlock.style.color = Colors.BLACK; + endBlock.style.backgroundColor = Colors.LIGHT_GRAY; } }} onChange={(e: React.ChangeEvent<HTMLInputElement>) => { @@ -1558,16 +1524,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this._batch = UndoManager.StartBatch("presStartTime"); const startBlock = document.getElementById("startTime"); if (startBlock) { - startBlock.style.color = PresColor.LightBackground; - startBlock.style.backgroundColor = PresColor.DarkBlue; + startBlock.style.color = Colors.LIGHT_GRAY; + startBlock.style.backgroundColor = Colors.MEDIUM_BLUE; } }} onPointerUp={() => { this._batch?.end(); const startBlock = document.getElementById("startTime"); if (startBlock) { - startBlock.style.color = "black"; - startBlock.style.backgroundColor = PresColor.LightBackground; + startBlock.style.color = Colors.BLACK; + startBlock.style.backgroundColor = Colors.LIGHT_GRAY; } }} onChange={(e: React.ChangeEvent<HTMLInputElement>) => { @@ -1651,15 +1617,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div> <div className={'presBox-toolbar-dropdown'} style={{ display: this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="layout-container" style={{ height: 'max-content' }}> - <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} /> - <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}> + <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} /> + <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}> <div className="title">Title</div> <div className="subtitle">Subtitle</div> </div> - <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}> + <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}> <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div> </div> - <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}> + <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}> <div className="title" style={{ alignSelf: 'center' }}>Title</div> <div className="content">Text goes here</div> </div> @@ -1691,26 +1657,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-box"> Choose type: <div className="ribbon-doubleButton"> - <div title="Text" className={'ribbon-toggle'} style={{ background: this.addFreeform ? "" : PresColor.LightBlue }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Text</div> - <div title="Freeform" className={'ribbon-toggle'} style={{ background: this.addFreeform ? PresColor.LightBlue : "" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Freeform</div> + <div title="Text" className={'ribbon-toggle'} style={{ background: this.addFreeform ? "" : Colors.LIGHT_BLUE }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Text</div> + <div title="Freeform" className={'ribbon-toggle'} style={{ background: this.addFreeform ? Colors.LIGHT_BLUE : "" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Freeform</div> </div> </div> <div className="ribbon-box" style={{ display: this.addFreeform ? "grid" : "none" }}> Preset layouts: <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}> - <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'blank')} /> - <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'title')}> + <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'blank')} /> + <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'title')}> <div className="title">Title</div> <div className="subtitle">Subtitle</div> </div> - <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'header')}> + <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'header')}> <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div> </div> - <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'content')}> + <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'content')}> <div className="title" style={{ alignSelf: 'center' }}>Title</div> <div className="content">Text goes here</div> </div> - <div className="layout" style={{ border: this.layout === 'twoColumns' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'twoColumns')}> + <div className="layout" style={{ border: this.layout === 'twoColumns' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'twoColumns')}> <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div> <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div> <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div> @@ -1869,8 +1835,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-box"> {this.stringType} selected <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}> - <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeChild}>Contents</div> - <div className="ribbon-toggle" style={{ opacity: activeItem.presProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editProgressivize ? PresColor.LightBlue : "" }} onClick={this.editProgressivize}>Edit</div> + <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeChild}>Contents</div> + <div className="ribbon-toggle" style={{ opacity: activeItem.presProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editProgressivize}>Edit</div> </div> <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}> <div className="presBox-subheading">Active text color</div> @@ -1885,12 +1851,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> {this.viewedColorPicker} <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}> - <div className="ribbon-toggle" style={{ backgroundColor: activeItem.zoomProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeZoom}>Zoom</div> - <div className="ribbon-toggle" style={{ opacity: activeItem.zoomProgressivize ? 1 : 0.4, backgroundColor: activeItem.editZoomProgressivize ? PresColor.LightBlue : "" }} onClick={this.editZoomProgressivize}>Edit</div> + <div className="ribbon-toggle" style={{ backgroundColor: activeItem.zoomProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeZoom}>Zoom</div> + <div className="ribbon-toggle" style={{ opacity: activeItem.zoomProgressivize ? 1 : 0.4, backgroundColor: activeItem.editZoomProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editZoomProgressivize}>Edit</div> </div> <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: targetDoc._viewType === "stacking" || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}> - <div className="ribbon-toggle" style={{ backgroundColor: activeItem.scrollProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeScroll}>Scroll</div> - <div className="ribbon-toggle" style={{ opacity: activeItem.scrollProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editScrollProgressivize ? PresColor.LightBlue : "" }} onClick={this.editScrollProgressivize}>Edit</div> + <div className="ribbon-toggle" style={{ backgroundColor: activeItem.scrollProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeScroll}>Scroll</div> + <div className="ribbon-toggle" style={{ opacity: activeItem.scrollProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editScrollProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editScrollProgressivize}>Edit</div> </div> </div> <div className="ribbon-final-box"> @@ -1900,7 +1866,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc, activeItem); }}> <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> </div> - <div key="num" title="toggle view all" className="numKeyframe" style={{ color: targetDoc.keyFrameEditing ? "white" : "black", backgroundColor: targetDoc.keyFrameEditing ? PresColor.DarkBlue : PresColor.LightBlue }} + <div key="num" title="toggle view all" className="numKeyframe" style={{ color: targetDoc.keyFrameEditing ? "white" : "black", backgroundColor: targetDoc.keyFrameEditing ? Colors.MEDIUM_BLUE : Colors.LIGHT_BLUE }} onClick={action(() => targetDoc.keyFrameEditing = !targetDoc.keyFrameEditing)} > {NumCast(targetDoc._currentFrame)} </div> @@ -1914,7 +1880,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> {this.frameListHeader} {this.frameList} </div> - <div className="ribbon-toggle" style={{ height: 20, backgroundColor: PresColor.LightBlue }} onClick={() => console.log(" TODO: play frames")}>Play</div> + <div className="ribbon-toggle" style={{ height: 20, backgroundColor: Colors.LIGHT_BLUE }} onClick={() => console.log(" TODO: play frames")}>Play</div> </div> </div> </div> @@ -2130,7 +2096,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> tags.push(<div style={{ position: 'absolute', display: doc.displayMovement ? "block" : "none" }}>{this.checkMovementLists(doc, doc["x-indexed"], doc["y-indexed"])}</div>); } tags.push( - <div className="progressivizeButton" key={index} onPointerLeave={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? PresColor.LightBlue : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}> + <div className="progressivizeButton" key={index} onPointerLeave={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? Colors.LIGHT_BLUE : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}> <div className="progressivizeButton-prev"><FontAwesomeIcon icon={"caret-left"} size={"lg"} onClick={e => { e.stopPropagation(); this.prevAppearFrame(doc, index); }} /></div> <div className="progressivizeButton-frame">{doc.appearFrame}</div> <div className="progressivizeButton-next"><FontAwesomeIcon icon={"caret-right"} size={"lg"} onClick={e => { e.stopPropagation(); this.nextAppearFrame(doc, index); }} /></div> @@ -2213,6 +2179,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; const isMini: boolean = this.toolbarWidth <= 100; const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation); + const activeColor = Colors.LIGHT_BLUE; + const inactiveColor = Colors.WHITE; return (mode === CollectionViewType.Carousel3D) ? (null) : ( <div id="toolbarContainer" className={'presBox-toolbar'}> {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}> @@ -2220,7 +2188,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> </div></Tooltip> */} <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}> - <div style={{ opacity: this.childDocs.length > 1 && this.layoutDoc.presCollection ? 1 : 0.3, color: this._pathBoolean ? PresColor.DarkBlue : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 && this.layoutDoc.presCollection ? this.viewPaths : undefined}> + <div style={{ opacity: this.childDocs.length > 1 && this.layoutDoc.presCollection ? 1 : 0.3, color: this._pathBoolean ? Colors.MEDIUM_BLUE : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 && this.layoutDoc.presCollection ? this.viewPaths : undefined}> <FontAwesomeIcon icon={"exchange-alt"} /> </div> </Tooltip> @@ -2229,7 +2197,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="toolbar-divider" /> {/* <Tooltip title={<><div className="dash-tooltip">{this._expandBoolean ? "Minimize all" : "Expand all"}</div></>}> <div className={"toolbar-button"} - style={{ color: this._expandBoolean ? PresColors.DarkBlue : 'white' }} + style={{ color: this._expandBoolean ? Colors.MEDIUM_BLUE : 'white' }} onClick={this.toggleExpandMode}> <FontAwesomeIcon icon={"eye"} /> </div> @@ -2237,12 +2205,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="toolbar-divider" /> */} <Tooltip title={<><div className="dash-tooltip">{presKeyEvents ? "Keys are active" : "Keys are not active - click anywhere on the presentation trail to activate keys"}</div></>}> <div className="toolbar-button" style={{ cursor: presKeyEvents ? 'default' : 'pointer', position: 'absolute', right: 30, fontSize: 16 }}> - <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"keyboard"} style={{ color: presKeyEvents ? PresColor.DarkBlue : 'white' }} /> + <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"keyboard"} style={{ color: presKeyEvents ? activeColor : inactiveColor }} /> </div> </Tooltip> <Tooltip title={<><div className="dash-tooltip">{propTitle}</div></>}> <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}> - <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? PresColor.DarkBlue : 'white' }} /> + <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? activeColor : inactiveColor }} /> </div> </Tooltip> </> @@ -2379,7 +2347,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0); // Case 1: There are still other frames and should go through all frames before going to next slide return (<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}> - <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? PresColor.DarkBlue : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> <div className="presPanel-divider"></div> <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div> <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? "pause" : "play"} /></div></Tooltip> @@ -2418,8 +2386,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0); return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ? <div className="miniPres"> - <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + PresColor.DarkBlue : undefined }}> - <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? PresColor.DarkBlue : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> + <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + Colors.MEDIUM_BLUE : undefined }}> + <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip> <div className="presPanel-divider"></div> <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div> <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip> diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 1ad4b820e..1ad4b820e 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index f15d51764..5e713c3cf 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -2,27 +2,29 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; -import { DataSym, Doc, Opt } from "../../../fields/Doc"; -import { documentSchema } from '../../../fields/documentSchemas'; -import { Id } from "../../../fields/FieldSymbols"; -import { createSchema, makeInterface } from '../../../fields/Schema'; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, emptyPath, returnEmptyDoclist } from "../../../Utils"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { DocumentManager } from "../../util/DocumentManager"; -import { DragManager } from "../../util/DragManager"; -import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; -import { ViewBoxBaseComponent } from '../DocComponent'; -import { EditableView } from "../EditableView"; -import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; -import { FieldView, FieldViewProps } from '../nodes/FieldView'; -import { PresBox, PresColor, PresMovement } from "../nodes/PresBox"; -import { StyleProp } from "../StyleProvider"; +import { DataSym, Doc, Opt } from "../../../../fields/Doc"; +import { documentSchema } from '../../../../fields/documentSchemas'; +import { Id } from "../../../../fields/FieldSymbols"; +import { createSchema, makeInterface } from '../../../../fields/Schema'; +import { Cast, NumCast, StrCast } from "../../../../fields/Types"; +import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, emptyPath, returnEmptyDoclist } from "../../../../Utils"; +import { DocumentType } from "../../../documents/DocumentTypes"; +import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; +import { DocumentManager } from "../../../util/DocumentManager"; +import { DragManager } from "../../../util/DragManager"; +import { Transform } from "../../../util/Transform"; +import { undoBatch } from "../../../util/UndoManager"; +import { ViewBoxBaseComponent } from '../../DocComponent'; +import { EditableView } from "../../EditableView"; +import { DocumentView, DocumentViewProps } from "../../nodes/DocumentView"; +import { FieldView, FieldViewProps } from '../../nodes/FieldView'; +import { PresBox } from "./PresBox"; +import { Colors } from "../../global/globalEnums"; +import { StyleProp } from "../../StyleProvider"; import "./PresElementBox.scss"; import React = require("react"); -import { DocUtils } from "../../documents/Documents"; +import { DocUtils } from "../../../documents/Documents"; +import { PresMovement } from "./PresEnums"; export const presSchema = createSchema({ presentationTargetDoc: Doc, @@ -210,11 +212,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc const height = slide.clientHeight; const halfLine = height / 2; if (y <= halfLine) { - slide.style.borderTop = "solid 2px #5B9FDD"; + slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`; slide.style.borderBottom = "0px"; } else if (y > halfLine) { slide.style.borderTop = "0px"; - slide.style.borderBottom = "solid 2px #5B9FDD"; + slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`; } } document.removeEventListener("pointermove", this.onPointerMove); @@ -292,7 +294,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc const miniView: boolean = this.toolbarWidth <= 110; const presBox: Doc = this.presBox; //presBox const presBoxColor: string = StrCast(presBox._backgroundColor); - const presColorBool: boolean = presBoxColor ? (presBoxColor !== "white" && presBoxColor !== "transparent") : false; + const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false; const targetDoc: Doc = this.targetDoc; const activeItem: Doc = this.rootDoc; return ( @@ -300,7 +302,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc key={this.props.Document[Id] + this.indexInPres} ref={this._itemRef} style={{ - backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? "#AEDDF8" : "transparent", + backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent", opacity: this._dragging ? 0.3 : 1 }} onClick={e => { @@ -356,7 +358,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc style={{ zIndex: 1000 - this.indexInPres, fontWeight: 700, - backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : PresColor.DarkBlue : undefined, + backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined, height: activeItem.groupWithUp ? 53 : 18, transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined }}> diff --git a/src/client/views/nodes/trails/PresEnums.ts b/src/client/views/nodes/trails/PresEnums.ts new file mode 100644 index 000000000..93ab323fb --- /dev/null +++ b/src/client/views/nodes/trails/PresEnums.ts @@ -0,0 +1,28 @@ +export enum PresMovement { + Zoom = "zoom", + Pan = "pan", + Jump = "jump", + None = "none", +} + +export enum PresEffect { + Zoom = "Zoom", + Lightspeed = "Lightspeed", + Fade = "Fade in", + Flip = "Flip", + Rotate = "Rotate", + Bounce = "Bounce", + Roll = "Roll", + None = "None", + Left = "left", + Right = "right", + Center = "center", + Top = "top", + Bottom = "bottom" +} + +export enum PresStatus { + Autoplay = "auto", + Manual = "manual", + Edit = "edit" +}
\ No newline at end of file diff --git a/src/client/views/nodes/trails/index.ts b/src/client/views/nodes/trails/index.ts new file mode 100644 index 000000000..8f3f7b03a --- /dev/null +++ b/src/client/views/nodes/trails/index.ts @@ -0,0 +1,3 @@ +export * from "./PresBox"; +export * from "./PresElementBox"; +export * from "./PresEnums";
\ No newline at end of file diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss new file mode 100644 index 000000000..e2d27d5a6 --- /dev/null +++ b/src/client/views/topbar/TopBar.scss @@ -0,0 +1,205 @@ +@import "../global/globalCssVariables"; + +.topbar-container { + display: flex; + flex-direction: column; + width: 100%; + position: relative; + font-size: 10px; + line-height: 1; + overflow-y: auto; + overflow-x: visible; + background: $dark-gray; + overflow: visible; + z-index: 1000; + + .topbar-bar { + height: $topbar-height; + display: grid; + grid-auto-columns: 33.3% 33.3% 33.3%; + align-items: center; + background-color: $dark-gray; + + .topbar-center { + grid-column: 2; + display: inline-flex; + justify-content: center; + align-items: center; + + .topbar-lozenge-dashboard { + display: flex; + + .topbar-dashboards { + display: inline-flex; + } + + .topbar-dashSelect { + border: none; + background-color: transparent; + color: black; + font-family: 'Roboto'; + font-size: 17; + font-weight: 500; + + &:hover { + cursor: pointer; + } + } + } + } + + .topBar-icon { + color: black; + cursor: pointer; + font-size: 15px; + height: 30; + width: 30; + display: flex; + justify-content: center; + align-items: center; + margin-right: 5px; + justify-self: center; + align-self: center; + border-radius: 100%; + transition: linear 0.1s; + background-color: #92adb900; + } + + .topBar-icon:hover { + background-color: rgba(0, 0, 0, 0.15); + } + + .topbar-right { + grid-column: 3; + position: relative; + display: flex; + justify-content: flex-end; + + .topbar-lozenge-user, + .topbar-lozenge { + height: 23; + font-size: 12; + color: white; + font-family: 'Roboto'; + font-weight: 400; + padding: 4px; + align-self: center; + margin-right: 7px; + display: flex; + align-items: center; + border: white 1px solid; + + .topbar-logoff { + border-radius: 3px; + background: olivedrab; + color: white; + display: none; + margin-left: 5px; + padding: 1px 2px 1px 2px; + cursor: pointer; + } + + .topbar-logoff { + background: red; + } + + .topbar-dashSelect { + border: none; + background-color: transparent; + color: black; + font-family: 'Roboto'; + font-size: 17; + font-weight: 500; + + &:hover { + cursor: pointer; + } + } + } + + .topbar-lozenge-user:hover { + .topbar-logoff { + display: inline-block; + } + } + + } + + .topbar-left { + grid-column: 1; + color: black; + font-family: 'Roboto'; + position: relative; + display: flex; + width: 450; + } + + .topbar-barChild { + + &.topbar-collection { + flex: 0 1 auto; + margin-left: 2px; + margin-right: 2px + } + + &.topbar-input { + margin:5px; + border-radius:20px; + border:$dark-gray; + display: block; + width: 130px; + -webkit-transition: width 0.4s; + transition: width 0.4s; + /* align-self: stretch; */ + outline: none; + + &:focus { + width: 500px; + outline: none; + } + } + + &.topbar-filter { + align-self: stretch; + + button { + transform: none; + + &:hover { + transform: none; + } + } + } + + &.topbar-submit { + margin-left: 2px; + margin-right: 2px + } + + &.topbar-close { + color: $white; + max-height: $topbar-height; + } + } + } +} + +.topbar-results { + display: flex; + flex-direction: column; + top: 300px; + display: flex; + flex-direction: column; + height: 100%; + overflow: visible; + + .no-result { + width: 500px; + background: $light-gray; + padding: 10px; + height: 50px; + text-transform: uppercase; + text-align: left; + font-weight: bold; + } +}
\ No newline at end of file diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx new file mode 100644 index 000000000..65da717f8 --- /dev/null +++ b/src/client/views/topbar/TopBar.tsx @@ -0,0 +1,67 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { observer } from "mobx-react"; +import * as React from 'react'; +import { Doc, DocListCast } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { StrCast } from '../../../fields/Types'; +import { Utils } from '../../../Utils'; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { SettingsManager } from "../../util/SettingsManager"; +import { undoBatch } from "../../util/UndoManager"; +import { Borders, Colors } from "../global/globalEnums"; +import "./TopBar.scss"; + +/** + * REACT TYPE: FUNCTIONAL + * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user + * and settings and help buttons. Future scope for this bar is to include the collaborators that are on the same Dashboard. + */ +@observer +export class TopBar extends React.Component { + render() { + const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data); + return ( + //TODO:glr Add support for light / dark mode + <div style={{ pointerEvents: "all" }} className="topbar-container"> + <div className="topbar-bar" style={{ background: Colors.DARK_GRAY, borderBottom: Borders.STANDARD }}> + <div className="topbar-center" > + <div className="topbar-lozenge-dashboard"> + <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])} + value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)} + style={{ color: Colors.WHITE }}> + {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)} + </select> + <div className="topbar-dashboards"> + <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))} + style={{ color: Colors.WHITE }}> + <FontAwesomeIcon icon="plus"></FontAwesomeIcon> + </div> + <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))} + style={{ color: Colors.WHITE }}> + <FontAwesomeIcon icon="camera"></FontAwesomeIcon> + </div> + </div> + </div> + </div> + <div className="topbar-right" > + <div className="topbar-icon" + style={{ color: Colors.WHITE }}> + <FontAwesomeIcon icon="question-circle"></FontAwesomeIcon> + </div> + <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()} + style={{ color: Colors.WHITE }}> + <FontAwesomeIcon icon="cog"></FontAwesomeIcon> + </div> + <div className="topbar-lozenge-user"> + {`${Doc.CurrentUserEmail}`} + <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}> + Logoff + </div> + </div> + </div> + + </div > + </div > + ); + } +}
\ No newline at end of file diff --git a/src/client/views/topbar/TopBarButton.tsx b/src/client/views/topbar/TopBarButton.tsx new file mode 100644 index 000000000..0d3d2a8d1 --- /dev/null +++ b/src/client/views/topbar/TopBarButton.tsx @@ -0,0 +1,10 @@ +import React from "react"; + +export interface IButtonProps { + icon?: JSX.Element; + text?: String; +} + +export class TopBarButton implements IButtonProps { + +} diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 111fd3f0d..976bd5ee1 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -23,6 +23,7 @@ import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { AudioField, ImageField, PdfField, VideoField, WebField } from "./URLField"; import { deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions, updateFunction } from "./util"; import JSZip = require("jszip"); +import { IconProp } from "@fortawesome/fontawesome-svg-core"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -1193,7 +1194,10 @@ export namespace Doc { case DocumentType.IMG: return "image"; case DocumentType.COMPARISON: return "columns"; case DocumentType.RTF: return "sticky-note"; - case DocumentType.COL: return !doc?.isFolder ? "folder" + (isOpen ? "-open" : "") : "chevron-" + (isOpen ? "down" : "right"); + case DocumentType.COL: + const folder: IconProp = isOpen ? "folder-open" : "folder"; + const chevron: IconProp = isOpen ? "chevron-down" : "chevron-right" + return !doc?.isFolder ? folder : chevron; case DocumentType.WEB: return "globe-asia"; case DocumentType.SCREENSHOT: return "photo-video"; case DocumentType.WEBCAM: return "video"; diff --git a/tslint.json b/tslint.json index 0056f4266..83255a798 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,9 @@ { "linterOptions": { - "exclude": ["./src/client/northstar/**", "**/*.js"] + "exclude": [ + "./src/client/northstar/**", + "**/*.js" + ] }, "rules": { "no-return-await": true, @@ -23,41 +26,7 @@ ], "no-tautology-expression": true, "unnecessary-constructor": true - // "trailing-comma": [ - // true, - // { - // "multiline": "always", - // "singleline": "never" - // } - // ], - // "ordered-imports": true - // "quotemark": [ - // true, - // "double", - // "jsx-double", - // "avoid-template", - // "avoid-escape" - // ], - // "object-literal-shorthand": true, - // "object-literal-sort-keys": true, - // "align": [ - // true, - // "parameters", - // "arguments", - // "statements", - // "members", - // "elements" - // ], - // "no-void-expression": [ - // true, - // "ignore-arrow-function-shorthand" - // ], - // "no-non-null-assertion": true, - // "no-var-keyword": true, - // "no-var-requires": true, }, "defaultSeverity": "warning", - "jsRules": { - - } + "jsRules": {} }
\ No newline at end of file |