aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-08-27 13:37:45 -0400
committerbobzel <zzzman@gmail.com>2023-08-27 13:37:45 -0400
commite566cdb001da320b5ee3f7fa60d96b7a09a195c3 (patch)
tree3d4373ede28da858ae964edffa8539961f148471
parent0332a80329328e39c244623d5090331b83df339c (diff)
parent6d60b14e109e527ddc7a096af858cbc05dab3480 (diff)
Merge branch 'master' into data-visualization-sarah
-rw-r--r--package-lock.json39
-rw-r--r--src/.DS_Storebin10244 -> 10244 bytes
-rw-r--r--src/client/documents/Documents.ts167
-rw-r--r--src/client/views/DashboardView.tsx1
-rw-r--r--src/client/views/FilterPanel.scss66
-rw-r--r--src/client/views/FilterPanel.tsx307
-rw-r--r--src/client/views/MainView.scss8
-rw-r--r--src/client/views/MainView.tsx5
-rw-r--r--src/client/views/Palette.tsx69
-rw-r--r--src/client/views/PropertiesSection.tsx3
-rw-r--r--src/client/views/PropertiesView.scss14
-rw-r--r--src/client/views/PropertiesView.tsx19
-rw-r--r--src/fields/Doc.ts18
-rw-r--r--src/fields/IconField.ts26
-rw-r--r--src/fields/PresField.ts6
-rw-r--r--src/mobile/MobileInterface.tsx1
16 files changed, 559 insertions, 190 deletions
diff --git a/package-lock.json b/package-lock.json
index 00410e3be..250ac5f8b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10445,16 +10445,6 @@
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
"dev": true
},
- "d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dev": true,
- "requires": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
"d3": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.4.tgz",
@@ -11835,28 +11825,6 @@
"is-symbol": "^1.0.2"
}
},
- "es5-ext": {
- "version": "0.10.62",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
- "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
- "dev": true,
- "requires": {
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.3",
- "next-tick": "^1.1.0"
- }
- },
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
- "dev": true,
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
- }
- },
"es6-promise": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -11868,7 +11836,6 @@
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"dev": true,
"requires": {
- "d": "^1.0.1",
"ext": "^1.1.2"
}
},
@@ -27681,12 +27648,6 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
- "type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
- "dev": true
- },
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/src/.DS_Store b/src/.DS_Store
index 3005fd3b3..c363efb13 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7f3309ea8..1186446e1 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -75,6 +75,8 @@ export class FInfo {
readOnly: boolean = false;
fieldType?: string = '';
values?: Field[];
+
+ filterable?: boolean = true;
// format?: string; // format to display values (e.g, decimal places, $, etc)
// parse?: ScriptField; // parse a value from a string
constructor(d: string, readOnly?: boolean) {
@@ -85,50 +87,61 @@ export class FInfo {
class BoolInfo extends FInfo {
fieldType? = 'boolean';
values?: boolean[] = [true, false];
+ constructor(d: string, filterable?: boolean) {
+ super(d);
+ this.filterable = filterable;
+ }
}
class NumInfo extends FInfo {
fieldType? = 'number';
values?: number[] = [];
- constructor(d: string, readOnly?: boolean, values?: number[]) {
+ constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: number[]) {
super(d, readOnly);
this.values = values;
+ this.filterable = filterable;
}
}
class StrInfo extends FInfo {
fieldType? = 'string';
values?: string[] = [];
- constructor(d: string, readOnly?: boolean, values?: string[]) {
+ constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: string[]) {
super(d, readOnly);
this.values = values;
+ this.filterable = filterable;
}
}
class DocInfo extends FInfo {
fieldType? = 'Doc';
values?: Doc[] = [];
- constructor(d: string, values?: Doc[]) {
+ constructor(d: string, filterable?: boolean, values?: Doc[]) {
super(d, true);
this.values = values;
+ this.filterable = filterable;
}
}
class DimInfo extends FInfo {
fieldType? = 'enumeration';
values? = [DimUnit.Pixel, DimUnit.Ratio];
readOnly = false;
+ filterable = false;
}
class PEInfo extends FInfo {
fieldType? = 'enumeration';
values? = ['all', 'none'];
readOnly = false;
+ filterable = false;
}
class DAInfo extends FInfo {
fieldType? = 'enumeration';
values? = ['embed', 'copy', 'move', 'same', 'proto', 'none'];
readOnly = false;
+ filterable = false;
}
class CTypeInfo extends FInfo {
fieldType? = 'enumeration';
values? = Array.from(Object.keys(CollectionViewType));
readOnly = false;
+ filterable = false;
}
class DTypeInfo extends FInfo {
fieldType? = 'enumeration';
@@ -138,10 +151,16 @@ class DTypeInfo extends FInfo {
class DateInfo extends FInfo {
fieldType? = 'date';
values?: DateField[] = [];
+ filterable = true;
+}
+class ListInfo extends FInfo {
+ fieldType? = 'list';
+ values?: List<any>[] = [];
}
type BOOLt = BoolInfo | boolean;
type NUMt = NumInfo | number;
type STRt = StrInfo | string;
+type LISTt = ListInfo | List<any>;
type DOCt = DocInfo | Doc;
type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio;
type PEVt = PEInfo | 'none' | 'all';
@@ -151,26 +170,26 @@ type DATEt = DateInfo | number;
type DTYPEt = DTypeInfo | string;
export class DocumentOptions {
// coordinate and dimensions depending on view
- x?: NUMt = new NumInfo('x coordinate of document in a freeform view');
- y?: NUMt = new NumInfo('y coordinage of document in a freeform view');
- z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, [1, 0]);
- _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height");
+ x?: NUMt = new NumInfo('x coordinate of document in a freeform view', false);
+ y?: NUMt = new NumInfo('y coordinage of document in a freeform view', false);
+ z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, false, [1, 0]);
+ _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", false);
_dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units");
- latitude?: NUMt = new NumInfo('latitude coordinate for map views');
- longitude?: NUMt = new NumInfo('longitude coordinate for map views');
+ latitude?: NUMt = new NumInfo('latitude coordinate for map views', false);
+ longitude?: NUMt = new NumInfo('longitude coordinate for map views', false);
map?: STRt = new StrInfo('text location of map');
- map_type?: STRt = new StrInfo('type of map view');
- map_zoom?: NUMt = new NumInfo('zoom of a map view');
- _timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)');
- _timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden');
+ map_type?: STRt = new StrInfo('type of map view', false);
+ map_zoom?: NUMt = new NumInfo('zoom of a map view', false);
+ _timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)', false);
+ _timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden', false);
_width?: NUMt = new NumInfo('displayed width of a document');
_height?: NUMt = new NumInfo('displayed height of document');
- data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)');
- data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)');
- linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)');
- _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)');
- _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)');
- _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers');
+ data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)', false);
+ data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)', false);
+ linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false);
+ _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', false);
+ _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)', false);
+ _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false);
_nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers');
'acl-Guest'?: STRt = new StrInfo("permissions granted to users logged in as 'guest' (either view, or private)"); // public permissions
@@ -178,30 +197,30 @@ export class DocumentOptions {
type?: DTYPEt = new DTypeInfo('type of document', true);
type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection
_type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection
- title?: STRt = new StrInfo('title of document');
+ title?: STRt = new StrInfo('title of document', true);
caption?: RichTextField;
author?: string; // STRt = new StrInfo('creator of document'); // bcz: don't change this. Otherwise, the userDoc's field Infos will have a FieldInfo assigned to its author field which will render it unreadable
author_date?: DATEt = new DateInfo('date the document was created', true);
- annotationOn?: DOCt = new DocInfo('document annotated by this document');
- embedContainer?: DOCt = new DocInfo('document that displays (contains) this discument');
- color?: STRt = new StrInfo('foreground color data doc');
- hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection');
- backgroundColor?: STRt = new StrInfo('background color for data doc');
- opacity?: NUMt = new NumInfo('document opacity');
- viewTransitionTime?: NUMt = new NumInfo('transition duration for view parameters');
- dontRegisterView?: BOOLt = new BoolInfo('are views of this document registered so that they can be found when following links, etc');
+ annotationOn?: DOCt = new DocInfo('document annotated by this document', false);
+ embedContainer?: DOCt = new DocInfo('document that displays (contains) this discument', false);
+ color?: STRt = new StrInfo('foreground color data doc', false);
+ hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection', false);
+ backgroundColor?: STRt = new StrInfo('background color for data doc', false);
+ opacity?: NUMt = new NumInfo('document opacity', false);
+ viewTransitionTime?: NUMt = new NumInfo('transition duration for view parameters', false);
+ dontRegisterView?: BOOLt = new BoolInfo('are views of this document registered so that they can be found when following links, etc', false);
_undoIgnoreFields?: List<string>; //'fields that should not be added to the undo stack (opacity for Undo/Redo/and sidebar) AND whether modifications to document are undoable (true for linearview menu buttons to prevent open/close from entering undo stack)'
undoIgnoreFields?: List<string>; //'fields that should not be added to the undo stack (opacity for Undo/Redo/and sidebar) AND whether modifications to document are undoable (true for linearview menu buttons to prevent open/close from entering undo stack)'
- _headerHeight?: NUMt = new NumInfo('height of document header used for displaying title');
- _headerFontSize?: NUMt = new NumInfo('font size of header of custom notes');
+ _headerHeight?: NUMt = new NumInfo('height of document header used for displaying title', false);
+ _headerFontSize?: NUMt = new NumInfo('font size of header of custom notes', false);
_headerPointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume');
_lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged");
_lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed');
layout?: string | Doc; // default layout string or template document
- layout_keyValue?: STRt = new StrInfo('layout definition for showing keyValue view of document');
- layout_explainer?: STRt = new StrInfo('explanation displayed at top of a collection to describe its purpose');
- layout_headerButton?: DOCt = new DocInfo('the (button) Doc to display at the top of a collection.');
+ layout_keyValue?: STRt = new StrInfo('layout definition for showing keyValue view of document', false);
+ layout_explainer?: STRt = new StrInfo('explanation displayed at top of a collection to describe its purpose', false);
+ layout_headerButton?: DOCt = new DocInfo('the (button) Doc to display at the top of a collection.', false);
layout_disableBrushing?: BOOLt = new BoolInfo('whether to suppress border highlighting');
layout_unrendered?: BOOLt = new BoolInfo('denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf)');
layout_hideOpenButton?: BOOLt = new BoolInfo('whether to hide the open full screen button when selected');
@@ -213,33 +232,33 @@ export class DocumentOptions {
layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected');
layout_borderRounding?: string;
layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow
- layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents');
+ layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents', false);
_layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents');
- _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document');
- _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds');
+ _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false);
+ _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false);
_layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown');
_layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)');
_layout_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content');
- _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition');
+ _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition', false);
_layout_enableAltContentUI?: BOOLt = new BoolInfo('whether to show alternate content button');
_layout_showTitle?: string; // field name to display in header (:hover is an optional suffix)
_layout_showSidebar?: BOOLt = new BoolInfo('whether an annotationsidebar should be displayed for text docuemnts');
_layout_showCaption?: string; // which field to display in the caption area. leave empty to have no caption
_chromeHidden?: BOOLt = new BoolInfo('whether the editing chrome for a document is hidden');
- _gridGap?: NUMt = new NumInfo('gap between items in masonry view');
- _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts');
- _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts');
- _xPadding?: NUMt = new NumInfo('x padding');
- _yPadding?: NUMt = new NumInfo('y padding');
+ _gridGap?: NUMt = new NumInfo('gap between items in masonry view', false);
+ _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts', false);
+ _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts', false);
+ _xPadding?: NUMt = new NumInfo('x padding', false);
+ _yPadding?: NUMt = new NumInfo('y padding', false);
_singleLine?: boolean; // whether label box is restricted to one line of text
_createDocOnCR?: boolean; // whether carriage returns and tabs create new text documents
- _columnWidth?: NUMt = new NumInfo('width of table column');
+ _columnWidth?: NUMt = new NumInfo('width of table column', false);
_columnsHideIfEmpty?: BOOLt = new BoolInfo('whether stacking view column headings should be hidden');
- _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', true);
- _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', true);
- icon_nativeWidth?: NUMt = new NumInfo('native width of icon view', true);
- icon_nativeHeight?: NUMt = new NumInfo('native height of icon view', true);
+ _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', false, true);
+ _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', false, true);
+ icon_nativeWidth?: NUMt = new NumInfo('native width of icon view', false, true);
+ icon_nativeHeight?: NUMt = new NumInfo('native height of icon view', false, true);
_text_fontSize?: string;
_text_fontFamily?: string;
_text_fontWeight?: string;
@@ -247,11 +266,11 @@ export class DocumentOptions {
infoWindowOpen?: BOOLt = new BoolInfo('whether info window corresponding to pin is open (on MapDocuments)');
_carousel_index?: NUMt = new NumInfo('which item index the carousel viewer is showing');
- _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes');
- _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes');
- stroke_width?: NUMt = new NumInfo('width of an ink stroke');
- icon_label?: STRt = new StrInfo('label to use for a fontIcon doc (otherwise, the title is used)');
- mediaState?: STRt = new StrInfo('status of audio/video media document: "pendingRecording", "recording", "paused", "playing"');
+ _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes', false);
+ _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes', false);
+ stroke_width?: NUMt = new NumInfo('width of an ink stroke', false);
+ icon_label?: STRt = new StrInfo('label to use for a fontIcon doc (otherwise, the title is used)', false);
+ mediaState?: STRt = new StrInfo('status of audio/video media document: "pendingRecording", "recording", "paused", "playing"', false);
recording?: BOOLt = new BoolInfo('whether WebCam is recording or not');
autoPlayAnchors?: BOOLt = new BoolInfo('whether to play audio/video when an anchor is clicked in a stackedTimeline.');
dontPlayLinkOnSelect?: BOOLt = new BoolInfo('whether an audio/video should start playing when a link is followed to it.');
@@ -269,7 +288,7 @@ export class DocumentOptions {
contextMenuIcons?: List<string>;
childFilters_boolean?: string;
childFilters?: List<string>;
- childLimitHeight?: NUMt = new NumInfo('whether to limit the height of collection children. 0 - means height can be no bigger than width');
+ childLimitHeight?: NUMt = new NumInfo('whether to limit the height of collection children. 0 - means height can be no bigger than width', false);
childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox layout in tree view)
childLayoutString?: string; // template string for collection to use to render its children
childDocumentsActive?: BOOLt = new BoolInfo('whether child documents are active when parent is document active');
@@ -281,12 +300,12 @@ export class DocumentOptions {
childContextMenuIcons?: List<string>;
targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
- lastFrame?: NUMt = new NumInfo('the last frame of a frame-based collection (e.g., progressive slide)');
- activeFrame?: NUMt = new NumInfo('the active frame of a document in a frame base collection');
- appearFrame?: NUMt = new NumInfo('the frame in which the document appears');
- _currentFrame?: NUMt = new NumInfo('the current frame of a frame-based collection (e.g., progressive slide)');
+ lastFrame?: NUMt = new NumInfo('the last frame of a frame-based collection (e.g., progressive slide)', false);
+ activeFrame?: NUMt = new NumInfo('the active frame of a document in a frame base collection', false);
+ appearFrame?: NUMt = new NumInfo('the frame in which the document appears', false);
+ _currentFrame?: NUMt = new NumInfo('the current frame of a frame-based collection (e.g., progressive slide)', false);
- isSystem?: BOOLt = new BoolInfo('is this a system created/owned doc', true);
+ isSystem?: BOOLt = new BoolInfo('is this a system created/owned doc', false);
isBaseProto?: BOOLt = new BoolInfo('is doc a base level prototype for data documents as opposed to data documents which are prototypes for layout documents. base protos are not cloned during a deep');
isTemplateForField?: string; // the field key for which the containing document is a rendering template
isTemplateDoc?: BOOLt = new BoolInfo('is the document a template for creating other documents');
@@ -295,26 +314,28 @@ export class DocumentOptions {
_isTimelineLabel?: BOOLt = new BoolInfo('is document a timeline label');
_isLightbox?: BOOLt = new BoolInfo('whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target');
- config_latitude?: NUMt = new NumInfo('latitude of a map'); // latitude of a map
- config_longitude?: NUMt = new NumInfo('longitude of map'); // longitude of map
- config_map_zoom?: NUMt = new NumInfo('zoom of map'); // zoom of map
- config_map_type?: string;
- config_map?: string;
- config_panX?: NUMt = new NumInfo('panX saved as a view spec');
- config_panY?: NUMt = new NumInfo('panY saved as a view spec');
- config_viewScale?: NUMt = new NumInfo('viewScale saved as a view Spec');
- presentation_transition?: NUMt = new NumInfo('the time taken for the transition TO a document');
- presentation_duration?: NUMt = new NumInfo('the duration of the slide in presentation view');
- presentation_zoomText?: BOOLt = new BoolInfo('whether text anchors should shown in a larger box when following links to make them stand out');
+ config_latitude?: NUMt = new NumInfo('latitude of a map', false);
+ config_longitude?: NUMt = new NumInfo('longitude of map', false);
+ config_map_zoom?: NUMt = new NumInfo('zoom of map', false);
+ config_map_type?: STRt = new StrInfo('map view type (e.g, aerial)', false);
+ config_map?: STRt = new StrInfo('text location of map', false);
+ config_panX?: NUMt = new NumInfo('panX saved as a view spec', false);
+ config_panY?: NUMt = new NumInfo('panY saved as a view spec', false);
+ config_viewScale?: NUMt = new NumInfo('viewScale saved as a view Spec', false);
+ presentation_transition?: NUMt = new NumInfo('the time taken for the transition TO a document', false);
+ presentation_duration?: NUMt = new NumInfo('the duration of the slide in presentation view', false);
+ presentation_zoomText?: BOOLt = new BoolInfo('whether text anchors should shown in a larger box when following links to make them stand out', false);
data?: any;
data_useCors?: BOOLt = new BoolInfo('whether CORS protocol should be used for web page');
columnHeaders?: List<SchemaHeaderField>; // headers for stacking views
schemaHeaders?: List<SchemaHeaderField>; // headers for schema view
- dockingConfig?: STRt = new StrInfo('configuration of golden layout windows (applies only if doc is rendered as a CollectionDockingView)');
+ dockingConfig?: STRt = new StrInfo('configuration of golden layout windows (applies only if doc is rendered as a CollectionDockingView)', false);
icon?: string; // icon used by fonticonbox to render button
noteType?: string;
+ // STOPPING HERE
+
// freeform properties
_freeform_backgroundGrid?: BOOLt = new BoolInfo('whether background grid is shown on freeform collections');
_freeform_scale?: NUMt = new NumInfo('how much a freeform view has been scaled (zoomed)');
@@ -382,9 +403,9 @@ export class DocumentOptions {
cloneFieldFilter?: List<string>; // fields not to copy when the document is clonedclipboard?: Doc;
dragWhenActive?: BOOLt = new BoolInfo('should document drag when it is active - e.g., pileView, group');
dragAction?: DROPt = new DAInfo('how to drag document when it is active (e.g., tree, groups)');
- dragFactory_count?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', true);
- dragFactory?: DOCt = new DocInfo('document to create when dragging with a suitable onDragStart script');
- clickFactory?: DOCt = new DocInfo('document to create when clicking on a button with a suitable onClick script');
+ dragFactory_count?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)', false, true);
+ dragFactory?: DOCt = new DocInfo('document to create when dragging with a suitable onDragStart script', false);
+ clickFactory?: DOCt = new DocInfo('document to create when clicking on a button with a suitable onClick script', false);
onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop
target?: Doc; // available for use in scripts. used to provide a document parameter to the script (Note, this is a convenience entry since any field could be used for parameterizing a script)
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 231a2d5fb..5d7fc8835 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -402,6 +402,7 @@ export class DashboardView extends React.Component {
backgroundColor: background,
title: `Untitled Tab 1`,
};
+
const title = name ? name : `Dashboard ${dashboardCount}`;
const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: title }, id, 'row');
diff --git a/src/client/views/FilterPanel.scss b/src/client/views/FilterPanel.scss
index 4f0460659..d6d2956aa 100644
--- a/src/client/views/FilterPanel.scss
+++ b/src/client/views/FilterPanel.scss
@@ -135,7 +135,7 @@
.filterBox-addFilter {
width: 120px;
- background-color: #e9e9e9;
+ backgroundcolor: #e9e9e9;
border-radius: 12px;
padding: 5px;
margin: 5px;
@@ -156,7 +156,7 @@
right: 0;
top: 0;
z-index: 1;
- // background-color: #9f9f9f;
+ // background-color: #9f9f9f;
.filterBox-tree {
z-index: 0;
@@ -191,22 +191,60 @@
}
}
+.filterBox-facetHeader {
+ display: flex;
+ align-items: center;
+ // float:right;
+ .filterBox-facetHeader-collapse {
+ // float: right;
+ // justify-items: right;
+ // align-items: flex-end;
+ margin-left: auto;
+ // margin-right: 9px;
-.filterBox-facetHeader{
- display: flex;
- align-items: center;
- // float:right;
-
- .filterBox-facetHeader-collapse{
float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
+ font-size: 16;
}
+ .filterBox-facetHeader-remove {
+ // margin-left: auto;
+ float: right;
+ font-size: 16;
+ font-weight: bold;
+ }
}
-
-
+.filterbox-collpasedAndActive {
+ // left:100px;
+ text-indent: 18px;
+ // background-color: pink;
+ font-size: 12px;
+ font-weight: bold;
+}
+
+.sliderBox-outerDiv {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+// .sliderBox-outerDiv {
+// width: 30%;// width: calc(100% - 14px); // 14px accounts for handles that are at the max value of the slider that would extend outside the box
+// height: 40; // height: 100%;
+// border-radius: inherit;
+// display: flex;
+// flex-direction: column;
+// position: relative;
+// // background-color: yellow;
+// .slider-tracks {
+// top: 7px;
+// position: relative;
+// }
+// .slider-ticks {
+// position: relative;
+// }
+// .slider-handles {
+// top: 7px;
+// position: relative;
+// }
+// }
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index 63bd01b19..11c2fc86c 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -2,6 +2,7 @@ import React = require('react');
import { action, computed, observable, ObservableMap } from 'mobx';
import { observer } from 'mobx-react';
import Select from 'react-select';
+import { Checkbox, Tooltip } from '@material-ui/core';
import { Doc, DocListCast, Field, StrListCast } from '../../fields/Doc';
import { RichTextField } from '../../fields/RichTextField';
import { StrCast } from '../../fields/Types';
@@ -11,14 +12,21 @@ import './FilterPanel.scss';
import { FieldView } from './nodes/FieldView';
import { SearchBox } from './search/SearchBox';
import { undoable } from '../util/UndoManager';
-import { AiOutlineMinusSquare } from 'react-icons/ai';
+import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai';
import { CiCircleRemove } from 'react-icons/ci';
+import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider';
+import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components';
+import { DocumentOptions, FInfo } from '../documents/Documents';
+import { string32 } from 'pdfjs-dist/types/src/shared/util';
interface filterProps {
rootDoc: Doc;
}
+
@observer
export class FilterPanel extends React.Component<filterProps> {
+ private _documentOptions: DocumentOptions = new DocumentOptions();
+
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(FilterPanel, fieldKey);
}
@@ -43,6 +51,7 @@ export class FilterPanel extends React.Component<filterProps> {
if (targetDoc) {
SearchBox.foreachRecursiveDoc([this.targetDoc], (depth, doc) => allDocs.add(doc));
}
+ console.log('this is all Docs' + Array.from(allDocs));
return Array.from(allDocs);
}
@@ -58,23 +67,56 @@ export class FilterPanel extends React.Component<filterProps> {
.filter(key => key[0])
.filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode)
.sort();
+
+ // console.log('THIS IS HERE ' + Doc.UserDoc().color + 'space ' + Doc.UserDoc().color);
noviceFields.forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1));
+
+ console.log('this is novice fields ' + noviceFields + 'and this is sorted Keys ' + sortedKeys);
+
return [...noviceFields, ...sortedKeys];
}
+ @computed get rangeFilters() {
+ return StrListCast(this.targetDoc?._childFiltersByRanges).filter((filter, i) => !(i % 3));
+ }
+
/**
- * The current attributes selected to filter based on
+ * activeFilters( ) -- all filters that currently have a filter set on them in this document (ranges, and others)
+ * ["#tags::bob::check", "tags::joe::check", "width", "height"]
*/
@computed get activeFilters() {
- return StrListCast(this.targetDoc?._childFilters);
+ return StrListCast(this.targetDoc?._childFilters).concat(this.rangeFilters);
}
+ @computed get mapActiveFiltersToFacets() {
+ const filters = new Map<string, string>();
+ //this.targetDoc.docFilters
+ this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1], filter.split(Doc.FilterSep)[0]));
+ return filters;
+ }
+
+ //
+ // activeFacetHeaders() - just the facet names, not the rest of the filter
+ //
+ // this wants to return all the filter facets that have an existing filter set on them in order to show them in the rendered panel
+ // this set may overlap the selectedFilters
+ // if the components reloads, these will still exist and be shown
+
+ // ["#tags", "width", "height"]
+ //
+
+ @computed get activeFacetHeaders() {
+ const activeHeaders = new Array();
+ this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0]));
+
+ return activeHeaders;
+ }
/**
* @returns a string array of the current attributes
*/
- @computed get currentFacets() {
- return this.activeFilters.map(filter => filter.split(Doc.FilterSep)[0]);
- }
+ // @computed get currentFacets() {
+ // return this.activeFilters.map(filter => filter.split(Doc.FilterSep)[0]);
+ // }
gatherFieldValues(childDocs: Doc[], facetKey: string) {
const valueSet = new Set<string>();
@@ -86,6 +128,7 @@ export class FilterPanel extends React.Component<filterProps> {
newarray = [];
subDocs.forEach(t => {
const facetVal = t[facetKey];
+ // console.log("facetVal " + facetVal)
if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++;
facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field));
(facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal));
@@ -99,6 +142,7 @@ export class FilterPanel extends React.Component<filterProps> {
}
// }
// });
+
return { strings: Array.from(valueSet.keys()), rtFields };
}
@@ -107,40 +151,87 @@ export class FilterPanel extends React.Component<filterProps> {
Doc.setDocRangeFilter(this.targetDoc, filterName, undefined);
};
- @observable _chosenFacets = new ObservableMap<string, 'text' | 'checkbox' | 'slider' | 'range'>();
- @computed get activeFacets() {
- const facets = new Map<string, 'text' | 'checkbox' | 'slider' | 'range'>(this._chosenFacets);
- StrListCast(this.targetDoc?._childFilters).map(filter => facets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox'));
- setTimeout(() => StrListCast(this.targetDoc?._childFilters).map(action(filter => this._chosenFacets.set(filter.split(Doc.FilterSep)[0], filter.split(Doc.FilterSep)[2] === 'match' ? 'text' : 'checkbox'))));
- return facets;
+ // @observable _chosenFacets = new ObservableMap<string, 'text' | 'checkbox' | 'slider' | 'range'>();
+ @observable _chosenFacetsCollapse = new ObservableMap<string, boolean>();
+ @observable _collapseReturnKeys = new Array();
+
+ // this computed function gets the active filters and maps them to their headers
+
+ //
+ // activeRenderedFacetInfos()
+ // returns renderInfo for all user selected filters and for all existing filters set on the document
+ // Map("tags" => {"checkbox"},
+ // "width" => {"rangs", domain:[1978,1992]})
+ //
+
+ @computed get activeRenderedFacetInfos() {
+ return new Set(
+ Array.from(new Set(Array.from(this._selectedFacetHeaders).concat(this.activeFacetHeaders))).map(facetHeader => {
+ const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader);
+
+ let nonNumbers = 0;
+ let minVal = Number.MAX_VALUE,
+ maxVal = -Number.MAX_VALUE;
+ facetValues.strings.map(val => {
+ const num = val ? Number(val) : Number.NaN;
+ if (Number.isNaN(num)) {
+ val && nonNumbers++;
+ } else {
+ minVal = Math.min(num, minVal);
+ maxVal = Math.max(num, maxVal);
+ }
+ });
+
+ if (facetHeader === 'text') {
+ return { facetHeader: facetHeader, renderType: 'text' };
+ } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
+ const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1));
+ const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05)));
+ const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter
+ return { facetHeader: facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] };
+ } else {
+ return { facetHeader: facetHeader, renderType: 'checkbox' };
+ }
+ })
+ );
}
+
+ @observable _selectedFacetHeaders = new Set<string>();
+
/**
- * Responds to clicking the check box in the flyout menu
+ * user clicks on a filter facet because they want to see it.
+ * this adds this chosen filter to a set of user selected filters called: selectedFilters
+ * if this component reloads, then these filters will go away since they haven't been written to any Doc anywhere
+ *
+ * // this._selectedFacets.add(facetHeader); .. add to Set() not array
*/
+
@action
facetClick = (facetHeader: string) => {
- if (!this.targetDoc) return;
- const allCollectionDocs = this.targetDocChildren;
- const facetValues = this.gatherFieldValues(this.targetDocChildren, facetHeader);
+ // just when someone chooses a facet
- let nonNumbers = 0;
- let minVal = Number.MAX_VALUE,
- maxVal = -Number.MAX_VALUE;
- facetValues.strings.map(val => {
- const num = val ? Number(val) : Number.NaN;
- if (Number.isNaN(num)) {
- val && nonNumbers++;
- } else {
- minVal = Math.min(num, minVal);
- maxVal = Math.max(num, maxVal);
+ this._selectedFacetHeaders.add(facetHeader);
+
+ return;
+ };
+
+ @action
+ sortingCurrentFacetValues = (facetHeader: string) => {
+ this._collapseReturnKeys.splice(0);
+
+ Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => {
+ if (renderInfo.renderType === 'range' && renderInfo.facetHeader === facetHeader && renderInfo.range) {
+ this._collapseReturnKeys.push(renderInfo.range.map(number => number.toFixed(2)));
}
});
- if (facetHeader === 'text' || (facetValues.rtFields / allCollectionDocs.length > 0.1 && facetValues.strings.length > 20)) {
- this._chosenFacets.set(facetHeader, 'text');
- } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
- } else {
- this._chosenFacets.set(facetHeader, 'checkbox');
+
+ for (var key of this.facetValues(facetHeader)) {
+ if (this.mapActiveFiltersToFacets.get(key)) {
+ this._collapseReturnKeys.push(key);
+ }
}
+
+ return <div className=" filterbox-collpasedAndActive">{this._collapseReturnKeys.join(', ')}</div>;
};
facetValues = (facetHeader: string) => {
@@ -168,7 +259,24 @@ export class FilterPanel extends React.Component<filterProps> {
};
render() {
- const options = this._allFacets.filter(facet => this.currentFacets.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet }));
+ // console.log('this is frist one today ' + this._allFacets);
+ this._allFacets.forEach(element => console.log(element));
+ // const options = Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => pair[1].filterable ).map(facet => value: facet, label: facet) //this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet }));
+ // console.log('HEELLLLLL ' + DocumentOptions);
+
+ let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest'];
+
+ Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => {
+ if (pair[1].filterable) {
+ filteredOptions.push(pair[0]);
+ console.log('THIS IS FILTERABLE ALKDJFIIEII' + filteredOptions);
+ }
+ });
+
+ let options = filteredOptions.map(facet => ({ value: facet, label: facet }));
+
+ // Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => console.log('this is first piar ' + pair[0] + ' this is second piar ' + pair[1].filterable));
+
return (
<div className="filterBox-treeView">
<div className="filterBox-select">
@@ -188,29 +296,58 @@ export class FilterPanel extends React.Component<filterProps> {
</div>
<div className="filterBox-tree" key="tree">
- {Array.from(this.activeFacets.keys()).map(facetHeader => (
- <div>
- <div className="filterBox-facetHeader">
- <div className="filterBox-facetHeader-Header"> </div>
- {facetHeader.charAt(0).toUpperCase() + facetHeader.slice(1)}
+ {Array.from(this.activeRenderedFacetInfos.keys()).map(
+ (
+ renderInfo // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
+ ) => (
+ <div>
+ <div className="filterBox-facetHeader">
+ <div className="filterBox-facetHeader-Header"> </div>
+ {renderInfo.facetHeader.charAt(0).toUpperCase() + renderInfo.facetHeader.slice(1)}
+
+ <div
+ className="filterBox-facetHeader-collapse"
+ onClick={action(e => {
+ const collapseBoolValue = this._chosenFacetsCollapse.get(renderInfo.facetHeader);
+ this._chosenFacetsCollapse.set(renderInfo.facetHeader, !collapseBoolValue);
+ })}>
+ {this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? <AiOutlinePlusSquare /> : <AiOutlineMinusSquare />}
+ </div>
- <div className="filterBox-facetHeader-collapse">
- <AiOutlineMinusSquare />
- {/* <CiCircleRemove/> */}
+ <div
+ className="filterBox-facetHeader-remove"
+ onClick={action(e => {
+ for (var key of this.facetValues(renderInfo.facetHeader)) {
+ if (this.mapActiveFiltersToFacets.get(key)) {
+ Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove');
+ }
+ }
+ this._selectedFacetHeaders.delete(renderInfo.facetHeader);
+ this._chosenFacetsCollapse.delete(renderInfo.facetHeader);
+
+ if (renderInfo.domain) {
+ Doc.setDocRangeFilter(this.targetDoc, renderInfo.facetHeader, renderInfo.domain, 'remove');
+ }
+ })}>
+ <CiCircleRemove />{' '}
+ </div>
</div>
- </div>
- {this.displayFacetValueFilterUIs(this.activeFacets.get(facetHeader), facetHeader)}
- </div>
- ))}
+ {this._chosenFacetsCollapse.get(renderInfo.facetHeader)
+ ? this.sortingCurrentFacetValues(renderInfo.facetHeader)
+ : this.displayFacetValueFilterUIs(renderInfo.renderType, renderInfo.facetHeader, renderInfo.domain, renderInfo.range)}
+ {/* */}
+ </div>
+ )
+ )}
</div>
</div>
);
}
- private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string): React.ReactNode {
- switch (type) {
- case 'text':
+ private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string, renderInfoDomain?: number[] | undefined, renderInfoRange?: number[]): React.ReactNode {
+ switch (type /* renderInfo.type */) {
+ case 'text': // if (this.chosenFacets.get(facetHeader) === 'text')
return (
<input
placeholder={
@@ -241,6 +378,82 @@ export class FilterPanel extends React.Component<filterProps> {
</div>
);
});
+
+ case 'range':
+ const domain = renderInfoDomain;
+ const range = renderInfoRange;
+
+ if (range) {
+ console.log('this is info range ' + range[0] + ' , ' + range[1]);
+ }
+
+ if (domain) {
+ console.log('this is info domain ' + domain[0] + ', ' + domain[1]);
+
+ return (
+ <>
+ {/* <div className="sliderBox-outerDiv-checkBox" style={{ float: 'left' }}>
+ <Checkbox color="primary" onChange={action(() => console.log('on change'))} />
+ </div> */}
+
+ <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45, float: 'right' }}>
+ <Slider
+ mode={2}
+ step={Math.min(1, 0.1 * (domain[1] - domain[0]))}
+ domain={[domain[0], domain[1]]} // -1000, 1000
+ rootStyle={{ position: 'relative', width: '100%' }}
+ onChange={values => Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)}
+ values={renderInfoRange!}>
+ <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
+ <Handles>
+ {({ handles, activeHandleID, getHandleProps }) => (
+ <div className="slider-handles">
+ {handles.map((handle, i) => {
+ // const value = i === 0 ? defaultValues[0] : defaultValues[1];
+ return (
+ <div>
+ <Handle key={handle.id} handle={handle} domain={domain} isActive={handle.id === activeHandleID} getHandleProps={getHandleProps} />
+ </div>
+ );
+ })}
+ </div>
+ )}
+ </Handles>
+ <Tracks left={false} right={false}>
+ {({ tracks, getTrackProps }) => (
+ <div className="slider-tracks">
+ {tracks.map(({ id, source, target }) => (
+ <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
+ ))}
+ </div>
+ )}
+ </Tracks>
+ <Ticks count={5}>
+ {({ ticks }) => (
+ <div className="slider-ticks">
+ {ticks.map(tick => (
+ <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
+ ))}
+ </div>
+ )}
+ </Ticks>
+ </Slider>
+ </div>
+ </>
+ );
+ }
+
+ // case 'range'
+ // return <Slider ...
+ // return <slider domain={renderInfo.domain}> domain is number[] for min and max
+ // onChange = { ... Doc.setDocRangeFilter(this.targetDoc, facetHeader, [extendedMinVal, extendedMaxVal] ) }
+ //
+ // OR
+
+ // return <div>
+ // <slider domain={renderInfo.domain}> // domain is number[] for min and max
+ // <dimain changing handles >
+ // <?div
}
}
}
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index b3faff442..8a7f5132b 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -194,11 +194,11 @@ h1,
left: 0;
position: absolute;
z-index: 2;
- background-color: linen; //$light-gray;
+ // background-color: linen; //$light-gray;
- .editable-title {
- background-color: linen; //$light-gray;
- }
+ // .editable-title {
+ // background-color: linen; //$light-gray;
+ // }
}
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index cbe06a9c0..c81bc70b8 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -813,9 +813,8 @@ export class MainView extends React.Component {
{this.dockingContent}
{this._hideUI ? null : (
- <div className="mainView-propertiesDragger"
- key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), right: this.propertiesWidth() - 1}}>
- <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={StrCast(Doc.UserDoc().userColor)} size="sm" />
+ <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.Instance.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+ <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.Instance.userColor} size="sm" />
</div>
)}
<div className="properties-container" style={{ width: this.propertiesWidth() }}>
diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx
new file mode 100644
index 000000000..3ad28c418
--- /dev/null
+++ b/src/client/views/Palette.tsx
@@ -0,0 +1,69 @@
+import { IReactionDisposer, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Doc } from '../../fields/Doc';
+import { NumCast } from '../../fields/Types';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, emptyPath } from '../../Utils';
+import { Transform } from '../util/Transform';
+import { DocumentView } from './nodes/DocumentView';
+import './Palette.scss';
+
+export interface PaletteProps {
+ x: number;
+ y: number;
+ thumb: number[];
+ thumbDoc: Doc;
+}
+
+@observer
+export default class Palette extends React.Component<PaletteProps> {
+ private _selectedDisposer?: IReactionDisposer;
+ @observable private _selectedIndex: number = 0;
+
+ componentDidMount = () => {
+ this._selectedDisposer = reaction(
+ () => NumCast(this.props.thumbDoc.selectedIndex),
+ i => (this._selectedIndex = i),
+ { fireImmediately: true }
+ );
+ };
+
+ componentWillUnmount = () => {
+ this._selectedDisposer?.();
+ };
+
+ render() {
+ return (
+ <div className="palette-container" style={{ transform: `translate(${this.props.x}px, ${this.props.y}px)` }}>
+ <div className="palette-thumb" style={{ transform: `translate(${this.props.thumb[0] - this.props.x}px, ${this.props.thumb[1] - this.props.y}px)` }}>
+ <div className="palette-thumbContent" style={{ transform: `translate(-${this._selectedIndex * 50 + 10}px, 0px)` }}>
+ <DocumentView
+ Document={this.props.thumbDoc}
+ DataDoc={undefined}
+ addDocument={undefined}
+ addDocTab={returnFalse}
+ rootSelected={returnTrue}
+ pinToPres={emptyFunction}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ PanelWidth={() => window.screen.width}
+ PanelHeight={() => window.screen.height}
+ renderDepth={0}
+ isDocumentActive={returnTrue}
+ isContentActive={emptyFunction}
+ focus={emptyFunction}
+ docViewPath={returnEmptyDoclist}
+ styleProvider={returnEmptyString}
+ whenChildContentsActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ />
+ <div className="palette-cover" style={{ transform: `translate(${Math.max(0, this._selectedIndex) * 50.75 + 23}px, 0px)` }}></div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/src/client/views/PropertiesSection.tsx b/src/client/views/PropertiesSection.tsx
index 6fab0168b..b72e048df 100644
--- a/src/client/views/PropertiesSection.tsx
+++ b/src/client/views/PropertiesSection.tsx
@@ -49,7 +49,8 @@ export class PropertiesSection extends React.Component<PropertiesSectionProps> {
this.props.setIsOpen(!this.props.isOpen);
})}
style={{
- background: this.props.isOpen ? this.variantColor : this.backgroundColor,
+ background: this.variantColor,
+ // this.props.isOpen ? this.variantColor : this.backgroundColor,
color: this.color,
}}>
{this.props.title}
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index e3a481206..63b9b53c2 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -35,6 +35,20 @@
padding: 5px 10px;
}
+ .propertiesView-propAndInfoGrouping {
+ display: flex;
+ }
+
+ .propertiesView-info {
+ margin-top: 20;
+ margin-right: 10;
+ float: right;
+ font-size: 20;
+ path {
+ fill: white !important;
+ }
+ }
+
.propertiesView-sharing {
//border-bottom: 1px solid black;
//padding: 8.5px;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 9e054b876..9df04c862 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -191,7 +191,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
});
rows.push(
- <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: 'white', textAlign: 'center' }}>
+ <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.Instance.userBackgroundColor, textAlign: 'center' }}>
<EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
</div>
);
@@ -564,13 +564,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
}
@computed get currentType() {
+ // console.log("current type " + this.selectedDoc?.type)
+
const documentType = StrCast(this.selectedDoc?.type);
var currentType: string = documentType;
var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType);
return (
<div>
- <div className="propertiesView-wordType">Type</div>
+ Type
+ {/* <div className = "propertiesView-wordType">Type</div> */}
<div className="currentType">
<div className="currentType-icon">{this.currentComponent}</div>
@@ -1064,7 +1067,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = val), 'set width')
)}
{this.getNumber(
- 'X Coordinate',
+ 'X', //'X Coordinate',
' px',
-2000,
2000,
@@ -1072,7 +1075,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
undoable((val: string) => !isNaN(Number(val)) && (this.shapeXps = val), 'set x coord')
)}
{this.getNumber(
- 'Y Coordinate',
+ 'Y', //'Y Coordinate',
' px',
-2000,
2000,
@@ -1663,19 +1666,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="propertiesView-propAndInfoGrouping">
<div className="propertiesView-title" style={{ width: this.props.width }}>
Properties
- <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/')}>
- <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} color={StrCast(Doc.UserDoc().userColor)} />
+ <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
+ <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.Instance.userColor} />
</div>
</div>
</div>
<div className="propertiesView-name">{this.editableTitle}</div>
<div className="propertiesView-type"> {this.currentType} </div>
- {this.contextsSubMenu}
+ {this.optionsSubMenu}
{this.linksSubMenu}
{!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties}
{this.inkSubMenu}
- {this.optionsSubMenu}
+ {this.contextsSubMenu}
{this.fieldsSubMenu}
{isNovice ? null : this.sharingSubMenu}
{isNovice ? null : this.filtersSubMenu}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 716039568..f242ab5be 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1461,21 +1461,37 @@ export namespace Doc {
prevLayout === 'icon' && (doc.deiconifyLayout = undefined);
doc.layout_fieldKey = deiconify || 'layout';
}
- export function setDocRangeFilter(container: Opt<Doc>, key: string, range?: number[]) {
+ export function setDocRangeFilter(container: Opt<Doc>, key: string, range?: readonly number[], modifiers?: 'remove') { //, modifiers: 'remove' | 'set'
if (!container) return;
+
const childFiltersByRanges = Cast(container._childFiltersByRanges, listSpec('string'), []);
+
+
+
+
for (let i = 0; i < childFiltersByRanges.length; i += 3) {
if (childFiltersByRanges[i] === key) {
+ console.log("this is key inside childfilters by range " + key)
childFiltersByRanges.splice(i, 3);
+ console.log("this is child filters by range " + childFiltersByRanges)
break;
}
}
if (range !== undefined) {
+ console.log("in doc.ts in set range filter")
childFiltersByRanges.push(key);
childFiltersByRanges.push(range[0].toString());
childFiltersByRanges.push(range[1].toString());
container._childFiltersByRanges = new List<string>(childFiltersByRanges);
+ console.log("this is child filters by range "+ childFiltersByRanges[0] + "," + childFiltersByRanges[1] + "," + childFiltersByRanges[2])
+ console.log("this is new list " + container._childFiltersByRange)
+ }
+
+ if (modifiers){
+ childFiltersByRanges.splice(0,3)
+ container._childFiltersByRanges = new List<string>(childFiltersByRanges);
}
+ console.log("this is child filters by range END"+ childFiltersByRanges[0] + "," + childFiltersByRanges[1] + "," + childFiltersByRanges[2])
}
export const FilterSep = '::';
diff --git a/src/fields/IconField.ts b/src/fields/IconField.ts
new file mode 100644
index 000000000..76c4ddf1b
--- /dev/null
+++ b/src/fields/IconField.ts
@@ -0,0 +1,26 @@
+import { Deserializable } from "../client/util/SerializationHelper";
+import { serializable, primitive } from "serializr";
+import { ObjectField } from "./ObjectField";
+import { Copy, ToScriptString, ToString } from "./FieldSymbols";
+
+@Deserializable("icon")
+export class IconField extends ObjectField {
+ @serializable(primitive())
+ readonly icon: string;
+
+ constructor(icon: string) {
+ super();
+ this.icon = icon;
+ }
+
+ [Copy]() {
+ return new IconField(this.icon);
+ }
+
+ [ToScriptString]() {
+ return "invalid";
+ }
+ [ToString]() {
+ return "ICONfield";
+ }
+}
diff --git a/src/fields/PresField.ts b/src/fields/PresField.ts
new file mode 100644
index 000000000..f236a04fd
--- /dev/null
+++ b/src/fields/PresField.ts
@@ -0,0 +1,6 @@
+//insert code here
+import { ObjectField } from "./ObjectField";
+
+export abstract class PresField extends ObjectField {
+
+} \ No newline at end of file
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 584a7b432..c16a1c124 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -584,6 +584,7 @@ export class MobileInterface extends React.Component {
y: 400,
title: 'Collection ' + dashboardCount,
};
+
const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, 'row');