aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/goldenLayout.js3090
-rw-r--r--src/client/util/CurrentUserUtils.ts45
-rw-r--r--src/client/util/SettingsManager.tsx79
-rw-r--r--src/client/views/AntimodeMenu.scss4
-rw-r--r--src/client/views/DocumentButtonBar.scss15
-rw-r--r--src/client/views/DocumentButtonBar.tsx9
-rw-r--r--src/client/views/DocumentDecorations.scss4
-rw-r--r--src/client/views/MainView.scss57
-rw-r--r--src/client/views/MainView.tsx76
-rw-r--r--src/client/views/PropertiesView.tsx2
-rw-r--r--src/client/views/_nodeModuleOverrides.scss51
-rw-r--r--src/client/views/collections/CollectionDockingView.scss100
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionLinearView.scss23
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx10
-rw-r--r--src/client/views/collections/CollectionMenu.scss4
-rw-r--r--src/client/views/collections/CollectionMenu.tsx2
-rw-r--r--src/client/views/collections/TabDocView.scss59
-rw-r--r--src/client/views/collections/TabDocView.tsx114
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx3
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx1
-rw-r--r--src/client/views/global/globalCssVariables.scss9
-rw-r--r--src/client/views/global/globalEnums.tsx4
-rw-r--r--src/client/views/linking/LinkEditor.scss8
-rw-r--r--src/client/views/linking/LinkMenu.scss26
-rw-r--r--src/client/views/linking/LinkMenu.tsx8
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx2
-rw-r--r--src/client/views/linking/LinkMenuItem.scss8
-rw-r--r--src/client/views/linking/LinkPopup.scss45
-rw-r--r--src/client/views/linking/LinkPopup.tsx114
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
-rw-r--r--src/client/views/nodes/DocumentLinksButton.scss25
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx94
-rw-r--r--src/client/views/nodes/DocumentView.scss2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/FontIconBox.tsx3
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx1
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx11
-rw-r--r--src/client/views/nodes/trails/PresBox.scss (renamed from src/client/views/nodes/PresBox.scss)6
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx (renamed from src/client/views/nodes/PresBox.tsx)184
-rw-r--r--src/client/views/nodes/trails/PresElementBox.scss (renamed from src/client/views/presentationview/PresElementBox.scss)0
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx (renamed from src/client/views/presentationview/PresElementBox.tsx)50
-rw-r--r--src/client/views/nodes/trails/PresEnums.ts28
-rw-r--r--src/client/views/nodes/trails/index.ts3
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx18
-rw-r--r--src/client/views/topbar/TopBar.scss213
-rw-r--r--src/client/views/topbar/TopBar.tsx67
-rw-r--r--src/fields/Doc.ts6
50 files changed, 2701 insertions, 1996 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f8ccbb102..4e45f6b7c 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/goldenLayout.js b/src/client/goldenLayout.js
index 9cfea7f3f..238f1ac0a 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -82,16 +82,16 @@
return target;
};
- /**
- * This is based on Paul Irish's shim, but looks quite odd in comparison. Why?
- * Because
- * a) it shouldn't affect the global requestAnimationFrame function
- * b) it shouldn't pass on the time that has passed
- *
- * @param {Function} fn
- *
- * @returns {void}
- */
+ /**
+ * This is based on Paul Irish's shim, but looks quite odd in comparison. Why?
+ * Because
+ * a) it shouldn't affect the global requestAnimationFrame function
+ * b) it shouldn't pass on the time that has passed
+ *
+ * @param {Function} fn
+ *
+ * @returns {void}
+ */
lm.utils.animFrame = function (fn) {
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
@@ -178,16 +178,16 @@
.replace('.', '');
};
- /**
- * A basic XSS filter. It is ultimately up to the
- * implementing developer to make sure their particular
- * applications and usecases are save from cross site scripting attacks
- *
- * @param {String} input
- * @param {Boolean} keepTags
- *
- * @returns {String} filtered input
- */
+ /**
+ * A basic XSS filter. It is ultimately up to the
+ * implementing developer to make sure their particular
+ * applications and usecases are save from cross site scripting attacks
+ *
+ * @param {String} input
+ * @param {Boolean} keepTags
+ *
+ * @returns {String} filtered input
+ */
lm.utils.filterXss = function (input, keepTags) {
var output = input
@@ -206,41 +206,41 @@
}
};
- /**
- * Removes html tags from a string
- *
- * @param {String} input
- *
- * @returns {String} input without tags
- */
+ /**
+ * Removes html tags from a string
+ *
+ * @param {String} input
+ *
+ * @returns {String} input without tags
+ */
lm.utils.stripTags = function (input) {
return $.trim(input.replace(/(<([^>]+)>)/ig, ''));
};
- /**
- * A generic and very fast EventEmitter
- * implementation. On top of emitting the
- * actual event it emits an
- *
- * lm.utils.EventEmitter.ALL_EVENT
- *
- * event for every event triggered. This allows
- * to hook into it and proxy events forwards
- *
- * @constructor
- */
+ /**
+ * A generic and very fast EventEmitter
+ * implementation. On top of emitting the
+ * actual event it emits an
+ *
+ * lm.utils.EventEmitter.ALL_EVENT
+ *
+ * event for every event triggered. This allows
+ * to hook into it and proxy events forwards
+ *
+ * @constructor
+ */
lm.utils.EventEmitter = function () {
this._mSubscriptions = {};
this._mSubscriptions[lm.utils.EventEmitter.ALL_EVENT] = [];
- /**
- * Listen for events
- *
- * @param {String} sEvent The name of the event to listen to
- * @param {Function} fCallback The callback to execute when the event occurs
- * @param {[Object]} oContext The value of the this pointer within the callback function
- *
- * @returns {void}
- */
+ /**
+ * Listen for events
+ *
+ * @param {String} sEvent The name of the event to listen to
+ * @param {Function} fCallback The callback to execute when the event occurs
+ * @param {[Object]} oContext The value of the this pointer within the callback function
+ *
+ * @returns {void}
+ */
this.on = function (sEvent, fCallback, oContext) {
if (!lm.utils.isFunction(fCallback)) {
throw new Error('Tried to listen to event ' + sEvent + ' with non-function callback ' + fCallback);
@@ -253,14 +253,14 @@
this._mSubscriptions[sEvent].push({ fn: fCallback, ctx: oContext });
};
- /**
- * Emit an event and notify listeners
- *
- * @param {String} sEvent The name of the event
- * @param {Mixed} various additional arguments that will be passed to the listener
- *
- * @returns {void}
- */
+ /**
+ * Emit an event and notify listeners
+ *
+ * @param {String} sEvent The name of the event
+ * @param {Mixed} various additional arguments that will be passed to the listener
+ *
+ * @returns {void}
+ */
this.emit = function (sEvent) {
var i, ctx, args;
@@ -286,15 +286,15 @@
}
};
- /**
- * Removes a listener for an event, or all listeners if no callback and context is provided.
- *
- * @param {String} sEvent The name of the event
- * @param {Function} fCallback The previously registered callback method (optional)
- * @param {Object} oContext The previously registered context (optional)
- *
- * @returns {void}
- */
+ /**
+ * Removes a listener for an event, or all listeners if no callback and context is provided.
+ *
+ * @param {String} sEvent The name of the event
+ * @param {Function} fCallback The previously registered callback method (optional)
+ * @param {Object} oContext The previously registered context (optional)
+ *
+ * @returns {void}
+ */
this.unbind = function (sEvent, fCallback, oContext) {
if (!this._mSubscriptions[sEvent]) {
throw new Error('No subscribtions to unsubscribe for event ' + sEvent);
@@ -318,28 +318,28 @@
}
};
- /**
- * Alias for unbind
- */
+ /**
+ * Alias for unbind
+ */
this.off = this.unbind;
- /**
- * Alias for emit
- */
+ /**
+ * Alias for emit
+ */
this.trigger = this.emit;
};
- /**
- * The name of the event that's triggered for every other event
- *
- * usage
- *
- * myEmitter.on( lm.utils.EventEmitter.ALL_EVENT, function( eventName, argsArray ){
- * //do stuff
- * });
- *
- * @type {String}
- */
+ /**
+ * The name of the event that's triggered for every other event
+ *
+ * usage
+ *
+ * myEmitter.on( lm.utils.EventEmitter.ALL_EVENT, function( eventName, argsArray ){
+ * //do stuff
+ * });
+ *
+ * @type {String}
+ */
lm.utils.EventEmitter.ALL_EVENT = '__all';
lm.utils.DragListener = function (eElement, nButtonCode) {
lm.utils.EventEmitter.call(this);
@@ -349,14 +349,14 @@
this._eBody = $(document.body);
this._nButtonCode = nButtonCode || 0;
- /**
- * The delay after which to start the drag in milliseconds
- */
+ /**
+ * The delay after which to start the drag in milliseconds
+ */
this._nDelay = 200;
- /**
- * The distance the mouse needs to be moved to qualify as a drag
- */
+ /**
+ * The distance the mouse needs to be moved to qualify as a drag
+ */
this._nDistance = 10;//TODO - works better with delay only
this._nX = 0;
@@ -459,16 +459,16 @@
};
}
});
- /**
- * The main class that will be exposed as GoldenLayout.
- *
- * @public
- * @constructor
- * @param {GoldenLayout config} config
- * @param {[DOM element container]} container Can be a jQuery selector string or a Dom element. Defaults to body
- *
- * @returns {VOID}
- */
+ /**
+ * The main class that will be exposed as GoldenLayout.
+ *
+ * @public
+ * @constructor
+ * @param {GoldenLayout config} config
+ * @param {[DOM element container]} container Can be a jQuery selector string or a Dom element. Defaults to body
+ *
+ * @returns {VOID}
+ */
lm.LayoutManager = function (config, container) {
if (!$ || typeof $.noConflict !== 'function') {
@@ -521,59 +521,59 @@
};
};
- /**
- * Hook that allows to access private classes
- */
+ /**
+ * Hook that allows to access private classes
+ */
lm.LayoutManager.__lm = lm;
- /**
- * Takes a GoldenLayout configuration object and
- * replaces its keys and values recursively with
- * one letter codes
- *
- * @static
- * @public
- * @param {Object} config A GoldenLayout config object
- *
- * @returns {Object} minified config
- */
+ /**
+ * Takes a GoldenLayout configuration object and
+ * replaces its keys and values recursively with
+ * one letter codes
+ *
+ * @static
+ * @public
+ * @param {Object} config A GoldenLayout config object
+ *
+ * @returns {Object} minified config
+ */
lm.LayoutManager.minifyConfig = function (config) {
return (new lm.utils.ConfigMinifier()).minifyConfig(config);
};
- /**
- * Takes a configuration Object that was previously minified
- * using minifyConfig and returns its original version
- *
- * @static
- * @public
- * @param {Object} minifiedConfig
- *
- * @returns {Object} the original configuration
- */
+ /**
+ * Takes a configuration Object that was previously minified
+ * using minifyConfig and returns its original version
+ *
+ * @static
+ * @public
+ * @param {Object} minifiedConfig
+ *
+ * @returns {Object} the original configuration
+ */
lm.LayoutManager.unminifyConfig = function (config) {
return (new lm.utils.ConfigMinifier()).unminifyConfig(config);
};
lm.utils.copy(lm.LayoutManager.prototype, {
- /**
- * Register a component with the layout manager. If a configuration node
- * of type component is reached it will look up componentName and create the
- * associated component
- *
- * {
- * type: "component",
- * componentName: "EquityNewsFeed",
- * componentState: { "feedTopic": "us-bluechips" }
- * }
- *
- * @public
- * @param {String} name
- * @param {Function} constructor
- *
- * @returns {void}
- */
+ /**
+ * Register a component with the layout manager. If a configuration node
+ * of type component is reached it will look up componentName and create the
+ * associated component
+ *
+ * {
+ * type: "component",
+ * componentName: "EquityNewsFeed",
+ * componentState: { "feedTopic": "us-bluechips" }
+ * }
+ *
+ * @public
+ * @param {String} name
+ * @param {Function} constructor
+ *
+ * @returns {void}
+ */
registerComponent: function (name, constructor) {
if (typeof constructor !== 'function') {
throw new Error('Please register a constructor function');
@@ -586,12 +586,12 @@
this._components[name] = constructor;
},
- /**
- * Creates a layout configuration object based on the the current state
- *
- * @public
- * @returns {Object} GoldenLayout configuration
- */
+ /**
+ * Creates a layout configuration object based on the the current state
+ *
+ * @public
+ * @returns {Object} GoldenLayout configuration
+ */
toConfig: function (root) {
var config, next, i;
@@ -603,18 +603,18 @@
throw new Error('Root must be a ContentItem');
}
- /*
- * settings & labels
- */
+ /*
+ * settings & labels
+ */
config = {
settings: lm.utils.copy({}, this.config.settings),
dimensions: lm.utils.copy({}, this.config.dimensions),
labels: lm.utils.copy({}, this.config.labels)
};
- /*
- * Content
- */
+ /*
+ * Content
+ */
config.content = [];
next = function (configNode, item) {
var key, i;
@@ -641,30 +641,30 @@
next(config, this.root);
}
- /*
- * Retrieve config for subwindows
- */
+ /*
+ * Retrieve config for subwindows
+ */
this._$reconcilePopoutWindows();
config.openPopouts = [];
for (i = 0; i < this.openPopouts.length; i++) {
config.openPopouts.push(this.openPopouts[i].toConfig());
}
- /*
- * Add maximised item
- */
+ /*
+ * Add maximised item
+ */
config.maximisedItemId = this._maximisedItem ? '__glMaximised' : null;
return config;
},
- /**
- * Returns a previously registered component
- *
- * @public
- * @param {String} name The name used
- *
- * @returns {Function}
- */
+ /**
+ * Returns a previously registered component
+ *
+ * @public
+ * @param {String} name The name used
+ *
+ * @returns {Function}
+ */
getComponent: function (name) {
if (this._components[name] === undefined) {
throw new lm.errors.ConfigurationError('Unknown component "' + name + '"');
@@ -673,44 +673,44 @@
return this._components[name];
},
- /**
- * Creates the actual layout. Must be called after all initial components
- * are registered. Recurses through the configuration and sets up
- * the item tree.
- *
- * If called before the document is ready it adds itself as a listener
- * to the document.ready event
- *
- * @public
- *
- * @returns {void}
- */
+ /**
+ * Creates the actual layout. Must be called after all initial components
+ * are registered. Recurses through the configuration and sets up
+ * the item tree.
+ *
+ * If called before the document is ready it adds itself as a listener
+ * to the document.ready event
+ *
+ * @public
+ *
+ * @returns {void}
+ */
init: function () {
- /**
- * Create the popout windows straight away. If popouts are blocked
- * an error is thrown on the same 'thread' rather than a timeout and can
- * be caught. This also prevents any further initilisation from taking place.
- */
+ /**
+ * Create the popout windows straight away. If popouts are blocked
+ * an error is thrown on the same 'thread' rather than a timeout and can
+ * be caught. This also prevents any further initilisation from taking place.
+ */
if (this._subWindowsCreated === false) {
this._createSubWindows();
this._subWindowsCreated = true;
}
- /**
- * If the document isn't ready yet, wait for it.
- */
+ /**
+ * If the document isn't ready yet, wait for it.
+ */
if (document.readyState === 'loading' || document.body === null) {
$(document).ready(lm.utils.fnBind(this.init, this));
return;
}
- /**
- * If this is a subwindow, wait a few milliseconds for the original
- * page's js calls to be executed, then replace the bodies content
- * with GoldenLayout
- */
+ /**
+ * If this is a subwindow, wait a few milliseconds for the original
+ * page's js calls to be executed, then replace the bodies content
+ * with GoldenLayout
+ */
if (this.isSubWindow === true && this._creationTimeoutPassed === false) {
setTimeout(lm.utils.fnBind(this.init, this), 7);
this._creationTimeoutPassed = true;
@@ -732,15 +732,15 @@
this.emit('initialised');
},
- /**
- * Updates the layout managers size
- *
- * @public
- * @param {[int]} width height in pixels
- * @param {[int]} height width in pixels
- *
- * @returns {void}
- */
+ /**
+ * Updates the layout managers size
+ *
+ * @public
+ * @param {[int]} width height in pixels
+ * @param {[int]} height width in pixels
+ *
+ * @returns {void}
+ */
updateSize: function (width, height) {
if (arguments.length === 2) {
this.width = width;
@@ -763,13 +763,13 @@
}
},
- /**
- * Destroys the LayoutManager instance itself as well as every ContentItem
- * within it. After this is called nothing should be left of the LayoutManager.
- *
- * @public
- * @returns {void}
- */
+ /**
+ * Destroys the LayoutManager instance itself as well as every ContentItem
+ * within it. After this is called nothing should be left of the LayoutManager.
+ *
+ * @public
+ * @returns {void}
+ */
destroy: function () {
if (this.isInitialised === false) {
return;
@@ -793,16 +793,16 @@
this._dragSources = [];
},
- /**
- * Recursively creates new item tree structures based on a provided
- * ItemConfiguration object
- *
- * @public
- * @param {Object} config ItemConfig
- * @param {[ContentItem]} parent The item the newly created item should be a child of
- *
- * @returns {lm.items.ContentItem}
- */
+ /**
+ * Recursively creates new item tree structures based on a provided
+ * ItemConfiguration object
+ *
+ * @public
+ * @param {Object} config ItemConfig
+ * @param {[ContentItem]} parent The item the newly created item should be a child of
+ *
+ * @returns {lm.items.ContentItem}
+ */
createContentItem: function (config, parent) {
var typeErrorMsg, contentItem;
@@ -823,9 +823,9 @@
}
- /**
- * We add an additional stack around every component that's not within a stack anyways.
- */
+ /**
+ * We add an additional stack around every component that's not within a stack anyways.
+ */
if (
// If this is a component
config.type === 'component' &&
@@ -851,17 +851,17 @@
return contentItem;
},
- /**
- * Creates a popout window with the specified content and dimensions
- *
- * @param {Object|lm.itemsAbstractContentItem} configOrContentItem
- * @param {[Object]} dimensions A map with width, height, left and top
- * @param {[String]} parentId the id of the element this item will be appended to
- * when popIn is called
- * @param {[Number]} indexInParent The position of this item within its parent element
+ /**
+ * Creates a popout window with the specified content and dimensions
+ *
+ * @param {Object|lm.itemsAbstractContentItem} configOrContentItem
+ * @param {[Object]} dimensions A map with width, height, left and top
+ * @param {[String]} parentId the id of the element this item will be appended to
+ * when popIn is called
+ * @param {[Number]} indexInParent The position of this item within its parent element
- * @returns {lm.controls.BrowserPopout}
- */
+ * @returns {lm.controls.BrowserPopout}
+ */
createPopout: function (configOrContentItem, dimensions, parentId, indexInParent) {
var config = configOrContentItem,
isItem = configOrContentItem instanceof lm.items.AbstractContentItem,
@@ -879,14 +879,14 @@
config = this.toConfig(configOrContentItem).content;
parentId = lm.utils.getUniqueId();
- /**
- * If the item is the only component within a stack or for some
- * other reason the only child of its parent the parent will be destroyed
- * when the child is removed.
- *
- * In order to support this we move up the tree until we find something
- * that will remain after the item is being popped out
- */
+ /**
+ * If the item is the only component within a stack or for some
+ * other reason the only child of its parent the parent will be destroyed
+ * when the child is removed.
+ *
+ * In order to support this we move up the tree until we find something
+ * that will remain after the item is being popped out
+ */
parent = configOrContentItem.parent;
child = configOrContentItem;
while (parent.contentItems.length === 1 && !parent.isRoot) {
@@ -946,16 +946,16 @@
return browserPopout;
},
- /**
- * Attaches DragListener to any given DOM element
- * and turns it into a way of creating new ContentItems
- * by 'dragging' the DOM element into the layout
- *
- * @param {jQuery DOM element} element
- * @param {Object|Function} itemConfig for the new item to be created, or a function which will provide it
- *
- * @returns {void}
- */
+ /**
+ * Attaches DragListener to any given DOM element
+ * and turns it into a way of creating new ContentItems
+ * by 'dragging' the DOM element into the layout
+ *
+ * @param {jQuery DOM element} element
+ * @param {Object|Function} itemConfig for the new item to be created, or a function which will provide it
+ *
+ * @returns {void}
+ */
createDragSource: function (element, itemConfig) {
this.config.settings.constrainDragToContainer = false;
var dragSource = new lm.controls.DragSource($(element), itemConfig, this);
@@ -964,17 +964,17 @@
return dragSource;
},
- /**
- * Programmatically selects an item. This deselects
- * the currently selected item, selects the specified item
- * and emits a selectionChanged event
- *
- * @param {lm.item.AbstractContentItem} item#
- * @param {[Boolean]} _$silent Wheather to notify the item of its selection
- * @event selectionChanged
- *
- * @returns {VOID}
- */
+ /**
+ * Programmatically selects an item. This deselects
+ * the currently selected item, selects the specified item
+ * and emits a selectionChanged event
+ *
+ * @param {lm.item.AbstractContentItem} item#
+ * @param {[Boolean]} _$silent Wheather to notify the item of its selection
+ * @event selectionChanged
+ *
+ * @returns {VOID}
+ */
selectItem: function (item, _$silent) {
if (this.config.settings.selectionEnabled !== true) {
@@ -998,9 +998,9 @@
this.emit('selectionChanged', item);
},
- /*************************
- * PACKAGE PRIVATE
- *************************/
+ /*************************
+ * PACKAGE PRIVATE
+ *************************/
_$maximiseItem: function (contentItem) {
if (this._maximisedItem !== null) {
this._$minimiseItem(this._maximisedItem);
@@ -1028,20 +1028,20 @@
this.emit('stateChanged');
},
- /**
- * This method is used to get around sandboxed iframe restrictions.
- * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute
- * (as is the case with codepens) the parent window is forbidden from calling certain
- * methods on the child, such as window.close() or setting document.location.href.
- *
- * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call
- * _$closeWindow on the child window's gl instance which (after a timeout to disconnect
- * the invoking method from the close call) closes itself.
- *
- * @packagePrivate
- *
- * @returns {void}
- */
+ /**
+ * This method is used to get around sandboxed iframe restrictions.
+ * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute
+ * (as is the case with codepens) the parent window is forbidden from calling certain
+ * methods on the child, such as window.close() or setting document.location.href.
+ *
+ * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call
+ * _$closeWindow on the child window's gl instance which (after a timeout to disconnect
+ * the invoking method from the close call) closes itself.
+ *
+ * @packagePrivate
+ *
+ * @returns {void}
+ */
_$closeWindow: function () {
window.setTimeout(function () {
window.close();
@@ -1088,13 +1088,13 @@
var i, area, allContentItems = this._getAllContentItems();
this._itemAreas = [];
- /**
- * If the last item is dragged out, highlight the entire container size to
- * allow to re-drop it. allContentItems[ 0 ] === this.root at this point
- *
- * Don't include root into the possible drop areas though otherwise since it
- * will used for every gap in the layout, e.g. splitters
- */
+ /**
+ * If the last item is dragged out, highlight the entire container size to
+ * allow to re-drop it. allContentItems[ 0 ] === this.root at this point
+ *
+ * Don't include root into the possible drop areas though otherwise since it
+ * will used for every gap in the layout, e.g. splitters
+ */
if (allContentItems.length === 1) {
this._itemAreas.push(this.root._$getArea());
return;
@@ -1124,18 +1124,18 @@
}
},
- /**
- * Takes a contentItem or a configuration and optionally a parent
- * item and returns an initialised instance of the contentItem.
- * If the contentItem is a function, it is first called
- *
- * @packagePrivate
- *
- * @param {lm.items.AbtractContentItem|Object|Function} contentItemOrConfig
- * @param {lm.items.AbtractContentItem} parent Only necessary when passing in config
- *
- * @returns {lm.items.AbtractContentItem}
- */
+ /**
+ * Takes a contentItem or a configuration and optionally a parent
+ * item and returns an initialised instance of the contentItem.
+ * If the contentItem is a function, it is first called
+ *
+ * @packagePrivate
+ *
+ * @param {lm.items.AbtractContentItem|Object|Function} contentItemOrConfig
+ * @param {lm.items.AbtractContentItem} parent Only necessary when passing in config
+ *
+ * @returns {lm.items.AbtractContentItem}
+ */
_$normalizeContentItem: function (contentItemOrConfig, parent) {
if (!contentItemOrConfig) {
throw new Error('No content item defined');
@@ -1158,15 +1158,15 @@
}
},
- /**
- * Iterates through the array of open popout windows and removes the ones
- * that are effectively closed. This is necessary due to the lack of reliably
- * listening for window.close / unload events in a cross browser compatible fashion.
- *
- * @packagePrivate
- *
- * @returns {void}
- */
+ /**
+ * Iterates through the array of open popout windows and removes the ones
+ * that are effectively closed. This is necessary due to the lack of reliably
+ * listening for window.close / unload events in a cross browser compatible fashion.
+ *
+ * @packagePrivate
+ *
+ * @returns {void}
+ */
_$reconcilePopoutWindows: function () {
var openPopouts = [], i;
@@ -1185,17 +1185,17 @@
},
- /***************************
- * PRIVATE
- ***************************/
- /**
- * Returns a flattened array of all content items,
- * regardles of level or type
- *
- * @private
- *
- * @returns {void}
- */
+ /***************************
+ * PRIVATE
+ ***************************/
+ /**
+ * Returns a flattened array of all content items,
+ * regardles of level or type
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_getAllContentItems: function () {
var allContentItems = [];
@@ -1214,13 +1214,13 @@
return allContentItems;
},
- /**
- * Binds to DOM/BOM events on init
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Binds to DOM/BOM events on init
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_bindEvents: function () {
if (this._isFullPage) {
$(window).resize(this._resizeFunction);
@@ -1228,27 +1228,27 @@
$(window).on('unload beforeunload', this._unloadFunction);
},
- /**
- * Debounces resize events
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Debounces resize events
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_onResize: function () {
clearTimeout(this._resizeTimeoutId);
this._resizeTimeoutId = setTimeout(lm.utils.fnBind(this.updateSize, this), 100);
},
- /**
- * Extends the default config with the user specific settings and applies
- * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode)
- * that deals with the extension of item configs
- *
- * @param {Object} config
- * @static
- * @returns {Object} config
- */
+ /**
+ * Extends the default config with the user specific settings and applies
+ * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode)
+ * that deals with the extension of item configs
+ *
+ * @param {Object} config
+ * @static
+ * @returns {Object} config
+ */
_createConfig: function (config) {
var windowConfigKey = lm.utils.getQueryStringParam('gl-window');
@@ -1283,14 +1283,14 @@
return config;
},
- /**
- * This is executed when GoldenLayout detects that it is run
- * within a previously opened popout window.
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * This is executed when GoldenLayout detects that it is run
+ * within a previously opened popout window.
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_adjustToWindowMode: function () {
var popInButton = $('<div class="lm_popin" title="' + this.config.labels.popin + '">' +
'<div class="lm_icon"></div>' +
@@ -1310,26 +1310,26 @@
.css('visibility', 'visible')
.append(popInButton);
- /*
- * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around
- * slickgrid's "Cannot find stylesheet." bug in chrome
- */
+ /*
+ * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around
+ * slickgrid's "Cannot find stylesheet." bug in chrome
+ */
var x = document.body.offsetHeight; // jshint ignore:line
- /*
- * Expose this instance on the window object
- * to allow the opening window to interact with
- * it
- */
+ /*
+ * Expose this instance on the window object
+ * to allow the opening window to interact with
+ * it
+ */
window.__glInstance = this;
},
- /**
- * Creates Subwindows (if there are any). Throws an error
- * if popouts are blocked.
- *
- * @returns {void}
- */
+ /**
+ * Creates Subwindows (if there are any). Throws an error
+ * if popouts are blocked.
+ *
+ * @returns {void}
+ */
_createSubWindows: function () {
var i, popout;
@@ -1345,13 +1345,13 @@
}
},
- /**
- * Determines what element the layout will be created in
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Determines what element the layout will be created in
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_setContainer: function () {
var container = $(this.container || 'body');
@@ -1377,13 +1377,13 @@
this.container = container;
},
- /**
- * Kicks of the initial, recursive creation chain
- *
- * @param {Object} config GoldenLayout Config
- *
- * @returns {void}
- */
+ /**
+ * Kicks of the initial, recursive creation chain
+ *
+ * @param {Object} config GoldenLayout Config
+ *
+ * @returns {void}
+ */
_create: function (config) {
var errorMsg;
@@ -1410,12 +1410,12 @@
}
},
- /**
- * Called when the window is closed or the user navigates away
- * from the page
- *
- * @returns {void}
- */
+ /**
+ * Called when the window is closed or the user navigates away
+ * from the page
+ *
+ * @returns {void}
+ */
_onUnload: function () {
if (this.config.settings.closePopoutsOnUnload === true) {
for (var i = 0; i < this.openPopouts.length; i++) {
@@ -1424,11 +1424,11 @@
}
},
- /**
- * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth.
- *
- * @returns {void}
- */
+ /**
+ * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth.
+ *
+ * @returns {void}
+ */
_adjustColumnsResponsive: function () {
// If there is no min width set, or not content items, do nothing.
@@ -1470,21 +1470,21 @@
this._updatingColumnsResponsive = false;
},
- /**
- * Determines if responsive layout should be used.
- *
- * @returns {bool} - True if responsive layout should be used; otherwise false.
- */
+ /**
+ * Determines if responsive layout should be used.
+ *
+ * @returns {bool} - True if responsive layout should be used; otherwise false.
+ */
_useResponsiveLayout: function () {
return this.config.settings && (this.config.settings.responsiveMode == 'always' || (this.config.settings.responsiveMode == 'onload' && this._firstLoad));
},
- /**
- * Adds all children of a node to another container recursively.
- * @param {object} container - Container to add child content items to.
- * @param {object} node - Node to search for content items.
- * @returns {void}
- */
+ /**
+ * Adds all children of a node to another container recursively.
+ * @param {object} container - Container to add child content items to.
+ * @param {object} node - Node to search for content items.
+ * @returns {void}
+ */
_addChildContentItemsToContainer: function (container, node) {
if (node.type === 'stack') {
node.contentItems.forEach(function (item) {
@@ -1499,10 +1499,10 @@
}
},
- /**
- * Finds all the stack containers.
- * @returns {array} - The found stack containers.
- */
+ /**
+ * Finds all the stack containers.
+ * @returns {array} - The found stack containers.
+ */
_findAllStackContainers: function () {
var stackContainers = [];
this._findAllStackContainersRecursive(stackContainers, this.root);
@@ -1510,14 +1510,14 @@
return stackContainers;
},
- /**
- * Finds all the stack containers.
- *
- * @param {array} - Set of containers to populate.
- * @param {object} - Current node to process.
- *
- * @returns {void}
- */
+ /**
+ * Finds all the stack containers.
+ *
+ * @param {array} - Set of containers to populate.
+ * @param {object} - Current node to process.
+ *
+ * @returns {void}
+ */
_findAllStackContainersRecursive: function (stackContainers, node) {
node.contentItems.forEach(lm.utils.fnBind(function (item) {
if (item.type == 'stack') {
@@ -1530,9 +1530,9 @@
}
});
- /**
- * Expose the Layoutmanager as the single entrypoint using UMD
- */
+ /**
+ * Expose the Layoutmanager as the single entrypoint using UMD
+ */
(function () {
/* global define */
if (typeof define === 'function' && define.amd) {
@@ -1567,15 +1567,15 @@
showCloseIcon: true,
responsiveMode: 'onload', // Can be onload, always, or none.
tabOverlapAllowance: 0, // maximum pixel overlap per tab
- reorderOnTabMenuClick: true,
+ reorderOnTabMenuClick: false, //do not reorder! - horizontal scroll
tabControlOffset: 10
},
dimensions: {
- borderWidth: 5,
+ borderWidth: 3,
borderGrabWidth: 5,
minItemHeight: 10,
- minItemWidth: 10,
- headerHeight: 20,
+ minItemWidth: 20,
+ headerHeight: 27,
dragProxyWidth: 300,
dragProxyHeight: 200
},
@@ -1611,36 +1611,36 @@
lm.utils.copy(lm.container.ItemContainer.prototype, {
- /**
- * Get the inner DOM element the container's content
- * is intended to live in
- *
- * @returns {DOM element}
- */
+ /**
+ * Get the inner DOM element the container's content
+ * is intended to live in
+ *
+ * @returns {DOM element}
+ */
getElement: function () {
return this._contentElement;
},
- /**
- * Hide the container. Notifies the containers content first
- * and then hides the DOM node. If the container is already hidden
- * this should have no effect
- *
- * @returns {void}
- */
+ /**
+ * Hide the container. Notifies the containers content first
+ * and then hides the DOM node. If the container is already hidden
+ * this should have no effect
+ *
+ * @returns {void}
+ */
hide: function () {
this.emit('hide');
this.isHidden = true;
this._element.hide();
},
- /**
- * Shows a previously hidden container. Notifies the
- * containers content first and then shows the DOM element.
- * If the container is already visible this has no effect.
- *
- * @returns {void}
- */
+ /**
+ * Shows a previously hidden container. Notifies the
+ * containers content first and then shows the DOM element.
+ * If the container is already visible this has no effect.
+ *
+ * @returns {void}
+ */
show: function () {
this.emit('show');
this.isHidden = false;
@@ -1651,19 +1651,19 @@
}
},
- /**
- * Set the size from within the container. Traverses up
- * the item tree until it finds a row or column element
- * and resizes its items accordingly.
- *
- * If this container isn't a descendant of a row or column
- * it returns false
- * @todo Rework!!!
- * @param {Number} width The new width in pixel
- * @param {Number} height The new height in pixel
- *
- * @returns {Boolean} resizeSuccesful
- */
+ /**
+ * Set the size from within the container. Traverses up
+ * the item tree until it finds a row or column element
+ * and resizes its items accordingly.
+ *
+ * If this container isn't a descendant of a row or column
+ * it returns false
+ * @todo Rework!!!
+ * @param {Number} width The new width in pixel
+ * @param {Number} height The new height in pixel
+ *
+ * @returns {Boolean} resizeSuccesful
+ */
setSize: function (width, height) {
var rowOrColumn = this.parent,
rowOrColumnChild = this,
@@ -1679,9 +1679,9 @@
rowOrColumn = rowOrColumn.parent;
- /**
- * No row or column has been found
- */
+ /**
+ * No row or column has been found
+ */
if (rowOrColumn.isRoot) {
return false;
}
@@ -1707,13 +1707,13 @@
return true;
},
- /**
- * Closes the container if it is closable. Can be called by
- * both the component within at as well as the contentItem containing
- * it. Emits a close event before the container itself is closed.
- *
- * @returns {void}
- */
+ /**
+ * Closes the container if it is closable. Can be called by
+ * both the component within at as well as the contentItem containing
+ * it. Emits a close event before the container itself is closed.
+ *
+ * @returns {void}
+ */
close: function () {
if (this._config.isClosable) {
this.emit('close');
@@ -1721,55 +1721,55 @@
}
},
- /**
- * Returns the current state object
- *
- * @returns {Object} state
- */
+ /**
+ * Returns the current state object
+ *
+ * @returns {Object} state
+ */
getState: function () {
return this._config.componentState;
},
- /**
- * Merges the provided state into the current one
- *
- * @param {Object} state
- *
- * @returns {void}
- */
+ /**
+ * Merges the provided state into the current one
+ *
+ * @param {Object} state
+ *
+ * @returns {void}
+ */
extendState: function (state) {
this.setState($.extend(true, this.getState(), state));
},
- /**
- * Notifies the layout manager of a stateupdate
- *
- * @param {serialisable} state
- */
+ /**
+ * Notifies the layout manager of a stateupdate
+ *
+ * @param {serialisable} state
+ */
setState: function (state) {
this._config.componentState = state;
this.parent.emitBubblingEvent('stateChanged');
},
- /**
- * Set's the components title
- *
- * @param {String} title
- */
+ /**
+ * Set's the components title
+ *
+ * @param {String} title
+ */
setTitle: function (title) {
this.parent.setTitle(title);
},
- /**
- * Set's the containers size. Called by the container's component.
- * To set the size programmatically from within the container please
- * use the public setSize method
- *
- * @param {[Int]} width in px
- * @param {[Int]} height in px
- *
- * @returns {void}
- */
+ /**
+ * Set's the containers size. Called by the container's component.
+ * To set the size programmatically from within the container please
+ * use the public setSize method
+ *
+ * @param {[Int]} width in px
+ * @param {[Int]} height in px
+ *
+ * @returns {void}
+ */
_$setSize: function (width, height) {
if (width !== this.width || height !== this.height) {
this.width = width;
@@ -1784,22 +1784,22 @@
}
});
- /**
- * Pops a content item out into a new browser window.
- * This is achieved by
- *
- * - Creating a new configuration with the content item as root element
- * - Serializing and minifying the configuration
- * - Opening the current window's URL with the configuration as a GET parameter
- * - GoldenLayout when opened in the new window will look for the GET parameter
- * and use it instead of the provided configuration
- *
- * @param {Object} config GoldenLayout item config
- * @param {Object} dimensions A map with width, height, top and left
- * @param {String} parentId The id of the element the item will be appended to on popIn
- * @param {Number} indexInParent The position of this element within its parent
- * @param {lm.LayoutManager} layoutManager
- */
+ /**
+ * Pops a content item out into a new browser window.
+ * This is achieved by
+ *
+ * - Creating a new configuration with the content item as root element
+ * - Serializing and minifying the configuration
+ * - Opening the current window's URL with the configuration as a GET parameter
+ * - GoldenLayout when opened in the new window will look for the GET parameter
+ * and use it instead of the provided configuration
+ *
+ * @param {Object} config GoldenLayout item config
+ * @param {Object} dimensions A map with width, height, top and left
+ * @param {String} parentId The id of the element the item will be appended to on popIn
+ * @param {Number} indexInParent The position of this element within its parent
+ * @param {lm.LayoutManager} layoutManager
+ */
lm.controls.BrowserPopout = function (config, dimensions, parentId, indexInParent, layoutManager) {
lm.utils.EventEmitter.call(this);
this.isInitialised = false;
@@ -1853,10 +1853,10 @@
}
},
- /**
- * Returns the popped out item to its original position. If the original
- * parent isn't available anymore it falls back to the layout's topmost element
- */
+ /**
+ * Returns the popped out item to its original position. If the original
+ * parent isn't available anymore it falls back to the layout's topmost element
+ */
popIn: function () {
var childConfig,
parentItem,
@@ -1864,22 +1864,22 @@
if (this._parentId) {
- /*
- * The $.extend call seems a bit pointless, but it's crucial to
- * copy the config returned by this.getGlInstance().toConfig()
- * onto a new object. Internet Explorer keeps the references
- * to objects on the child window, resulting in the following error
- * once the child window is closed:
- *
- * The callee (server [not server application]) is not available and disappeared
- */
+ /*
+ * The $.extend call seems a bit pointless, but it's crucial to
+ * copy the config returned by this.getGlInstance().toConfig()
+ * onto a new object. Internet Explorer keeps the references
+ * to objects on the child window, resulting in the following error
+ * once the child window is closed:
+ *
+ * The callee (server [not server application]) is not available and disappeared
+ */
childConfig = $.extend(true, {}, this.getGlInstance().toConfig()).content[0];
parentItem = this._layoutManager.root.getItemsById(this._parentId)[0];
- /*
- * Fallback if parentItem is not available. Either add it to the topmost
- * item or make it the topmost item if the layout is empty
- */
+ /*
+ * Fallback if parentItem is not available. Either add it to the topmost
+ * item or make it the topmost item if the layout is empty
+ */
if (!parentItem) {
if (this._layoutManager.root.contentItems.length > 0) {
parentItem = this._layoutManager.root.contentItems[0];
@@ -1894,28 +1894,28 @@
this.close();
},
- /**
- * Creates the URL and window parameter
- * and opens a new window
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Creates the URL and window parameter
+ * and opens a new window
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_createWindow: function () {
var checkReadyInterval,
url = this._createUrl(),
- /**
- * Bogus title to prevent re-usage of existing window with the
- * same title. The actual title will be set by the new window's
- * GoldenLayout instance if it detects that it is in subWindowMode
- */
+ /**
+ * Bogus title to prevent re-usage of existing window with the
+ * same title. The actual title will be set by the new window's
+ * GoldenLayout instance if it detects that it is in subWindowMode
+ */
title = Math.floor(Math.random() * 1000000).toString(36),
- /**
- * The options as used in the window.open string
- */
+ /**
+ * The options as used in the window.open string
+ */
options = this._serializeWindowOptions({
width: this._dimensions.width,
height: this._dimensions.height,
@@ -1946,12 +1946,12 @@
.on('load', lm.utils.fnBind(this._positionWindow, this))
.on('unload beforeunload', lm.utils.fnBind(this._onClose, this));
- /**
- * Polling the childwindow to find out if GoldenLayout has been initialised
- * doesn't seem optimal, but the alternatives - adding a callback to the parent
- * window or raising an event on the window object - both would introduce knowledge
- * about the parent to the child window which we'd rather avoid
- */
+ /**
+ * Polling the childwindow to find out if GoldenLayout has been initialised
+ * doesn't seem optimal, but the alternatives - adding a callback to the parent
+ * window or raising an event on the window object - both would introduce knowledge
+ * about the parent to the child window which we'd rather avoid
+ */
checkReadyInterval = setInterval(lm.utils.fnBind(function () {
if (this._popoutWindow.__glInstance && this._popoutWindow.__glInstance.isInitialised) {
this._onInitialised();
@@ -1960,13 +1960,13 @@
}, this), 10);
},
- /**
- * Serialises a map of key:values to a window options string
- *
- * @param {Object} windowOptions
- *
- * @returns {String} serialised window options
- */
+ /**
+ * Serialises a map of key:values to a window options string
+ *
+ * @param {Object} windowOptions
+ *
+ * @returns {String} serialised window options
+ */
_serializeWindowOptions: function (windowOptions) {
var windowOptionsString = [], key;
@@ -1977,12 +1977,12 @@
return windowOptionsString.join(',');
},
- /**
- * Creates the URL for the new window, including the
- * config GET parameter
- *
- * @returns {String} URL
- */
+ /**
+ * Creates the URL for the new window, including the
+ * config GET parameter
+ *
+ * @returns {String} URL
+ */
_createUrl: function () {
var config = { content: this._config },
storageKey = 'gl-window-config-' + lm.utils.getUniqueId(),
@@ -2008,57 +2008,57 @@
}
},
- /**
- * Move the newly created window roughly to
- * where the component used to be.
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Move the newly created window roughly to
+ * where the component used to be.
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_positionWindow: function () {
this._popoutWindow.moveTo(this._dimensions.left, this._dimensions.top);
this._popoutWindow.focus();
},
- /**
- * Callback when the new window is opened and the GoldenLayout instance
- * within it is initialised
- *
- * @returns {void}
- */
+ /**
+ * Callback when the new window is opened and the GoldenLayout instance
+ * within it is initialised
+ *
+ * @returns {void}
+ */
_onInitialised: function () {
this.isInitialised = true;
this.getGlInstance().on('popIn', this.popIn, this);
this.emit('initialised');
},
- /**
- * Invoked 50ms after the window unload event
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Invoked 50ms after the window unload event
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_onClose: function () {
setTimeout(lm.utils.fnBind(this.emit, this, ['closed']), 50);
}
});
- /**
- * This class creates a temporary container
- * for the component whilst it is being dragged
- * and handles drag events
- *
- * @constructor
- * @private
- *
- * @param {Number} x The initial x position
- * @param {Number} y The initial y position
- * @param {lm.utils.DragListener} dragListener
- * @param {lm.LayoutManager} layoutManager
- * @param {lm.item.AbstractContentItem} contentItem
- * @param {lm.item.AbstractContentItem} originalParent
- */
+ /**
+ * This class creates a temporary container
+ * for the component whilst it is being dragged
+ * and handles drag events
+ *
+ * @constructor
+ * @private
+ *
+ * @param {Number} x The initial x position
+ * @param {Number} y The initial y position
+ * @param {lm.utils.DragListener} dragListener
+ * @param {lm.LayoutManager} layoutManager
+ * @param {lm.item.AbstractContentItem} contentItem
+ * @param {lm.item.AbstractContentItem} originalParent
+ */
lm.controls.DragProxy = function (x, y, dragListener, layoutManager, contentItem, originalParent) {
lm.utils.EventEmitter.call(this);
@@ -2120,19 +2120,19 @@
lm.utils.copy(lm.controls.DragProxy.prototype, {
- /**
- * Callback on every mouseMove event during a drag. Determines if the drag is
- * still within the valid drag area and calls the layoutManager to highlight the
- * current drop area
- *
- * @param {Number} offsetX The difference from the original x position in px
- * @param {Number} offsetY The difference from the original y position in px
- * @param {jQuery DOM event} event
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Callback on every mouseMove event during a drag. Determines if the drag is
+ * still within the valid drag area and calls the layoutManager to highlight the
+ * current drop area
+ *
+ * @param {Number} offsetX The difference from the original x position in px
+ * @param {Number} offsetY The difference from the original y position in px
+ * @param {jQuery DOM event} event
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_onDrag: function (offsetX, offsetY, event) {
event = event.originalEvent && event.originalEvent.touches ? event.originalEvent.touches[0] : event;
@@ -2148,16 +2148,16 @@
this._setDropPosition(x, y);
},
- /**
- * Sets the target position, highlighting the appropriate area
- *
- * @param {Number} x The x position in px
- * @param {Number} y The y position in px
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Sets the target position, highlighting the appropriate area
+ *
+ * @param {Number} x The x position in px
+ * @param {Number} y The y position in px
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_setDropPosition: function (x, y) {
this.element.css({ left: x, top: y });
this._area = this._layoutManager._$getArea(x, y);
@@ -2168,43 +2168,43 @@
}
},
- /**
- * Callback when the drag has finished. Determines the drop area
- * and adds the child to it
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Callback when the drag has finished. Determines the drop area
+ * and adds the child to it
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_onDrop: function () {
this._layoutManager.dropTargetIndicator.hide();
- /*
- * Valid drop area found
- */
+ /*
+ * Valid drop area found
+ */
if (this._area !== null) {
this._area.contentItem._$onDrop(this._contentItem, this._area);
- /**
- * No valid drop area available at present, but one has been found before.
- * Use it
- */
+ /**
+ * No valid drop area available at present, but one has been found before.
+ * Use it
+ */
} else if (this._lastValidArea !== null) {
this._lastValidArea.contentItem._$onDrop(this._contentItem, this._lastValidArea);
- /**
- * No valid drop area found during the duration of the drag. Return
- * content item to its original position if a original parent is provided.
- * (Which is not the case if the drag had been initiated by createDragSource)
- */
+ /**
+ * No valid drop area found during the duration of the drag. Return
+ * content item to its original position if a original parent is provided.
+ * (Which is not the case if the drag had been initiated by createDragSource)
+ */
} else if (this._originalParent) {
this._originalParent.addChild(this._contentItem);
- /**
- * The drag didn't ultimately end up with adding the content item to
- * any container. In order to ensure clean up happens, destroy the
- * content item.
- */
+ /**
+ * The drag didn't ultimately end up with adding the content item to
+ * any container. In order to ensure clean up happens, destroy the
+ * content item.
+ */
} else {
this._contentItem._$destroy();
}
@@ -2215,18 +2215,18 @@
this._layoutManager.emit('itemDropped', this._contentItem);
},
- /**
- * Removes the item from its original position within the tree
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Removes the item from its original position within the tree
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_updateTree: function () {
- /**
- * parent is null if the drag had been initiated by a external drag source
- */
+ /**
+ * parent is null if the drag had been initiated by a external drag source
+ */
if (this._contentItem.parent) {
this._contentItem.parent.removeChild(this._contentItem, true);
}
@@ -2234,13 +2234,13 @@
this._contentItem._$setParent(this);
},
- /**
- * Updates the Drag Proxie's dimensions
- *
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Updates the Drag Proxie's dimensions
+ *
+ * @private
+ *
+ * @returns {void}
+ */
_setDimensions: function () {
var dimensions = this._layoutManager.config.dimensions,
width = dimensions.dragProxyWidth,
@@ -2259,16 +2259,16 @@
}
});
- /**
- * Allows for any DOM item to create a component on drag
- * start tobe dragged into the Layout
- *
- * @param {jQuery element} element
- * @param {Object} itemConfig the configuration for the contentItem that will be created
- * @param {LayoutManager} layoutManager
- *
- * @constructor
- */
+ /**
+ * Allows for any DOM item to create a component on drag
+ * start tobe dragged into the Layout
+ *
+ * @param {jQuery element} element
+ * @param {Object} itemConfig the configuration for the contentItem that will be created
+ * @param {LayoutManager} layoutManager
+ *
+ * @constructor
+ */
lm.controls.DragSource = function (element, itemConfig, layoutManager) {
this._element = element;
this._itemConfig = itemConfig;
@@ -2280,11 +2280,11 @@
lm.utils.copy(lm.controls.DragSource.prototype, {
- /**
- * Called initially and after every drag
- *
- * @returns {void}
- */
+ /**
+ * Called initially and after every drag
+ *
+ * @returns {void}
+ */
_createDragListener: function () {
if (this._dragListener !== null) {
this._dragListener.destroy();
@@ -2306,14 +2306,14 @@
}
},
- /**
- * Callback for the DragListener's dragStart event
- *
- * @param {int} x the x position of the mouse on dragStart
- * @param {int} y the x position of the mouse on dragStart
- *
- * @returns {void}
- */
+ /**
+ * Callback for the DragListener's dragStart event
+ *
+ * @param {int} x the x position of the mouse on dragStart
+ * @param {int} y the x position of the mouse on dragStart
+ *
+ * @returns {void}
+ */
_onDragStart: function (x, y) {
var itemConfig = this._itemConfig;
if (lm.utils.isFunction(itemConfig)) {
@@ -2355,12 +2355,12 @@
this.element.hide();
}
});
- /**
- * This class represents a header above a Stack ContentItem.
- *
- * @param {lm.LayoutManager} layoutManager
- * @param {lm.item.AbstractContentItem} parent
- */
+ /**
+ * This class represents a header above a Stack ContentItem.
+ *
+ * @param {lm.LayoutManager} layoutManager
+ * @param {lm.item.AbstractContentItem} parent
+ */
lm.controls.Header = function (layoutManager, parent) {
lm.utils.EventEmitter.call(this);
@@ -2390,24 +2390,24 @@
this._createControls();
};
+ // '<ul class="lm_tabdropdown_list"></ul>',
lm.controls.Header._template = [
'<div class="lm_header">',
'<ul class="lm_tabs"></ul>',
'<ul class="lm_controls"></ul>',
- '<ul class="lm_tabdropdown_list"></ul>',
'</div>'
].join('');
lm.utils.copy(lm.controls.Header.prototype, {
- /**
- * Creates a new tab and associates it with a contentItem
- *
- * @param {lm.item.AbstractContentItem} contentItem
- * @param {Integer} index The position of the tab
- *
- * @returns {void}
- */
+ /**
+ * Creates a new tab and associates it with a contentItem
+ *
+ * @param {lm.item.AbstractContentItem} contentItem
+ * @param {Integer} index The position of the tab
+ *
+ * @returns {void}
+ */
createTab: function (contentItem, index) {
var tab, i;
@@ -2441,13 +2441,13 @@
this._updateTabSizes();
},
- /**
- * Finds a tab based on the contentItem its associated with and removes it.
- *
- * @param {lm.item.AbstractContentItem} contentItem
- *
- * @returns {void}
- */
+ /**
+ * Finds a tab based on the contentItem its associated with and removes it.
+ *
+ * @param {lm.item.AbstractContentItem} contentItem
+ *
+ * @returns {void}
+ */
removeTab: function (contentItem) {
for (var i = 0; i < this.tabs.length; i++) {
if (this.tabs[i].contentItem === contentItem) {
@@ -2460,11 +2460,11 @@
throw new Error('contentItem is not controlled by this header');
},
- /**
- * The programmatical equivalent of clicking a Tab.
- *
- * @param {lm.item.AbstractContentItem} contentItem
- */
+ /**
+ * The programmatical equivalent of clicking a Tab.
+ *
+ * @param {lm.item.AbstractContentItem} contentItem
+ */
setActiveContentItem: function (contentItem) {
var i, j, isActive, activeTab;
@@ -2477,32 +2477,33 @@
}
}
- if (this.layoutManager.config.settings.reorderOnTabMenuClick) {
- /**
- * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
- * This will make sure the most used tabs stay visible.
- */
- if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) {
- activeTab = this.tabs[this.parent.config.activeItemIndex];
- for (j = this.parent.config.activeItemIndex; j > 0; j--) {
- this.tabs[j] = this.tabs[j - 1];
- }
- this.tabs[0] = activeTab;
- this.parent.config.activeItemIndex = 0;
- }
- }
+ // glr: removed for new tab manager
+ // if (this.layoutManager.config.settings.reorderOnTabMenuClick) {
+ // /**
+ // * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
+ // * This will make sure the most used tabs stay visible.
+ // */
+ // if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) {
+ // activeTab = this.tabs[this.parent.config.activeItemIndex];
+ // for (j = this.parent.config.activeItemIndex; j > 0; j--) {
+ // this.tabs[j] = this.tabs[j - 1];
+ // }
+ // this.tabs[0] = activeTab;
+ // this.parent.config.activeItemIndex = 0;
+ // }
+ // }
this._updateTabSizes();
this.parent.emitBubblingEvent('stateChanged');
},
- /**
- * Programmatically operate with header position.
- *
- * @param {string} position one of ('top','left','right','bottom') to set or empty to get it.
- *
- * @returns {string} previous header position
- */
+ /**
+ * Programmatically operate with header position.
+ *
+ * @param {string} position one of ('top','left','right','bottom') to set or empty to get it.
+ *
+ * @returns {string} previous header position
+ */
position: function (position) {
var previous = this.parent._header.show;
if (previous && !this.parent._side)
@@ -2514,14 +2515,14 @@
return previous;
},
- /**
- * Programmatically set closability.
- *
- * @package private
- * @param {Boolean} isClosable Whether to enable/disable closability.
- *
- * @returns {Boolean} Whether the action was successful
- */
+ /**
+ * Programmatically set closability.
+ *
+ * @package private
+ * @param {Boolean} isClosable Whether to enable/disable closability.
+ *
+ * @returns {Boolean} Whether the action was successful
+ */
_$setClosable: function (isClosable) {
if (this.closeButton && this._isClosable()) {
this.closeButton.element[isClosable ? "show" : "hide"]();
@@ -2531,13 +2532,13 @@
return false;
},
- /**
- * Destroys the entire header
- *
- * @package private
- *
- * @returns {void}
- */
+ /**
+ * Destroys the entire header
+ *
+ * @package private
+ *
+ * @returns {void}
+ */
_$destroy: function () {
this.emit('destroy', this);
@@ -2548,20 +2549,20 @@
this.element.remove();
},
- /**
- * get settings from header
- *
- * @returns {string} when exists
- */
+ /**
+ * get settings from header
+ *
+ * @returns {string} when exists
+ */
_getHeaderSetting: function (name) {
if (name in this.parent._header)
return this.parent._header[name];
},
- /**
- * Creates the popout, maximise and close buttons in the header's top right corner
- *
- * @returns {void}
- */
+ /**
+ * Creates the popout, maximise and close buttons in the header's top right corner
+ *
+ * @returns {void}
+ */
_createControls: function () {
var closeStack,
popout,
@@ -2573,26 +2574,26 @@
tabDropdownLabel,
showTabDropdown;
- /**
- * Dropdown to show additional tabs.
- */
+ /**
+ * Dropdown to show additional tabs.
+ */
showTabDropdown = lm.utils.fnBind(this._showAdditionalTabsDropdown, this);
tabDropdownLabel = this.layoutManager.config.labels.tabDropdown;
- this.tabDropdownButton = new lm.controls.HeaderButton(this, tabDropdownLabel, 'lm_tabdropdown', showTabDropdown);
- this.tabDropdownButton.element.hide();
+ // this.tabDropdownButton = new lm.controls.HeaderButton(this, tabDropdownLabel, 'lm_tabdropdown', showTabDropdown);
+ // this.tabDropdownButton.element.hide();
- /**
- * Popout control to launch component in new window.
- */
+ /**
+ * Popout control to launch component in new window.
+ */
if (this._getHeaderSetting('popout')) {
popout = lm.utils.fnBind(this._onPopoutClick, this);
label = this._getHeaderSetting('popout');
new lm.controls.HeaderButton(this, label, 'lm_popout', popout);
}
- /**
- * Maximise control - set the component to the full size of the layout
- */
+ /**
+ * Maximise control - set the component to the full size of the layout
+ */
if (this._getHeaderSetting('maximise')) {
maximise = lm.utils.fnBind(this.parent.toggleMaximise, this.parent);
maximiseLabel = this._getHeaderSetting('maximise');
@@ -2608,9 +2609,9 @@
});
}
- /**
- * Close button
- */
+ /**
+ * Close button
+ */
if (this._isClosable()) {
closeStack = lm.utils.fnBind(this.parent.remove, this.parent);
label = this._getHeaderSetting('close');
@@ -2618,30 +2619,30 @@
}
},
- /**
- * Shows drop down for additional tabs when there are too many to display.
- *
- * @returns {void}
- */
+ /**
+ * Shows drop down for additional tabs when there are too many to display.
+ *
+ * @returns {void}
+ */
_showAdditionalTabsDropdown: function () {
this.tabDropdownContainer.show();
},
- /**
- * Hides drop down for additional tabs when there are too many to display.
- *
- * @returns {void}
- */
+ /**
+ * Hides drop down for additional tabs when there are too many to display.
+ *
+ * @returns {void}
+ */
_hideAdditionalTabsDropdown: function (e) {
this.tabDropdownContainer.hide();
},
- /**
- * Checks whether the header is closable based on the parent config and
- * the global config.
- *
- * @returns {Boolean} Whether the header is closable.
- */
+ /**
+ * Checks whether the header is closable based on the parent config and
+ * the global config.
+ *
+ * @returns {Boolean} Whether the header is closable.
+ */
_isClosable: function () {
return this.parent.config.isClosable && this.layoutManager.config.settings.showCloseIcon;
},
@@ -2655,32 +2656,29 @@
},
- /**
- * Invoked when the header's background is clicked (not it's tabs or controls)
- *
- * @param {jQuery DOM event} event
- *
- * @returns {void}
- */
+ /**
+ * Invoked when the header's background is clicked (not it's tabs or controls)
+ *
+ * @param {jQuery DOM event} event
+ *
+ * @returns {void}
+ */
_onHeaderClick: function (event) {
if (event.target === this.element[0]) {
this.parent.select();
}
},
- /**
- * Pushes the tabs to the tab dropdown if the available space is not sufficient
- *
- * @returns {void}
- */
+ /**
+ * Pushes the tabs to the tab dropdown if the available space is not sufficient
+ *
+ * @returns {void}
+ */
_updateTabSizes: function (showTabMenu) {
if (this.tabs.length === 0) {
return;
}
- //Show the menu based on function argument
- this.tabDropdownButton.element.toggle(showTabMenu === true);
-
var size = function (val) {
return val ? 'width' : 'height';
};
@@ -2835,14 +2833,14 @@
}
});
- /**
- * Represents an individual tab within a Stack's header
- *
- * @param {lm.controls.Header} header
- * @param {lm.items.AbstractContentItem} contentItem
- *
- * @constructor
- */
+ /**
+ * Represents an individual tab within a Stack's header
+ *
+ * @param {lm.controls.Header} header
+ * @param {lm.items.AbstractContentItem} contentItem
+ *
+ * @constructor
+ */
lm.controls.Tab = function (header, contentItem) {
this.header = header;
this.contentItem = contentItem;
@@ -2888,37 +2886,37 @@
}
};
- /**
- * The tab's html template
- *
- * @type {String}
- */
+ /**
+ * The tab's html template
+ *
+ * @type {String}
+ */
lm.controls.Tab._template = '<li class="lm_tab"><i class="lm_left"></i>' +
'<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab"></div>' +
'<i class="lm_right"></i></li>';
lm.utils.copy(lm.controls.Tab.prototype, {
- /**
- * Sets the tab's title to the provided string and sets
- * its title attribute to a pure text representation (without
- * html tags) of the same string.
- *
- * @public
- * @param {String} title can contain html
- */
+ /**
+ * Sets the tab's title to the provided string and sets
+ * its title attribute to a pure text representation (without
+ * html tags) of the same string.
+ *
+ * @public
+ * @param {String} title can contain html
+ */
setTitle: function (title) {
this.element.attr('title', lm.utils.stripTags(title));
this.titleElement.html(title);
},
- /**
- * Sets this tab's active state. To programmatically
- * switch tabs, use header.setActiveContentItem( item ) instead.
- *
- * @public
- * @param {Boolean} isActive
- */
+ /**
+ * Sets this tab's active state. To programmatically
+ * switch tabs, use header.setActiveContentItem( item ) instead.
+ *
+ * @public
+ * @param {Boolean} isActive
+ */
setActive: function (isActive) {
if (isActive === this.isActive) {
return;
@@ -2932,12 +2930,12 @@
}
},
- /**
- * Destroys the tab
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Destroys the tab
+ *
+ * @private
+ * @returns {void}
+ */
_$destroy: function () {
this._layoutManager.emit('tabDestroyed', this);
this.element.off('mousedown touchstart', this._onTabClickFn);
@@ -2950,15 +2948,15 @@
this.element.remove();
},
- /**
- * Callback for the DragListener
- *
- * @param {Number} x The tabs absolute x position
- * @param {Number} y The tabs absolute y position
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Callback for the DragListener
+ *
+ * @param {Number} x The tabs absolute x position
+ * @param {Number} y The tabs absolute y position
+ *
+ * @private
+ * @returns {void}
+ */
_onDragStart: function (x, y) {
if (this.contentItem.parent.isMaximised === true) {
this.contentItem.parent.toggleMaximise();
@@ -2973,14 +2971,14 @@
);
},
- /**
- * Callback when the tab is clicked
- *
- * @param {jQuery DOM event} event
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Callback when the tab is clicked
+ *
+ * @param {jQuery DOM event} event
+ *
+ * @private
+ * @returns {void}
+ */
_onTabClick: function (event) {
// left mouse button or tap
if (event.button === 0 || event.type === 'touchstart') {
@@ -2995,30 +2993,30 @@
}
},
- /**
- * Callback when the tab's close button is
- * clicked
- *
- * @param {jQuery DOM event} event
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Callback when the tab's close button is
+ * clicked
+ *
+ * @param {jQuery DOM event} event
+ *
+ * @private
+ * @returns {void}
+ */
_onCloseClick: function (event) {
event.stopPropagation();
this.header.parent.removeChild(this.contentItem);
},
- /**
- * Callback to capture tab close button mousedown
- * to prevent tab from activating.
- *
- * @param (jQuery DOM event) event
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Callback to capture tab close button mousedown
+ * to prevent tab from activating.
+ *
+ * @param (jQuery DOM event) event
+ *
+ * @private
+ * @returns {void}
+ */
_onCloseMousedown: function (event) {
event.stopPropagation();
}
@@ -3040,9 +3038,9 @@
},
transitionElements: function (fromElement, toElement) {
- /**
- * TODO - This is not quite as cool as expected. Review.
- */
+ /**
+ * TODO - This is not quite as cool as expected. Review.
+ */
return;
this._toElement = toElement;
this._animationStartTime = lm.utils.now();
@@ -3096,27 +3094,27 @@
lm.errors.ConfigurationError.prototype = new Error();
- /**
- * This is the baseclass that all content items inherit from.
- * Most methods provide a subset of what the sub-classes do.
- *
- * It also provides a number of functions for tree traversal
- *
- * @param {lm.LayoutManager} layoutManager
- * @param {item node configuration} config
- * @param {lm.item} parent
- *
- * @event stateChanged
- * @event beforeItemDestroyed
- * @event itemDestroyed
- * @event itemCreated
- * @event componentCreated
- * @event rowCreated
- * @event columnCreated
- * @event stackCreated
- *
- * @constructor
- */
+ /**
+ * This is the baseclass that all content items inherit from.
+ * Most methods provide a subset of what the sub-classes do.
+ *
+ * It also provides a number of functions for tree traversal
+ *
+ * @param {lm.LayoutManager} layoutManager
+ * @param {item node configuration} config
+ * @param {lm.item} parent
+ *
+ * @event stateChanged
+ * @event beforeItemDestroyed
+ * @event itemDestroyed
+ * @event itemCreated
+ * @event componentCreated
+ * @event rowCreated
+ * @event columnCreated
+ * @event stackCreated
+ *
+ * @constructor
+ */
lm.items.AbstractContentItem = function (layoutManager, config, parent) {
lm.utils.EventEmitter.call(this);
@@ -3146,26 +3144,26 @@
lm.utils.copy(lm.items.AbstractContentItem.prototype, {
- /**
- * Set the size of the component and its children, called recursively
- *
- * @abstract
- * @returns void
- */
+ /**
+ * Set the size of the component and its children, called recursively
+ *
+ * @abstract
+ * @returns void
+ */
setSize: function () {
throw new Error('Abstract Method');
},
- /**
- * Calls a method recursively downwards on the tree
- *
- * @param {String} functionName the name of the function to be called
- * @param {[Array]}functionArguments optional arguments that are passed to every function
- * @param {[bool]} bottomUp Call methods from bottom to top, defaults to false
- * @param {[bool]} skipSelf Don't invoke the method on the class that calls it, defaults to false
- *
- * @returns {void}
- */
+ /**
+ * Calls a method recursively downwards on the tree
+ *
+ * @param {String} functionName the name of the function to be called
+ * @param {[Array]}functionArguments optional arguments that are passed to every function
+ * @param {[bool]} bottomUp Call methods from bottom to top, defaults to false
+ * @param {[bool]} skipSelf Don't invoke the method on the class that calls it, defaults to false
+ *
+ * @returns {void}
+ */
callDownwards: function (functionName, functionArguments, bottomUp, skipSelf) {
var i;
@@ -3180,53 +3178,53 @@
}
},
- /**
- * Removes a child node (and its children) from the tree
- *
- * @param {lm.items.ContentItem} contentItem
- *
- * @returns {void}
- */
+ /**
+ * Removes a child node (and its children) from the tree
+ *
+ * @param {lm.items.ContentItem} contentItem
+ *
+ * @returns {void}
+ */
removeChild: function (contentItem, keepChild) {
- /*
- * Get the position of the item that's to be removed within all content items this node contains
- */
+ /*
+ * Get the position of the item that's to be removed within all content items this node contains
+ */
var index = lm.utils.indexOf(contentItem, this.contentItems);
- /*
- * Make sure the content item to be removed is actually a child of this item
- */
+ /*
+ * Make sure the content item to be removed is actually a child of this item
+ */
if (index === -1) {
throw new Error('Can\'t remove child item. Unknown content item');
}
- /**
- * Call ._$destroy on the content item. This also calls ._$destroy on all its children
- */
+ /**
+ * Call ._$destroy on the content item. This also calls ._$destroy on all its children
+ */
if (keepChild !== true) {
this.contentItems[index]._$destroy();
}
- /**
- * Remove the content item from this nodes array of children
- */
+ /**
+ * Remove the content item from this nodes array of children
+ */
this.contentItems.splice(index, 1);
- /**
- * Remove the item from the configuration
- */
+ /**
+ * Remove the item from the configuration
+ */
this.config.content.splice(index, 1);
- /**
- * If this node still contains other content items, adjust their size
- */
+ /**
+ * If this node still contains other content items, adjust their size
+ */
if (this.contentItems.length > 0) {
this.callDownwards('setSize');
- /**
- * If this was the last content item, remove this node as well
- */
+ /**
+ * If this was the last content item, remove this node as well
+ */
} else if (!(this instanceof lm.items.Root) && this.config.isClosable === true) {
const stack = this;
const rowOrCol = stack.parent;
@@ -3244,14 +3242,14 @@
}
},
- /**
- * Sets up the tree structure for the newly added child
- * The responsibility for the actual DOM manipulations lies
- * with the concrete item
- *
- * @param {lm.items.AbstractContentItem} contentItem
- * @param {[Int]} index If omitted item will be appended
- */
+ /**
+ * Sets up the tree structure for the newly added child
+ * The responsibility for the actual DOM manipulations lies
+ * with the concrete item
+ *
+ * @param {lm.items.AbstractContentItem} contentItem
+ * @param {[Int]} index If omitted item will be appended
+ */
addChild: function (contentItem, index) {
if (index === undefined) {
index = this.contentItems.length;
@@ -3271,15 +3269,15 @@
}
},
- /**
- * Replaces oldChild with newChild. This used to use jQuery.replaceWith... which for
- * some reason removes all event listeners, so isn't really an option.
- *
- * @param {lm.item.AbstractContentItem} oldChild
- * @param {lm.item.AbstractContentItem} newChild
- *
- * @returns {void}
- */
+ /**
+ * Replaces oldChild with newChild. This used to use jQuery.replaceWith... which for
+ * some reason removes all event listeners, so isn't really an option.
+ *
+ * @param {lm.item.AbstractContentItem} oldChild
+ * @param {lm.item.AbstractContentItem} newChild
+ *
+ * @returns {void}
+ */
replaceChild: function (oldChild, newChild, _$destroyOldChild) {
newChild = this.layoutManager._$normalizeContentItem(newChild);
@@ -3293,23 +3291,23 @@
parentNode.replaceChild(newChild.element[0], oldChild.element[0]);
- /*
- * Optionally destroy the old content item
- */
+ /*
+ * Optionally destroy the old content item
+ */
if (_$destroyOldChild === true) {
oldChild.parent = null;
oldChild._$destroy();
}
- /*
- * Wire the new contentItem into the tree
- */
+ /*
+ * Wire the new contentItem into the tree
+ */
this.contentItems[index] = newChild;
newChild.parent = this;
- /*
- * Update tab reference
- */
+ /*
+ * Update tab reference
+ */
if (this.isStack) {
this.header.tabs[index].contentItem = newChild;
}
@@ -3322,33 +3320,33 @@
this.callDownwards('setSize');
},
- /**
- * Convenience method.
- * Shorthand for this.parent.removeChild( this )
- *
- * @returns {void}
- */
+ /**
+ * Convenience method.
+ * Shorthand for this.parent.removeChild( this )
+ *
+ * @returns {void}
+ */
remove: function () {
this.parent.removeChild(this);
},
- /**
- * Removes the component from the layout and creates a new
- * browser window with the component and its children inside
- *
- * @returns {lm.controls.BrowserPopout}
- */
+ /**
+ * Removes the component from the layout and creates a new
+ * browser window with the component and its children inside
+ *
+ * @returns {lm.controls.BrowserPopout}
+ */
popout: function () {
var browserPopout = this.layoutManager.createPopout(this);
this.emitBubblingEvent('stateChanged');
return browserPopout;
},
- /**
- * Maximises the Item or minimises it if it is already maximised
- *
- * @returns {void}
- */
+ /**
+ * Maximises the Item or minimises it if it is already maximised
+ *
+ * @returns {void}
+ */
toggleMaximise: function (e) {
e && e.preventDefault();
if (this.isMaximised === true) {
@@ -3361,11 +3359,11 @@
this.emitBubblingEvent('stateChanged');
},
- /**
- * Selects the item if it is not already selected
- *
- * @returns {void}
- */
+ /**
+ * Selects the item if it is not already selected
+ *
+ * @returns {void}
+ */
select: function () {
if (this.layoutManager.selectedItem !== this) {
this.layoutManager.selectItem(this, true);
@@ -3373,11 +3371,11 @@
}
},
- /**
- * De-selects the item if it is selected
- *
- * @returns {void}
- */
+ /**
+ * De-selects the item if it is selected
+ *
+ * @returns {void}
+ */
deselect: function () {
if (this.layoutManager.selectedItem === this) {
this.layoutManager.selectedItem = null;
@@ -3385,28 +3383,28 @@
}
},
- /**
- * Set this component's title
- *
- * @public
- * @param {String} title
- *
- * @returns {void}
- */
+ /**
+ * Set this component's title
+ *
+ * @public
+ * @param {String} title
+ *
+ * @returns {void}
+ */
setTitle: function (title) {
this.config.title = title;
this.emit('titleChanged', title);
this.emit('stateChanged');
},
- /**
- * Checks whether a provided id is present
- *
- * @public
- * @param {String} id
- *
- * @returns {Boolean} isPresent
- */
+ /**
+ * Checks whether a provided id is present
+ *
+ * @public
+ * @param {String} id
+ *
+ * @returns {Boolean} isPresent
+ */
hasId: function (id) {
if (!this.config.id) {
return false;
@@ -3417,15 +3415,15 @@
}
},
- /**
- * Adds an id. Adds it as a string if the component doesn't
- * have an id yet or creates/uses an array
- *
- * @public
- * @param {String} id
- *
- * @returns {void}
- */
+ /**
+ * Adds an id. Adds it as a string if the component doesn't
+ * have an id yet or creates/uses an array
+ *
+ * @public
+ * @param {String} id
+ *
+ * @returns {void}
+ */
addId: function (id) {
if (this.hasId(id)) {
return;
@@ -3440,15 +3438,15 @@
}
},
- /**
- * Removes an existing id. Throws an error
- * if the id is not present
- *
- * @public
- * @param {String} id
- *
- * @returns {void}
- */
+ /**
+ * Removes an existing id. Throws an error
+ * if the id is not present
+ *
+ * @public
+ * @param {String} id
+ *
+ * @returns {void}
+ */
removeId: function (id) {
if (!this.hasId(id)) {
throw new Error('Id not found');
@@ -3462,9 +3460,9 @@
}
},
- /****************************************
- * SELECTOR
- ****************************************/
+ /****************************************
+ * SELECTOR
+ ****************************************/
getItemsByFilter: function (filter) {
var result = [],
next = function (contentItem) {
@@ -3508,9 +3506,9 @@
return instances;
},
- /****************************************
- * PACKAGE PRIVATE
- ****************************************/
+ /****************************************
+ * PACKAGE PRIVATE
+ ****************************************/
_$getItemsByProperty: function (key, value) {
return this.getItemsByFilter(function (item) {
return item[key] === value;
@@ -3555,11 +3553,11 @@
}
},
- /**
- * Destroys this item ands its children
- *
- * @returns {void}
- */
+ /**
+ * Destroys this item ands its children
+ *
+ * @returns {void}
+ */
_$destroy: function () {
this.emitBubblingEvent('beforeItemDestroyed');
this.callDownwards('_$destroy', [], true, true);
@@ -3567,17 +3565,17 @@
this.emitBubblingEvent('itemDestroyed');
},
- /**
- * Returns the area the component currently occupies in the format
- *
- * {
- * x1: int
- * xy: int
- * y1: int
- * y2: int
- * contentItem: contentItem
- * }
- */
+ /**
+ * Returns the area the component currently occupies in the format
+ *
+ * {
+ * x1: int
+ * xy: int
+ * y1: int
+ * y2: int
+ * contentItem: contentItem
+ * }
+ */
_$getArea: function (element) {
element = element || this.element;
@@ -3595,17 +3593,17 @@
};
},
- /**
- * The tree of content items is created in two steps: First all content items are instantiated,
- * then init is called recursively from top to bottem. This is the basic init function,
- * it can be used, extended or overwritten by the content items
- *
- * Its behaviour depends on the content item
- *
- * @package private
- *
- * @returns {void}
- */
+ /**
+ * The tree of content items is created in two steps: First all content items are instantiated,
+ * then init is called recursively from top to bottem. This is the basic init function,
+ * it can be used, extended or overwritten by the content items
+ *
+ * Its behaviour depends on the content item
+ *
+ * @package private
+ *
+ * @returns {void}
+ */
_$init: function () {
var i;
this.setSize();
@@ -3619,26 +3617,26 @@
this.emitBubblingEvent(this.type + 'Created');
},
- /**
- * Emit an event that bubbles up the item tree.
- *
- * @param {String} name The name of the event
- *
- * @returns {void}
- */
+ /**
+ * Emit an event that bubbles up the item tree.
+ *
+ * @param {String} name The name of the event
+ *
+ * @returns {void}
+ */
emitBubblingEvent: function (name) {
var event = new lm.utils.BubblingEvent(name, this);
this.emit(name, event);
},
- /**
- * Private method, creates all content items for this node at initialisation time
- * PLEASE NOTE, please see addChild for adding contentItems add runtime
- * @private
- * @param {configuration item node} config
- *
- * @returns {void}
- */
+ /**
+ * Private method, creates all content items for this node at initialisation time
+ * PLEASE NOTE, please see addChild for adding contentItems add runtime
+ * @private
+ * @param {configuration item node} config
+ *
+ * @returns {void}
+ */
_createContentItems: function (config) {
var oContentItem, i;
@@ -3652,13 +3650,13 @@
}
},
- /**
- * Extends an item configuration node with default settings
- * @private
- * @param {configuration item node} config
- *
- * @returns {configuration item node} extended config
- */
+ /**
+ * Extends an item configuration node with default settings
+ * @private
+ * @param {configuration item node} config
+ *
+ * @returns {configuration item node} extended config
+ */
_extendItemNode: function (config) {
for (var key in lm.config.itemDefaultConfig) {
@@ -3670,26 +3668,26 @@
return config;
},
- /**
- * Called for every event on the item tree. Decides whether the event is a bubbling
- * event and propagates it to its parent
- *
- * @param {String} name the name of the event
- * @param {lm.utils.BubblingEvent} event
- *
- * @returns {void}
- */
+ /**
+ * Called for every event on the item tree. Decides whether the event is a bubbling
+ * event and propagates it to its parent
+ *
+ * @param {String} name the name of the event
+ * @param {lm.utils.BubblingEvent} event
+ *
+ * @returns {void}
+ */
_propagateEvent: function (name, event) {
if (event instanceof lm.utils.BubblingEvent &&
event.isPropagationStopped === false &&
this.isInitialised === true) {
- /**
- * In some cases (e.g. if an element is created from a DragSource) it
- * doesn't have a parent and is not below root. If that's the case
- * propagate the bubbling event from the top level of the substree directly
- * to the layoutManager
- */
+ /**
+ * In some cases (e.g. if an element is created from a DragSource) it
+ * doesn't have a parent and is not below root. If that's the case
+ * propagate the bubbling event from the top level of the substree directly
+ * to the layoutManager
+ */
if (this.isRoot === false && this.parent) {
this.parent.emit.apply(this.parent, Array.prototype.slice.call(arguments, 0));
} else {
@@ -3698,16 +3696,16 @@
}
},
- /**
- * All raw events bubble up to the root element. Some events that
- * are propagated to - and emitted by - the layoutManager however are
- * only string-based, batched and sanitized to make them more usable
- *
- * @param {String} name the name of the event
- *
- * @private
- * @returns {void}
- */
+ /**
+ * All raw events bubble up to the root element. Some events that
+ * are propagated to - and emitted by - the layoutManager however are
+ * only string-based, batched and sanitized to make them more usable
+ *
+ * @param {String} name the name of the event
+ *
+ * @private
+ * @returns {void}
+ */
_scheduleEventPropagationToLayoutManager: function (name, event) {
if (lm.utils.indexOf(name, this._throttledEvents) === -1) {
this.layoutManager.emit(name, event.origin);
@@ -3720,25 +3718,25 @@
},
- /**
- * Callback for events scheduled by _scheduleEventPropagationToLayoutManager
- *
- * @param {String} name the name of the event
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Callback for events scheduled by _scheduleEventPropagationToLayoutManager
+ *
+ * @param {String} name the name of the event
+ *
+ * @private
+ * @returns {void}
+ */
_propagateEventToLayoutManager: function (name, event) {
this._pendingEventPropagations[name] = false;
this.layoutManager.emit(name, event);
}
});
- /**
- * @param {[type]} layoutManager [description]
- * @param {[type]} config [description]
- * @param {[type]} parent [description]
- */
+ /**
+ * @param {[type]} layoutManager [description]
+ * @param {[type]} config [description]
+ * @param {[type]} parent [description]
+ */
lm.items.Component = function (layoutManager, config, parent) {
lm.items.AbstractContentItem.call(this, layoutManager, config, parent);
@@ -3798,11 +3796,11 @@
lm.items.AbstractContentItem.prototype._$destroy.call(this);
},
- /**
- * Dragging onto a component directly is not an option
- *
- * @returns null
- */
+ /**
+ * Dragging onto a component directly is not an option
+ *
+ * @returns null
+ */
_$getArea: function () {
return null;
}
@@ -3841,9 +3839,9 @@
this.element.width(width);
this.element.height(height);
- /*
- * Root can be empty
- */
+ /*
+ * Root can be empty
+ */
if (this.contentItems[0]) {
this.contentItems[0].element.width(width);
this.contentItems[0].element.height(height);
@@ -3917,18 +3915,18 @@
lm.utils.copy(lm.items.RowOrColumn.prototype, {
- /**
- * Add a new contentItem to the Row or Column
- *
- * @param {lm.item.AbstractContentItem} contentItem
- * @param {[int]} index The position of the new item within the Row or Column.
- * If no index is provided the item will be added to the end
- * @param {[bool]} _$suspendResize If true the items won't be resized. This will leave the item in
- * an inconsistent state and is only intended to be used if multiple
- * children need to be added in one go and resize is called afterwards
- *
- * @returns {void}
- */
+ /**
+ * Add a new contentItem to the Row or Column
+ *
+ * @param {lm.item.AbstractContentItem} contentItem
+ * @param {[int]} index The position of the new item within the Row or Column.
+ * If no index is provided the item will be added to the end
+ * @param {[bool]} _$suspendResize If true the items won't be resized. This will leave the item in
+ * an inconsistent state and is only intended to be used if multiple
+ * children need to be added in one go and resize is called afterwards
+ *
+ * @returns {void}
+ */
addChild: function (contentItem, index, _$suspendResize) {
var newItemSize, itemSize, i, splitterElement;
@@ -3986,14 +3984,14 @@
},
- /**
- * Removes a child of this element
- *
- * @param {lm.items.AbstractContentItem} contentItem
- * @param {boolean} keepChild If true the child will be removed, but not destroyed
- *
- * @returns {void}
- */
+ /**
+ * Removes a child of this element
+ *
+ * @param {lm.items.AbstractContentItem} contentItem
+ * @param {boolean} keepChild If true the child will be removed, but not destroyed
+ *
+ * @returns {void}
+ */
removeChild: function (contentItem, keepChild) {
var removedItemSize = contentItem.config[this._dimension],
index = lm.utils.indexOf(contentItem, this.contentItems),
@@ -4005,10 +4003,10 @@
throw new Error('Can\'t remove child. ContentItem is not child of this Row or Column');
}
- /**
- * Remove the splitter before the item or after if the item happens
- * to be the first in the row/column
- */
+ /**
+ * Remove the splitter before the item or after if the item happens
+ * to be the first in the row/column
+ */
if (this._splitter[splitterIndex]) {
this._splitter[splitterIndex]._$destroy();
this._splitter.splice(splitterIndex, 1);
@@ -4019,9 +4017,9 @@
if (this.contentItems[i].config.fixed)
fixedItemSize += this.contentItems[i].config[this._dimension];
}
- /**
- * Allocate the space that the removed item occupied to the remaining items
- */
+ /**
+ * Allocate the space that the removed item occupied to the remaining items
+ */
for (i = 0; i < this.contentItems.length; i++) {
if (this.contentItems[i].config.fixed)
;
@@ -4044,14 +4042,14 @@
}
},
- /**
- * Replaces a child of this Row or Column with another contentItem
- *
- * @param {lm.items.AbstractContentItem} oldChild
- * @param {lm.items.AbstractContentItem} newChild
- *
- * @returns {void}
- */
+ /**
+ * Replaces a child of this Row or Column with another contentItem
+ *
+ * @param {lm.items.AbstractContentItem} oldChild
+ * @param {lm.items.AbstractContentItem} newChild
+ *
+ * @returns {void}
+ */
replaceChild: function (oldChild, newChild) {
var size = oldChild.config[this._dimension];
lm.items.AbstractContentItem.prototype.replaceChild.call(this, oldChild, newChild);
@@ -4060,11 +4058,11 @@
this.emitBubblingEvent('stateChanged');
},
- /**
- * Called whenever the dimensions of this item or one of its parents change
- *
- * @returns {void}
- */
+ /**
+ * Called whenever the dimensions of this item or one of its parents change
+ *
+ * @returns {void}
+ */
setSize: function () {
if (this.contentItems.length > 0) {
this._calculateRelativeSizes();
@@ -4074,15 +4072,15 @@
this.emit('resize');
},
- /**
- * Invoked recursively by the layout manager. AbstractContentItem.init appends
- * the contentItem's DOM elements to the container, RowOrColumn init adds splitters
- * in between them
- *
- * @package private
- * @override AbstractContentItem._$init
- * @returns {void}
- */
+ /**
+ * Invoked recursively by the layout manager. AbstractContentItem.init appends
+ * the contentItem's DOM elements to the container, RowOrColumn init adds splitters
+ * in between them
+ *
+ * @package private
+ * @override AbstractContentItem._$init
+ * @returns {void}
+ */
_$init: function () {
if (this.isInitialised === true) return;
@@ -4095,15 +4093,15 @@
}
},
- /**
- * Turns the relative sizes calculated by _calculateRelativeSizes into
- * absolute pixel values and applies them to the children's DOM elements
- *
- * Assigns additional pixels to counteract Math.floor
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Turns the relative sizes calculated by _calculateRelativeSizes into
+ * absolute pixel values and applies them to the children's DOM elements
+ *
+ * Assigns additional pixels to counteract Math.floor
+ *
+ * @private
+ * @returns {void}
+ */
_setAbsoluteSizes: function () {
var i,
sizeData = this._calculateAbsoluteSizes();
@@ -4123,10 +4121,10 @@
}
},
- /**
- * Calculates the absolute sizes of all of the children of this Item.
- * @returns {object} - Set with absolute sizes and additional pixels.
- */
+ /**
+ * Calculates the absolute sizes of all of the children of this Item.
+ * @returns {object} - Set with absolute sizes and additional pixels.
+ */
_calculateAbsoluteSizes: function () {
var i,
totalSplitterSize = (this.contentItems.length - 1) * this._splitterSize,
@@ -4164,27 +4162,27 @@
};
},
- /**
- * Calculates the relative sizes of all children of this Item. The logic
- * is as follows:
- *
- * - Add up the total size of all items that have a configured size
- *
- * - If the total == 100 (check for floating point errors)
- * Excellent, job done
- *
- * - If the total is > 100,
- * set the size of items without set dimensions to 1/3 and add this to the total
- * set the size off all items so that the total is hundred relative to their original size
- *
- * - If the total is < 100
- * If there are items without set dimensions, distribute the remainder to 100 evenly between them
- * If there are no items without set dimensions, increase all items sizes relative to
- * their original size so that they add up to 100
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Calculates the relative sizes of all children of this Item. The logic
+ * is as follows:
+ *
+ * - Add up the total size of all items that have a configured size
+ *
+ * - If the total == 100 (check for floating point errors)
+ * Excellent, job done
+ *
+ * - If the total is > 100,
+ * set the size of items without set dimensions to 1/3 and add this to the total
+ * set the size off all items so that the total is hundred relative to their original size
+ *
+ * - If the total is < 100
+ * If there are items without set dimensions, distribute the remainder to 100 evenly between them
+ * If there are no items without set dimensions, increase all items sizes relative to
+ * their original size so that they add up to 100
+ *
+ * @private
+ * @returns {void}
+ */
_calculateRelativeSizes: function () {
var i,
@@ -4200,17 +4198,17 @@
}
}
- /**
- * Everything adds up to hundred, all good :-)
- */
+ /**
+ * Everything adds up to hundred, all good :-)
+ */
if (Math.round(total) === 100) {
this._respectMinItemWidth();
return;
}
- /**
- * Allocate the remaining size to the items without a set dimension
- */
+ /**
+ * Allocate the remaining size to the items without a set dimension
+ */
if (Math.round(total) < 100 && itemsWithoutSetDimension.length > 0) {
for (i = 0; i < itemsWithoutSetDimension.length; i++) {
itemsWithoutSetDimension[i].config[dimension] = (100 - total) / itemsWithoutSetDimension.length;
@@ -4219,12 +4217,12 @@
return;
}
- /**
- * If the total is > 100, but there are also items without a set dimension left, assing 50
- * as their dimension and add it to the total
- *
- * This will be reset in the next step
- */
+ /**
+ * If the total is > 100, but there are also items without a set dimension left, assing 50
+ * as their dimension and add it to the total
+ *
+ * This will be reset in the next step
+ */
if (Math.round(total) > 100) {
for (i = 0; i < itemsWithoutSetDimension.length; i++) {
itemsWithoutSetDimension[i].config[dimension] = 50;
@@ -4232,9 +4230,9 @@
}
}
- /**
- * Set every items size relative to 100 relative to its size to total
- */
+ /**
+ * Set every items size relative to 100 relative to its size to total
+ */
for (i = 0; i < this.contentItems.length; i++) {
this.contentItems[i].config[dimension] = (this.contentItems[i].config[dimension] / total) * 100;
}
@@ -4242,10 +4240,10 @@
this._respectMinItemWidth();
},
- /**
- * Adjusts the column widths to respect the dimensions minItemWidth if set.
- * @returns {}
- */
+ /**
+ * Adjusts the column widths to respect the dimensions minItemWidth if set.
+ * @returns {}
+ */
_respectMinItemWidth: function () {
var minItemWidth = this.layoutManager.config.dimensions ? (this.layoutManager.config.dimensions.minItemWidth || 0) : 0,
sizeData = null,
@@ -4266,9 +4264,9 @@
sizeData = this._calculateAbsoluteSizes();
- /**
- * Figure out how much we are under the min item size total and how much room we have to use.
- */
+ /**
+ * Figure out how much we are under the min item size total and how much room we have to use.
+ */
for (var i = 0; i < this.contentItems.length; i++) {
contentItem = this.contentItems[i];
@@ -4288,16 +4286,16 @@
allEntries.push(entry);
}
- /**
- * If there is nothing under min, or there is not enough over to make up the difference, do nothing.
- */
+ /**
+ * If there is nothing under min, or there is not enough over to make up the difference, do nothing.
+ */
if (totalUnderMin === 0 || totalUnderMin > totalOverMin) {
return;
}
- /**
- * Evenly reduce all columns that are over the min item width to make up the difference.
- */
+ /**
+ * Evenly reduce all columns that are over the min item width to make up the difference.
+ */
reducePercent = totalUnderMin / totalOverMin;
remainingWidth = totalUnderMin;
for (i = 0; i < entriesOverMin.length; i++) {
@@ -4307,31 +4305,31 @@
entry.width -= reducedWidth;
}
- /**
- * Take anything remaining from the last item.
- */
+ /**
+ * Take anything remaining from the last item.
+ */
if (remainingWidth !== 0) {
allEntries[allEntries.length - 1].width -= remainingWidth;
}
- /**
- * Set every items size relative to 100 relative to its size to total
- */
+ /**
+ * Set every items size relative to 100 relative to its size to total
+ */
for (i = 0; i < this.contentItems.length; i++) {
this.contentItems[i].config.width = (allEntries[i].width / sizeData.totalWidth) * 100;
}
},
- /**
- * Instantiates a new lm.controls.Splitter, binds events to it and adds
- * it to the array of splitters at the position specified as the index argument
- *
- * What it doesn't do though is append the splitter to the DOM
- *
- * @param {Int} index The position of the splitter
- *
- * @returns {lm.controls.Splitter}
- */
+ /**
+ * Instantiates a new lm.controls.Splitter, binds events to it and adds
+ * it to the array of splitters at the position specified as the index argument
+ *
+ * What it doesn't do though is append the splitter to the DOM
+ *
+ * @param {Int} index The position of the splitter
+ *
+ * @returns {lm.controls.Splitter}
+ */
_createSplitter: function (index) {
var splitter;
splitter = new lm.controls.Splitter(this._isColumn, this._splitterSize, this._splitterGrabSize);
@@ -4342,16 +4340,16 @@
return splitter;
},
- /**
- * Locates the instance of lm.controls.Splitter in the array of
- * registered splitters and returns a map containing the contentItem
- * before and after the splitters, both of which are affected if the
- * splitter is moved
- *
- * @param {lm.controls.Splitter} splitter
- *
- * @returns {Object} A map of contentItems that the splitter affects
- */
+ /**
+ * Locates the instance of lm.controls.Splitter in the array of
+ * registered splitters and returns a map containing the contentItem
+ * before and after the splitters, both of which are affected if the
+ * splitter is moved
+ *
+ * @param {lm.controls.Splitter} splitter
+ *
+ * @returns {Object} A map of contentItems that the splitter affects
+ */
_getItemsForSplitter: function (splitter) {
var index = lm.utils.indexOf(splitter, this._splitter);
@@ -4361,11 +4359,11 @@
};
},
- /**
- * Gets the minimum dimensions for the given item configuration array
- * @param item
- * @private
- */
+ /**
+ * Gets the minimum dimensions for the given item configuration array
+ * @param item
+ * @private
+ */
_getMinimumDimensions: function (arr) {
var minWidth = 0, minHeight = 0;
@@ -4377,14 +4375,14 @@
return { horizontal: minWidth, vertical: minHeight };
},
- /**
- * Invoked when a splitter's dragListener fires dragStart. Calculates the splitters
- * movement area once (so that it doesn't need calculating on every mousemove event)
- *
- * @param {lm.controls.Splitter} splitter
- *
- * @returns {void}
- */
+ /**
+ * Invoked when a splitter's dragListener fires dragStart. Calculates the splitters
+ * movement area once (so that it doesn't need calculating on every mousemove event)
+ *
+ * @param {lm.controls.Splitter} splitter
+ *
+ * @returns {void}
+ */
_onSplitterDragStart: function (splitter) {
var items = this._getItemsForSplitter(splitter),
minSize = this.layoutManager.config.dimensions[this._isColumn ? 'minItemHeight' : 'minItemWidth'];
@@ -4400,16 +4398,16 @@
this._splitterMaxPosition = items.after.element[this._dimension]() - (afterMinSize || minSize);
},
- /**
- * Invoked when a splitter's DragListener fires drag. Updates the splitters DOM position,
- * but not the sizes of the elements the splitter controls in order to minimize resize events
- *
- * @param {lm.controls.Splitter} splitter
- * @param {Int} offsetX Relative pixel values to the splitters original position. Can be negative
- * @param {Int} offsetY Relative pixel values to the splitters original position. Can be negative
- *
- * @returns {void}
- */
+ /**
+ * Invoked when a splitter's DragListener fires drag. Updates the splitters DOM position,
+ * but not the sizes of the elements the splitter controls in order to minimize resize events
+ *
+ * @param {lm.controls.Splitter} splitter
+ * @param {Int} offsetX Relative pixel values to the splitters original position. Can be negative
+ * @param {Int} offsetY Relative pixel values to the splitters original position. Can be negative
+ *
+ * @returns {void}
+ */
_onSplitterDrag: function (splitter, offsetX, offsetY) {
var offset = this._isColumn ? offsetY : offsetX;
@@ -4419,15 +4417,15 @@
}
},
- /**
- * Invoked when a splitter's DragListener fires dragStop. Resets the splitters DOM position,
- * and applies the new sizes to the elements before and after the splitter and their children
- * on the next animation frame
- *
- * @param {lm.controls.Splitter} splitter
- *
- * @returns {void}
- */
+ /**
+ * Invoked when a splitter's DragListener fires dragStop. Resets the splitters DOM position,
+ * and applies the new sizes to the elements before and after the splitter and their children
+ * on the next animation frame
+ *
+ * @param {lm.controls.Splitter} splitter
+ *
+ * @returns {void}
+ */
_onSplitterDragStop: function (splitter) {
var items = this._getItemsForSplitter(splitter),
@@ -4575,13 +4573,13 @@
this.emitBubblingEvent('stateChanged');
},
- /**
- * Validates that the stack is still closable or not. If a stack is able
- * to close, but has a non closable component added to it, the stack is no
- * longer closable until all components are closable.
- *
- * @returns {void}
- */
+ /**
+ * Validates that the stack is still closable or not. If a stack is able
+ * to close, but has a non closable component added to it, the stack is no
+ * longer closable until all components are closable.
+ *
+ * @returns {void}
+ */
_$validateClosability: function () {
var contentItem,
isClosable,
@@ -4607,51 +4605,51 @@
},
- /**
- * Ok, this one is going to be the tricky one: The user has dropped {contentItem} onto this stack.
- *
- * It was dropped on either the stacks header or the top, right, bottom or left bit of the content area
- * (which one of those is stored in this._dropSegment). Now, if the user has dropped on the header the case
- * is relatively clear: We add the item to the existing stack... job done (might be good to have
- * tab reordering at some point, but lets not sweat it right now)
- *
- * If the item was dropped on the content part things are a bit more complicated. If it was dropped on either the
- * top or bottom region we need to create a new column and place the items accordingly.
- * Unless, of course if the stack is already within a column... in which case we want
- * to add the newly created item to the existing column...
- * either prepend or append it, depending on wether its top or bottom.
- *
- * Same thing for rows and left / right drop segments... so in total there are 9 things that can potentially happen
- * (left, top, right, bottom) * is child of the right parent (row, column) + header drop
- *
- * @param {lm.item} contentItem
- *
- * @returns {void}
- */
+ /**
+ * Ok, this one is going to be the tricky one: The user has dropped {contentItem} onto this stack.
+ *
+ * It was dropped on either the stacks header or the top, right, bottom or left bit of the content area
+ * (which one of those is stored in this._dropSegment). Now, if the user has dropped on the header the case
+ * is relatively clear: We add the item to the existing stack... job done (might be good to have
+ * tab reordering at some point, but lets not sweat it right now)
+ *
+ * If the item was dropped on the content part things are a bit more complicated. If it was dropped on either the
+ * top or bottom region we need to create a new column and place the items accordingly.
+ * Unless, of course if the stack is already within a column... in which case we want
+ * to add the newly created item to the existing column...
+ * either prepend or append it, depending on wether its top or bottom.
+ *
+ * Same thing for rows and left / right drop segments... so in total there are 9 things that can potentially happen
+ * (left, top, right, bottom) * is child of the right parent (row, column) + header drop
+ *
+ * @param {lm.item} contentItem
+ *
+ * @returns {void}
+ */
_$onDrop: function (contentItem) {
- /*
- * The item was dropped on the header area. Just add it as a child of this stack and
- * get the hell out of this logic
- */
+ /*
+ * The item was dropped on the header area. Just add it as a child of this stack and
+ * get the hell out of this logic
+ */
if (this._dropSegment === 'header') {
this._resetHeaderDropZone();
this.addChild(contentItem, this._dropIndex);
return;
}
- /*
- * The stack is empty. Let's just add the element.
- */
+ /*
+ * The stack is empty. Let's just add the element.
+ */
if (this._dropSegment === 'body') {
this.addChild(contentItem);
return;
}
- /*
- * The item was dropped on the top-, left-, bottom- or right- part of the content. Let's
- * aggregate some conditions to make the if statements later on more readable
- */
+ /*
+ * The item was dropped on the top-, left-, bottom- or right- part of the content. Let's
+ * aggregate some conditions to make the if statements later on more readable
+ */
var isVertical = this._dropSegment === 'top' || this._dropSegment === 'bottom',
isHorizontal = this._dropSegment === 'left' || this._dropSegment === 'right',
insertBefore = this._dropSegment === 'top' || this._dropSegment === 'left',
@@ -4662,9 +4660,9 @@
stack,
rowOrColumn;
- /*
- * The content item can be either a component or a stack. If it is a component, wrap it into a stack
- */
+ /*
+ * The content item can be either a component or a stack. If it is a component, wrap it into a stack
+ */
if (contentItem.isComponent) {
stack = this.layoutManager.createContentItem({
type: 'stack',
@@ -4675,20 +4673,20 @@
contentItem = stack;
}
- /*
- * If the item is dropped on top or bottom of a column or left and right of a row, it's already
- * layd out in the correct way. Just add it as a child
- */
+ /*
+ * If the item is dropped on top or bottom of a column or left and right of a row, it's already
+ * layd out in the correct way. Just add it as a child
+ */
if (hasCorrectParent) {
index = lm.utils.indexOf(this, this.parent.contentItems);
this.parent.addChild(contentItem, insertBefore ? index : index + 1, true);
this.config[dimension] *= 0.5;
contentItem.config[dimension] = this.config[dimension];
this.parent.callDownwards('setSize');
- /*
- * This handles items that are dropped on top or bottom of a row or left / right of a column. We need
- * to create the appropriate contentItem for them to live in
- */
+ /*
+ * This handles items that are dropped on top or bottom of a row or left / right of a column. We need
+ * to create the appropriate contentItem for them to live in
+ */
} else {
type = isVertical ? 'column' : 'row';
rowOrColumn = this.layoutManager.createContentItem({ type: type }, this);
@@ -4703,15 +4701,15 @@
}
},
- /**
- * If the user hovers above the header part of the stack, indicate drop positions for tabs.
- * otherwise indicate which segment of the body the dragged item would be dropped on
- *
- * @param {Int} x Absolute Screen X
- * @param {Int} y Absolute Screen Y
- *
- * @returns {void}
- */
+ /**
+ * If the user hovers above the header part of the stack, indicate drop positions for tabs.
+ * otherwise indicate which segment of the body the dragged item would be dropped on
+ *
+ * @param {Int} x Absolute Screen X
+ * @param {Int} y Absolute Screen Y
+ *
+ * @returns {void}
+ */
_$highlightDropZone: function (x, y) {
var segment, area;
@@ -4761,17 +4759,17 @@
}
};
- /**
- * If this Stack is a parent to rows, columns or other stacks only its
- * header is a valid dropzone.
- */
+ /**
+ * If this Stack is a parent to rows, columns or other stacks only its
+ * header is a valid dropzone.
+ */
if (this._activeContentItem && this._activeContentItem.isComponent === false) {
return headerArea;
}
- /**
- * Highlight the entire body if the stack is empty
- */
+ /**
+ * Highlight the entire body if the stack is empty
+ */
if (this.contentItems.length === 0) {
this._contentAreaDimensions.body = {
@@ -4875,7 +4873,7 @@
this.layoutManager.dropTargetIndicator.highlightArea({
x1: headerOffset.left,
x2: headerOffset.left + 100,
- y1: headerOffset.top + this.header.element.height() - 20,
+ y1: headerOffset.top + this.header.element.height() - 25,
y2: headerOffset.top + this.header.element.height()
});
@@ -4971,13 +4969,13 @@
lm.utils.BubblingEvent.prototype.stopPropagation = function () {
this.isPropagationStopped = true;
};
- /**
- * Minifies and unminifies configs by replacing frequent keys
- * and values with one letter substitutes. Config options must
- * retain array position/index, add new options at the end.
- *
- * @constructor
- */
+ /**
+ * Minifies and unminifies configs by replacing frequent keys
+ * and values with one letter substitutes. Config options must
+ * retain array position/index, add new options at the end.
+ *
+ * @constructor
+ */
lm.utils.ConfigMinifier = function () {
this._keys = [
'settings',
@@ -5037,154 +5035,154 @@
lm.utils.copy(lm.utils.ConfigMinifier.prototype, {
- /**
- * Takes a GoldenLayout configuration object and
- * replaces its keys and values recursively with
- * one letter counterparts
- *
- * @param {Object} config A GoldenLayout config object
- *
- * @returns {Object} minified config
- */
+ /**
+ * Takes a GoldenLayout configuration object and
+ * replaces its keys and values recursively with
+ * one letter counterparts
+ *
+ * @param {Object} config A GoldenLayout config object
+ *
+ * @returns {Object} minified config
+ */
minifyConfig: function (config) {
var min = {};
this._nextLevel(config, min, '_min');
return min;
},
- /**
- * Takes a configuration Object that was previously minified
- * using minifyConfig and returns its original version
- *
- * @param {Object} minifiedConfig
- *
- * @returns {Object} the original configuration
- */
+ /**
+ * Takes a configuration Object that was previously minified
+ * using minifyConfig and returns its original version
+ *
+ * @param {Object} minifiedConfig
+ *
+ * @returns {Object} the original configuration
+ */
unminifyConfig: function (minifiedConfig) {
var orig = {};
this._nextLevel(minifiedConfig, orig, '_max');
return orig;
},
- /**
- * Recursive function, called for every level of the config structure
- *
- * @param {Array|Object} orig
- * @param {Array|Object} min
- * @param {String} translationFn
- *
- * @returns {void}
- */
+ /**
+ * Recursive function, called for every level of the config structure
+ *
+ * @param {Array|Object} orig
+ * @param {Array|Object} min
+ * @param {String} translationFn
+ *
+ * @returns {void}
+ */
_nextLevel: function (from, to, translationFn) {
var key, minKey;
for (key in from) {
- /**
- * For in returns array indices as keys, so let's cast them to numbers
- */
+ /**
+ * For in returns array indices as keys, so let's cast them to numbers
+ */
if (from instanceof Array) key = parseInt(key, 10);
- /**
- * In case something has extended Object prototypes
- */
+ /**
+ * In case something has extended Object prototypes
+ */
if (!from.hasOwnProperty(key)) continue;
- /**
- * Translate the key to a one letter substitute
- */
+ /**
+ * Translate the key to a one letter substitute
+ */
minKey = this[translationFn](key, this._keys);
- /**
- * For Arrays and Objects, create a new Array/Object
- * on the minified object and recurse into it
- */
+ /**
+ * For Arrays and Objects, create a new Array/Object
+ * on the minified object and recurse into it
+ */
if (typeof from[key] === 'object') {
to[minKey] = from[key] instanceof Array ? [] : {};
this._nextLevel(from[key], to[minKey], translationFn);
- /**
- * For primitive values (Strings, Numbers, Boolean etc.)
- * minify the value
- */
+ /**
+ * For primitive values (Strings, Numbers, Boolean etc.)
+ * minify the value
+ */
} else {
to[minKey] = this[translationFn](from[key], this._values);
}
}
},
- /**
- * Minifies value based on a dictionary
- *
- * @param {String|Boolean} value
- * @param {Array<String|Boolean>} dictionary
- *
- * @returns {String} The minified version
- */
+ /**
+ * Minifies value based on a dictionary
+ *
+ * @param {String|Boolean} value
+ * @param {Array<String|Boolean>} dictionary
+ *
+ * @returns {String} The minified version
+ */
_min: function (value, dictionary) {
- /**
- * If a value actually is a single character, prefix it
- * with ___ to avoid mistaking it for a minification code
- */
+ /**
+ * If a value actually is a single character, prefix it
+ * with ___ to avoid mistaking it for a minification code
+ */
if (typeof value === 'string' && value.length === 1) {
return '___' + value;
}
var index = lm.utils.indexOf(value, dictionary);
- /**
- * value not found in the dictionary, return it unmodified
- */
+ /**
+ * value not found in the dictionary, return it unmodified
+ */
if (index === -1) {
return value;
- /**
- * value found in dictionary, return its base36 counterpart
- */
+ /**
+ * value found in dictionary, return its base36 counterpart
+ */
} else {
return index.toString(36);
}
},
_max: function (value, dictionary) {
- /**
- * value is a single character. Assume that it's a translation
- * and return the original value from the dictionary
- */
+ /**
+ * value is a single character. Assume that it's a translation
+ * and return the original value from the dictionary
+ */
if (typeof value === 'string' && value.length === 1) {
return dictionary[parseInt(value, 36)];
}
- /**
- * value originally was a single character and was prefixed with ___
- * to avoid mistaking it for a translation. Remove the prefix
- * and return the original character
- */
+ /**
+ * value originally was a single character and was prefixed with ___
+ * to avoid mistaking it for a translation. Remove the prefix
+ * and return the original character
+ */
if (typeof value === 'string' && value.substr(0, 3) === '___') {
return value[3];
}
- /**
- * value was not minified
- */
+ /**
+ * value was not minified
+ */
return value;
}
});
- /**
- * An EventEmitter singleton that propagates events
- * across multiple windows. This is a little bit trickier since
- * windows are allowed to open childWindows in their own right
- *
- * This means that we deal with a tree of windows. Hence the rules for event propagation are:
- *
- * - Propagate events from this layout to both parents and children
- * - Propagate events from parent to this and children
- * - Propagate events from children to the other children (but not the emitting one) and the parent
- *
- * @constructor
- *
- * @param {lm.LayoutManager} layoutManager
- */
+ /**
+ * An EventEmitter singleton that propagates events
+ * across multiple windows. This is a little bit trickier since
+ * windows are allowed to open childWindows in their own right
+ *
+ * This means that we deal with a tree of windows. Hence the rules for event propagation are:
+ *
+ * - Propagate events from this layout to both parents and children
+ * - Propagate events from parent to this and children
+ * - Propagate events from children to the other children (but not the emitting one) and the parent
+ *
+ * @constructor
+ *
+ * @param {lm.LayoutManager} layoutManager
+ */
lm.utils.EventHub = function (layoutManager) {
lm.utils.EventEmitter.call(this);
this._layoutManager = layoutManager;
@@ -5195,15 +5193,15 @@
$(window).on('gl_child_event', this._boundOnEventFromChild);
};
- /**
- * Called on every event emitted on this eventHub, regardles of origin.
- *
- * @private
- *
- * @param {Mixed}
- *
- * @returns {void}
- */
+ /**
+ * Called on every event emitted on this eventHub, regardles of origin.
+ *
+ * @private
+ *
+ * @param {Mixed}
+ *
+ * @returns {void}
+ */
lm.utils.EventHub.prototype._onEventFromThis = function () {
var args = Array.prototype.slice.call(arguments);
@@ -5217,40 +5215,40 @@
this._childEventSource = null;
};
- /**
- * Called by the parent layout.
- *
- * @param {Array} args Event name + arguments
- *
- * @returns {void}
- */
+ /**
+ * Called by the parent layout.
+ *
+ * @param {Array} args Event name + arguments
+ *
+ * @returns {void}
+ */
lm.utils.EventHub.prototype._$onEventFromParent = function (args) {
this._dontPropagateToParent = args[0];
this.emit.apply(this, args);
};
- /**
- * Callback for child events raised on the window
- *
- * @param {DOMEvent} event
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Callback for child events raised on the window
+ *
+ * @param {DOMEvent} event
+ * @private
+ *
+ * @returns {void}
+ */
lm.utils.EventHub.prototype._onEventFromChild = function (event) {
this._childEventSource = event.originalEvent.__gl;
this.emit.apply(this, event.originalEvent.__glArgs);
};
- /**
- * Propagates the event to the parent by emitting
- * it on the parent's DOM window
- *
- * @param {Array} args Event name + arguments
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Propagates the event to the parent by emitting
+ * it on the parent's DOM window
+ *
+ * @param {Array} args Event name + arguments
+ * @private
+ *
+ * @returns {void}
+ */
lm.utils.EventHub.prototype._propagateToParent = function (args) {
var event,
eventName = 'gl_child_event';
@@ -5274,14 +5272,14 @@
}
};
- /**
- * Propagate events to children
- *
- * @param {Array} args Event name + arguments
- * @private
- *
- * @returns {void}
- */
+ /**
+ * Propagate events to children
+ *
+ * @param {Array} args Event name + arguments
+ * @private
+ *
+ * @returns {void}
+ */
lm.utils.EventHub.prototype._propagateToChildren = function (args) {
var childGl, i;
@@ -5295,25 +5293,25 @@
};
- /**
- * Destroys the EventHub
- *
- * @public
- * @returns {void}
- */
+ /**
+ * Destroys the EventHub
+ *
+ * @public
+ * @returns {void}
+ */
lm.utils.EventHub.prototype.destroy = function () {
$(window).off('gl_child_event', this._boundOnEventFromChild);
};
- /**
- * A specialised GoldenLayout component that binds GoldenLayout container
- * lifecycle events to react components
- *
- * @constructor
- *
- * @param {lm.container.ItemContainer} container
- * @param {Object} state state is not required for react components
- */
+ /**
+ * A specialised GoldenLayout component that binds GoldenLayout container
+ * lifecycle events to react components
+ *
+ * @constructor
+ *
+ * @param {lm.container.ItemContainer} container
+ * @param {Object} state state is not required for react components
+ */
lm.utils.ReactComponentHandler = function (container, state) {
this._reactComponent = null;
this._originalComponentWillUpdate = null;
@@ -5326,15 +5324,15 @@
lm.utils.copy(lm.utils.ReactComponentHandler.prototype, {
- /**
- * Creates the react class and component and hydrates it with
- * the initial state - if one is present
- *
- * By default, react's getInitialState will be used
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Creates the react class and component and hydrates it with
+ * the initial state - if one is present
+ *
+ * By default, react's getInitialState will be used
+ *
+ * @private
+ * @returns {void}
+ */
_render: function () {
this._reactComponent = ReactDOM.render(this._getReactComponent(), this._container.getElement()[0]);
this._originalComponentWillUpdate = this._reactComponent.componentWillUpdate || function () {
@@ -5345,36 +5343,36 @@
}
},
- /**
- * Removes the component from the DOM and thus invokes React's unmount lifecycle
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Removes the component from the DOM and thus invokes React's unmount lifecycle
+ *
+ * @private
+ * @returns {void}
+ */
_destroy: function () {
ReactDOM.unmountComponentAtNode(this._container.getElement()[0]);
this._container.off('open', this._render, this);
this._container.off('destroy', this._destroy, this);
},
- /**
- * Hooks into React's state management and applies the componentstate
- * to GoldenLayout
- *
- * @private
- * @returns {void}
- */
+ /**
+ * Hooks into React's state management and applies the componentstate
+ * to GoldenLayout
+ *
+ * @private
+ * @returns {void}
+ */
_onUpdate: function (nextProps, nextState) {
this._container.setState(nextState);
this._originalComponentWillUpdate.call(this._reactComponent, nextProps, nextState);
},
- /**
- * Retrieves the react class from GoldenLayout's registry
- *
- * @private
- * @returns {React.Class}
- */
+ /**
+ * Retrieves the react class from GoldenLayout's registry
+ *
+ * @private
+ * @returns {React.Class}
+ */
_getReactClass: function () {
var componentName = this._container._config.component;
var reactClass;
@@ -5393,12 +5391,12 @@
return reactClass;
},
- /**
- * Copies and extends the properties array and returns the React element
- *
- * @private
- * @returns {React.Element}
- */
+ /**
+ * Copies and extends the properties array and returns the React element
+ *
+ * @private
+ * @returns {React.Element}
+ */
_getReactComponent: function () {
var defaultProps = {
glEventHub: this._container.layoutManager.eventHub,
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 27bef915d..fe181759c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -34,6 +34,9 @@ import { SearchUtil } from "./SearchUtil";
import { SelectionManager } from "./SelectionManager";
import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
+import { computedFn } from "mobx-utils";
+import { ColorScheme } from "./SettingsManager";
+import { Colors } from "../views/global/globalEnums";
export let resolvedPorts: { server: number, socket: number };
@@ -475,7 +478,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 },
@@ -538,8 +541,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)' },
];
}
@@ -565,7 +568,6 @@ export class CurrentUserUtils {
dontUndo: true,
title,
target,
- backgroundColor: "black",
_dropAction: "alias",
_removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
_width: 60,
@@ -580,8 +582,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
@@ -591,8 +595,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
@@ -763,7 +765,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
@@ -779,7 +781,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
@@ -798,7 +800,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,
@@ -812,7 +814,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
@@ -843,7 +845,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;
@@ -863,6 +865,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);
@@ -895,6 +898,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) {
@@ -928,7 +932,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;
}
@@ -943,14 +948,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" }));
}
}
@@ -1011,10 +1016,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");
@@ -1205,7 +1214,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()`);
@@ -1261,6 +1270,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..8a0e5480e 100644
--- a/src/client/views/AntimodeMenu.scss
+++ b/src/client/views/AntimodeMenu.scss
@@ -6,9 +6,9 @@
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;
&.with-rows {
diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index 2a0b494f5..157f3a4f2 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -44,18 +44,19 @@ $linkGap : 3px;
}
.documentButtonBar {
- margin-top: $linkGap;
- grid-column: 1/4;
- width: max-content;
- height: auto;
display: flex;
flex-direction: row;
+ gap: 3px;
}
.documentButtonBar-button {
- pointer-events: auto;
- padding-right: 5px;
- width: 25px;
+ cursor: pointer;
+ display: flex;
+ width: 30px;
+ height: 30px;
+ align-content: center;
+ justify-content: center;
+ align-items: center;
}
.documentButtonBar-linker {
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/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 1715f35e7..952d8d150 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -263,7 +263,6 @@ $linkGap : 3px;
}
.link-button-container {
- padding: $linkGap;
border-radius: 10px;
width: max-content;
height: auto;
@@ -271,6 +270,9 @@ $linkGap : 3px;
flex-direction: row;
z-index: 998;
position: absolute;
+ justify-content: center;
+ align-items: center;
+ gap: 5px;
background: $medium-gray;
}
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 07ca0257c..d913f2069 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,6 +107,14 @@
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;
@@ -118,7 +122,6 @@
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,10 +162,10 @@
}
.propertiesView {
- right: 0;
+ left: 0;
position: absolute;
z-index: 2;
- background-color: $medium-gray;
+ background-color: $light-gray;
.editable-title {
background-color: $light-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 836b8130b..edb2aca75 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..fd0ac9d5c 100644
--- a/src/client/views/_nodeModuleOverrides.scss
+++ b/src/client/views/_nodeModuleOverrides.scss
@@ -1,8 +1,50 @@
+@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;
+ height: 27px !important;
+}
+
+/* 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 +57,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: 23px;
+ 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..77e7b86ea 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: 24px;
+ // 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: 27px;
+ 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 {
@@ -311,8 +357,6 @@
background: transparent url("../../../../node_modules/flexlayout-react/images/restore.png") no-repeat center;
}
- .flexlayout__popup_menu {}
-
.flexlayout__popup_menu_item {
padding: 2px 10px 2px 10px;
color: #ddd;
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/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss
index ec8805907..86610ac20 100644
--- a/src/client/views/collections/CollectionLinearView.scss
+++ b/src/client/views/collections/CollectionLinearView.scss
@@ -20,19 +20,21 @@
}
.bottomPopup-background {
- padding-right: 14px;
+ background: $light-blue;
+ display: flex;
height: 35;
- transform: translate3d(6px, 5px, 0px);
- padding-top: 6.5px;
- padding-bottom: 7px;
- padding-left: 5px;
+ transform: translate3d(6px, 0px, 0px);
+ align-content: center;
+ justify-content: center;
+ align-items: center;
}
.bottomPopup-text {
+ color: black;
display: inline;
white-space: nowrap;
padding-left: 8px;
- padding-right: 4px;
+ padding-right: 20px;
vertical-align: middle;
font-size: 12.5px;
}
@@ -43,8 +45,8 @@
padding-left: 8px;
padding-right: 8px;
vertical-align: middle;
- background-color: lightgrey;
- border-radius: 5.5px;
+ background-color: #efefef;
+ border-radius: 3px;
color: black;
margin-right: 5px;
}
@@ -52,11 +54,12 @@
.bottomPopup-exit {
display: inline;
white-space: nowrap;
+ margin-right: 10px;
padding-left: 8px;
padding-right: 8px;
vertical-align: middle;
- background-color: lightgrey;
- border-radius: 5.5px;
+ background-color: #f3b6b6;
+ border-radius: 3px;
color: black;
}
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index e0b90304b..52c836556 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -167,24 +167,22 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
})}
</div>
{DocumentLinksButton.StartLink ? <span className="bottomPopup-background" style={{
- background: backgroundColor === color ? "black" : backgroundColor,
pointerEvents: "all"
}}
onPointerDown={e => e.stopPropagation()} >
<span className="bottomPopup-text" >
- Creating link from: {DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}
+ Creating link from: <b>{DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}</b>
</span>
- <Tooltip title={<><div className="dash-tooltip">{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
- "Turn on description pop-up"} </div></>} placement="top">
+ <Tooltip title={<><div className="dash-tooltip">{"Toggle description pop-up"} </div></>} placement="top">
<span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
</span>
</Tooltip>
- <Tooltip title={<><div className="dash-tooltip">Exit link clicking mode </div></>} placement="top">
+ <Tooltip title={<><div className="dash-tooltip">Exit linking mode</div></>} placement="top">
<span className="bottomPopup-exit" onClick={this.exitLongLinks}>
- Clear
+ Stop
</span>
</Tooltip>
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 3f2cc27a6..f96615ded 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 12f5dd155..f2ed2a5a2 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,30 @@ 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 stack: HTMLDivElement = tab.contentItem.parent;
+ const header: HTMLDivElement = tab;
+ console.log("Stack: " + stack.id, stack.className)
+ stack.onscroll = action((e: any) => {
+ console.log('scrolling...')
+ })
+ 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 +267,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 +289,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 +506,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/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
index 0c434eae5..fd99abce5 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
@@ -103,6 +103,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
this.props.setPreviewDoc(this.props.rowProps.original);
+ console.log("click cell");
let url: string;
if (url = StrCast(this.props.rowProps.row.href)) {
try {
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index ead5e166e..a9f33c4da 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -11,6 +11,8 @@ $medium-blue: #4476F7;
$pink: #E0217D;
$yellow: #F5D747;
+$logout-red: #ca4444;
+
$drop-shadow: "#32323215";
//padding
@@ -21,8 +23,6 @@ $large-padding: 32px;
//icon sizes
$icon-size: 28px;
-$antimodemenu-height: 36px;
-
// fonts
$sans-serif: "Noto Sans", sans-serif;
$large-header: 16px;
@@ -33,11 +33,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/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index 839ebf894..e45a91d57 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -22,7 +22,7 @@
.linkEditor-info {
//border-bottom: 0.5px solid $light-gray;
//padding-bottom: 1px;
- padding-top: 5px;
+ padding: 12px;
padding-left: 5px;
//margin-bottom: 6px;
display: flex;
@@ -61,7 +61,7 @@
}
.linkEditor-description {
- padding-left: 6.5px;
+ padding-left: 26px;
padding-right: 6.5px;
padding-bottom: 3.5px;
@@ -107,9 +107,9 @@
}
.linkEditor-followingDropdown {
- padding-left: 6.5px;
+ padding-left: 26px;
padding-right: 6.5px;
- padding-bottom: 6px;
+ padding-bottom: 15px;
&:hover {
cursor: pointer;
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index a2ea42999..19c6463d3 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -7,20 +7,19 @@
z-index: 2001;
.linkMenu-list,
- .linkMenu-listEditor
- {
+ .linkMenu-listEditor {
display: inline-block;
position: relative;
- border: 1px solid black;
- box-shadow: 3px 3px 1.5px grey;
+ border: 1px solid #e4e4e4;
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
background: white;
-
min-width: 170px;
- max-height: 170px;
+ max-height: 230px;
overflow-y: scroll;
z-index: 10;
- }
- .linkMenu-list {
+ }
+
+ .linkMenu-list {
white-space: nowrap;
overflow-x: hidden;
width: 240px;
@@ -46,13 +45,13 @@
}
.linkMenu-group-name {
+ padding: 10px;
&:hover {
- p {
- background-color: lightgray;
-
- }
+ // p {
+ // background-color: lightgray;
+ // }
p.expand-one {
width: calc(100% + 20px);
@@ -65,10 +64,9 @@
p {
width: 100%;
- //padding: 4px 6px;
line-height: 12px;
border-radius: 5px;
- font-weight: bold;
+ text-transform: capitalize;
}
.linkEditor-tableButton {
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index c7888c5ee..6fc860447 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -15,6 +15,9 @@ interface Props {
changeFlyout: () => void;
}
+/**
+ * the outermost component for the link menu of a node that contains a list of its linked nodes
+ */
@observer
export class LinkMenu extends React.Component<Props> {
private _editorRef = React.createRef<HTMLDivElement>();
@@ -36,6 +39,11 @@ export class LinkMenu extends React.Component<Props> {
}
}
+ /**
+ * maps each link to a JSX element to be rendered
+ * @param groups LinkManager containing info of all of the links
+ * @returns list of link JSX elements if there at least one linked element
+ */
renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
const linkItems = Array.from(groups.entries()).map(group =>
<LinkMenuGroup
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 74af78234..c7586a467 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -40,7 +40,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
return (
<div className="linkMenu-group" ref={this._menuRef}>
<div className="linkMenu-group-name">
- <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
+ <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"}> {this.props.groupType}:</p>
</div>
<div className="linkMenu-group-wrapper">
{groupItems}
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 4f9881565..90722daf9 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -4,7 +4,7 @@
// border-top: 0.5px solid $medium-gray;
position: relative;
display: flex;
- border-bottom: 0.5px solid black;
+ border-top: 0.5px solid #cdcdcd;
padding-left: 6.5px;
padding-right: 2px;
@@ -55,8 +55,8 @@
.linkMenu-destination-title {
text-decoration: none;
- color: rgb(85, 120, 196);
- font-size: 14px;
+ color: #4476F7;
+ font-size: 16px;
padding-bottom: 2px;
padding-right: 4px;
margin-right: 4px;
@@ -76,7 +76,7 @@
text-decoration: none;
font-style: italic;
color: rgb(95, 97, 102);
- font-size: 10px;
+ font-size: 9px;
margin-left: 20px;
max-width: 125px;
height: auto;
diff --git a/src/client/views/linking/LinkPopup.scss b/src/client/views/linking/LinkPopup.scss
new file mode 100644
index 000000000..8ae65158d
--- /dev/null
+++ b/src/client/views/linking/LinkPopup.scss
@@ -0,0 +1,45 @@
+.linkPopup-container {
+ background: white;
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
+ top: 35px;
+ height: 200px;
+ width: 200px;
+ position: absolute;
+ padding: 15px;
+ border-radius: 3px;
+
+ input {
+ border: 1px solid #b9b9b9;
+ border-radius: 20px;
+ height: 25px;
+ width: 100%;
+ padding-left: 10px;
+ }
+
+ .divider {
+ margin: 10px 0;
+ height: 20px;
+ width: 100%;
+
+ .line {
+ height: 1px;
+ background-color: #b9b9b9;
+ width: 100%;
+ position: relative;
+ top: 12px;
+ }
+
+ .divider-text {
+ width: 20px;
+ background-color: white;
+ text-align: center;
+ position: relative;
+ margin: auto;
+ }
+ }
+
+
+ .searchBox-container {
+ background: pink;
+ }
+} \ No newline at end of file
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
new file mode 100644
index 000000000..2c4b718f4
--- /dev/null
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -0,0 +1,114 @@
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@material-ui/core';
+import { action, observable, runInAction } from 'mobx';
+import { observer } from "mobx-react";
+import { Doc, DocListCast } from '../../../fields/Doc';
+import { Cast, StrCast } from '../../../fields/Types';
+import { WebField } from '../../../fields/URLField';
+import { emptyFunction, setupMoveUpEvents, returnFalse, returnTrue, returnEmptyDoclist, returnEmptyFilter } from '../../../Utils';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { DocumentManager } from '../../util/DocumentManager';
+import { DragManager } from '../../util/DragManager';
+import { Hypothesis } from '../../util/HypothesisUtils';
+import { LinkManager } from '../../util/LinkManager';
+import { undoBatch } from '../../util/UndoManager';
+import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
+import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView';
+import { LinkDocPreview } from '../nodes/LinkDocPreview';
+import './LinkPopup.scss';
+import React = require("react");
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
+import { DefaultStyleProvider } from '../StyleProvider';
+import { Transform } from '../../util/Transform';
+import { DocUtils } from '../../documents/Documents';
+import { SearchBox } from '../search/SearchBox';
+import { EditorView } from 'prosemirror-view';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+
+interface LinkPopupProps {
+ showPopup: boolean;
+ // groupType: string;
+ // linkDoc: Doc;
+ // docView: DocumentView;
+ // sourceDoc: Doc;
+}
+
+/**
+ * Popup component for creating links from text to Dash documents
+ */
+
+@observer
+export class LinkPopup extends React.Component<LinkPopupProps> {
+ @observable private linkURL: string = "";
+ @observable public view?: EditorView;
+
+
+
+ // TODO: should check for valid URL
+ @undoBatch
+ makeLinkToURL = (target: string, lcoation: string) => {
+ ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target);
+ }
+
+ @action
+ onLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ this.linkURL = e.target.value;
+ console.log(this.linkURL)
+ }
+
+
+ getPWidth = () => 500;
+ getPHeight = () => 500;
+
+ render() {
+ const popupVisibility = this.props.showPopup ? "block" : "none";
+ return (
+ <div className="linkPopup-container" style={{ display: popupVisibility }}>
+ <div className="linkPopup-url-container">
+ <input autoComplete="off" type="text" value={this.linkURL} placeholder="Enter URL..." onChange={this.onLinkChange} />
+ <button onPointerDown={e => this.makeLinkToURL(this.linkURL, "add:right")}
+ style={{ display: "block", margin: "10px auto", }}>Apply hyperlink</button>
+ </div>
+ <div className="divider">
+ <div className="line"></div>
+ <p className="divider-text">or</p>
+ </div>
+ <div className="linkPopup-document-search-container">
+ {/* <i></i>
+ <input defaultValue={""} autoComplete="off" type="text" placeholder="Search for Document..." id="search-input"
+ className="linkPopup-searchBox searchBox-input" /> */}
+
+ <SearchBox Document={CurrentUserUtils.MySearchPanelDoc}
+ DataDoc={CurrentUserUtils.MySearchPanelDoc}
+ fieldKey="data"
+ dropAction="move"
+ isSelected={returnTrue}
+ isContentActive={returnTrue}
+ select={returnTrue}
+ setHeight={returnFalse}
+ addDocument={undefined}
+ addDocTab={returnTrue}
+ 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} />
+ </div>
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index cb07c949f..b6fc04b73 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..9bab72d55 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -1,16 +1,27 @@
@import "../global/globalCssVariables.scss";
+.documentLinksButton-menu {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ display: flex;
+ align-content: center;
+ justify-content: center;
+ align-items: center;
+}
+
.documentLinksButton-cont {
min-width: 20;
min-height: 20;
position: absolute;
}
+
.documentLinksButton,
.documentLinksButton-endLink,
.documentLinksButton-startLink {
- height: 20px;
- width: 20px;
+ height: 25px;
+ width: 25px;
position: absolute;
border-radius: 50%;
opacity: 0.9;
@@ -37,23 +48,21 @@
font-weight: bold;
&:hover {
- background: $medium-gray;
transform: scale(1.05);
cursor: pointer;
}
}
.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..cec06d2d4 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;
@@ -30,12 +31,12 @@ interface DocumentLinksButtonProps {
Offset?: (number | undefined)[];
AlwaysOn?: boolean;
InMenu?: boolean;
- StartLink?: boolean;
+ StartLink?: boolean; //whether the link HAS been started (i.e. now needs to be completed)
}
@observer
export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
private _linkButton = React.createRef<HTMLDivElement>();
- @observable public static StartLink: Doc | undefined;
+ @observable public static StartLink: Doc | undefined; //origin's Doc, if defined
@observable public static StartLinkView: DocumentView | undefined;
@observable public static AnnotationId: string | undefined;
@observable public static AnnotationUri: string | undefined;
@@ -45,6 +46,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
public static invisibleWebRef = React.createRef<HTMLDivElement>();
@action public static ClearLinkEditor() { DocumentLinksButton.LinkEditorDocView = undefined; }
+
@action @undoBatch
onLinkButtonMoved = (e: PointerEvent) => {
if (this.props.InMenu && this.props.StartLink) {
@@ -120,7 +122,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
- } else {
+ } else { //if this LinkButton's Document is undefined
DocumentLinksButton.StartLink = this.props.View.props.Document;
DocumentLinksButton.StartLinkView = this.props.View;
}
@@ -131,6 +133,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
}
}
+
completeLink = (e: React.PointerEvent): void => {
setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action((e, doubleTap) => {
if (doubleTap && !this.props.StartLink) {
@@ -141,7 +144,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
} else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
const sourceDoc = DocumentLinksButton.StartLink;
const targetDoc = this.props.View.ComponentView?.getAnchor?.() || this.props.View.Document;
- const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, "long drag");
+ const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, "links"); //why is long drag here when this is used for completing links by clicking?
LinkManager.currentLink = linkDoc;
@@ -184,7 +187,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
} else if (startLink !== endLink) {
endLink = endLinkView?.docView?._componentView?.getAnchor?.() || endLink;
startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.() || startLink;
- const linkDoc = DocUtils.MakeLink({ doc: startLink }, { doc: endLink }, DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : "long drag", undefined, undefined, true);
+ const linkDoc = DocUtils.MakeLink({ doc: startLink }, { doc: endLink }, DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : "link", undefined, undefined, true);
LinkManager.currentLink = linkDoc;
@@ -242,45 +245,57 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
return results;
}
+ /**
+ * gets the JSX of the link button (btn used to start/complete links) OR the link-view button (btn on bottom left of each linked node)
+ */
@computed get linkButtonInner() {
const btnDim = this.props.InMenu ? "20px" : "30px";
const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
- return <div className="documentLinksButton-cont" ref={this._linkButton}
- style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
- >
- <div className={"documentLinksButton"}
- onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
- style={{
- backgroundColor: this.props.InMenu ? "" : "#add8e6",
- color: this.props.InMenu ? "white" : "black",
- width: btnDim,
- height: btnDim,
- }} >
- {this.props.InMenu ?
- this.props.StartLink ?
- <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
- : link
- : Array.from(this.filteredLinks).length}
- </div>
- {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ?
- <div className={"documentLinksButton-endLink"}
+ return (!this.props.InMenu ?
+ <div className="documentLinksButton-cont" ref={this._linkButton}
+ style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
+ >
+ <div className={"documentLinksButton"}
+ onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
style={{
- width: btnDim, height: btnDim,
- backgroundColor: DocumentLinksButton.StartLink ? "" : "grey",
- 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)} />
- : (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 }} />
- : (null)
- }
- </div >;
+ backgroundColor: Colors.LIGHT_BLUE,
+ color: Colors.BLACK,
+ width: btnDim,
+ height: btnDim,
+ }}>
+ {Array.from(this.filteredLinks).length}
+ </div>
+ </div>
+ :
+ <div className="documentLinksButton-menu">
+ {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
+ <div className={"documentLinksButton-endLink"}
+ style={{
+ width: btnDim, height: btnDim,
+ 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)}>
+ {this.props.StartLink ?
+ <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
+ : link}
+ </div>
+ : (null)
+ }
+ {
+ this.props.InMenu ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+ <div className={'documentLinksButton' + (DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink) ? '-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>
+ )
}
render() {
@@ -290,6 +305,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
const buttonTitle = "Tap to view links; double tap to open link collection";
const title = this.props.InMenu ? menuTitle : buttonTitle;
+ //render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? (null) :
this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
<Tooltip title={<div className="dash-tooltip">{title}</div>}>
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 281f25fb3..7f164ca48 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -147,7 +147,7 @@
.documentView-titleWrapper,
.documentView-titleWrapper-hover {
overflow: hidden;
- color: gray;
+ color: $black;
transform-origin: top left;
top: 0;
width: 100%;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a7b4c4171..4232f98b5 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/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 6738d481d..5c3010dbc 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -215,6 +215,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
AnchorMenu.Instance.Status = "marquee";
AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => {
this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView.state, this._editorView?.dispatch);
+ console.log("highlight")
return undefined;
});
/**
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 59b2d3753..2523dda38 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -852,6 +852,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
@undoBatch
makeLinkToURL = (target: string, lcoation: string) => {
((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target);
+ console.log((this.view as any)?.TextView);
}
@undoBatch
@@ -963,7 +964,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 +977,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 +986,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 11a735645..033371e96 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;
@@ -1207,9 +1173,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>
@@ -1254,7 +1220,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" >
@@ -1289,9 +1255,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>
@@ -1308,11 +1274,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">
@@ -1365,7 +1331,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;
@@ -1505,7 +1471,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)}
@@ -1517,7 +1483,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>
@@ -1525,7 +1491,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)}
@@ -1543,16 +1509,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>) => {
@@ -1567,16 +1533,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>) => {
@@ -1660,15 +1626,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>
@@ -1700,26 +1666,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>
@@ -1879,8 +1845,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>
@@ -1895,12 +1861,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">
@@ -1910,7 +1876,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>
@@ -1924,7 +1890,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>
@@ -2140,7 +2106,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>
@@ -2223,6 +2189,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)}>
@@ -2230,7 +2198,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>
@@ -2239,7 +2207,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>
@@ -2247,12 +2215,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>
</>
@@ -2389,7 +2357,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>
@@ -2428,8 +2396,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 19893af7e..238d025dc 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,
@@ -213,11 +215,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);
@@ -296,7 +298,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 (
@@ -304,7 +306,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 => {
@@ -360,7 +362,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/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index c24c4eaaf..70ca19842 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -10,6 +10,7 @@ import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu";
import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu";
import "./AnchorMenu.scss";
import { SelectionManager } from "../../util/SelectionManager";
+import { LinkPopup } from "../linking/LinkPopup";
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -38,6 +39,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable private _valueValue: string = "";
@observable private _added: boolean = false;
@observable private highlightColor: string = "rgba(245, 230, 95, 0.616)";
+ @observable private _showLinkPopup: boolean = false;
@observable public _colorBtn = false;
@observable public Highlighting: boolean = false;
@@ -80,6 +82,14 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
}
}
+ @action
+ toggleLinkPopup = (e: React.MouseEvent) => {
+ //ignore the potential null type error because this method cannot be called unless the user selects text and clicks the link button
+ console.log(window.getSelection().toString())
+ //change popup visibility field to visible
+ this._showLinkPopup = !this._showLinkPopup;
+ }
+
@computed get highlighter() {
const button =
<button className="antimodeMenu-button color-preview-button" title="" key="highlighter-button" onClick={this.highlightClicked}>
@@ -136,6 +146,14 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
<FontAwesomeIcon icon="comment-alt" size="lg" />
</button>
</Tooltip>,
+
+ //NOTE: link popup is currently incomplete
+ // <Tooltip key="link" title={<div className="dash-tooltip">{"Link selected text to document or URL"}</div>}>
+ // <button className="antimodeMenu-button link" onPointerDown={this.toggleLinkPopup} style={{}}>
+ // <FontAwesomeIcon icon="link" size="lg" />
+ // </button>
+ // </Tooltip>,
+ // <LinkPopup showPopup={this._showLinkPopup} />
] : [
<Tooltip key="trash" title={<div className="dash-tooltip">{"Remove Link Anchor"}</div>}>
<button className="antimodeMenu-button" onPointerDown={this.Delete}>
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
new file mode 100644
index 000000000..ebdf030e7
--- /dev/null
+++ b/src/client/views/topbar/TopBar.scss
@@ -0,0 +1,213 @@
+@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-icon {
+ cursor: pointer;
+ font-size: 12px;
+ width: fit-content;
+ display: flex;
+ justify-content: center;
+ gap: 4px;
+ align-items: center;
+ justify-self: center;
+ align-self: center;
+ border-radius: 5px;
+ padding: 5px;
+ transition: linear 0.1s;
+ color: $black;
+ background-color: $light-gray;
+ }
+
+ .topBar-icon:hover {
+ background-color: $light-blue;
+ }
+
+
+ .topbar-center {
+ grid-column: 2;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ gap: 5px;
+
+ .topbar-lozenge-dashboard {
+ display: flex;
+
+ .topbar-dashboards {
+ display: inline-flex;
+ }
+
+ .topbar-dashSelect {
+ border: none;
+ background-color: $dark-gray;
+ color: $white;
+ font-family: 'Roboto';
+ font-size: 17;
+ font-weight: 500;
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+ }
+
+
+ .topbar-right {
+ grid-column: 3;
+ position: relative;
+ display: flex;
+ justify-content: flex-end;
+ gap: 5px;
+ margin-right: 5px;
+ }
+
+ .topbar-left {
+ grid-column: 1;
+ color: black;
+ font-family: 'Roboto';
+ position: relative;
+ display: flex;
+ width: 450;
+ gap: 5px;
+
+ .topBar-icon:hover {
+ background-color: $logout-red;
+ }
+
+ .topbar-lozenge-user,
+ .topbar-lozenge {
+ height: 23;
+ font-size: 12;
+ color: white;
+ font-family: 'Roboto';
+ font-weight: 400;
+ padding: 4px;
+ align-self: center;
+ margin-left: 7px;
+ display: flex;
+ align-items: center;
+
+ .topbar-dashSelect {
+ border: none;
+ background-color: transparent;
+ color: black;
+ font-family: 'Roboto';
+ font-size: 17;
+ font-weight: 500;
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+ }
+
+ .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-lozenge-user:hover {
+ .topbar-logoff {
+ display: inline-block;
+ }
+ }
+ }
+
+ .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..bd9935333
--- /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-left">
+ <div className="topbar-lozenge-user">
+ {`${Doc.CurrentUserEmail}`}
+ </div>
+ <div className="topbar-icon" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+ {"Sign out"}
+ </div>
+ </div>
+ <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>
+ <div className="topbar-dashboards">
+ <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
+ >
+ {"New"}<FontAwesomeIcon icon="plus"></FontAwesomeIcon>
+ </div>
+ {Doc.UserDoc().noviceMode ? (null) : <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
+ >
+ {"Snapshot"}<FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+ </div>}
+ </div>
+ </div>
+ <div className="topbar-right" >
+ <div className="topbar-icon">
+ {"Help"}<FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
+ </div>
+ <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}>
+ {"Settings"}<FontAwesomeIcon icon="cog"></FontAwesomeIcon>
+ </div>
+
+ </div>
+ </div>
+ </div >
+ );
+ }
+} \ No newline at end of file
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 6b6f0fed0..3b8109385 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, MapField, 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 {
@@ -1194,7 +1195,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";