diff options
author | eperelm2 <emily_perelman@brown.edu> | 2023-08-10 18:46:04 -0400 |
---|---|---|
committer | eperelm2 <emily_perelman@brown.edu> | 2023-08-10 18:46:04 -0400 |
commit | 1c5bb5390ab9f198acde7d48aaa7d7d536f432cd (patch) | |
tree | b80984ea3b07d79925eeb7194ff6dedb6d38cf87 /src | |
parent | 082a280ed989007d84c8619438889c64a6fedb14 (diff) |
need to pull
Diffstat (limited to 'src')
-rw-r--r-- | src/.DS_Store | bin | 10244 -> 10244 bytes | |||
-rw-r--r-- | src/client/documents/Documents.ts | 11 | ||||
-rw-r--r-- | src/client/util/.ClientUtils.ts.icloud | bin | 0 -> 161 bytes | |||
-rw-r--r-- | src/client/util/.ReportManager.scss.icloud | bin | 0 -> 168 bytes | |||
-rw-r--r-- | src/client/util/.ReportManager.tsx.icloud | bin | 0 -> 167 bytes | |||
-rw-r--r-- | src/client/views/.Palette.scss.icloud | bin | 0 -> 160 bytes | |||
-rw-r--r-- | src/client/views/DashboardView.tsx | 78 | ||||
-rw-r--r-- | src/client/views/FilterPanel.tsx | 371 | ||||
-rw-r--r-- | src/client/views/Palette.tsx | 69 | ||||
-rw-r--r-- | src/client/views/nodes/.QueryBox.scss.icloud | bin | 0 -> 160 bytes | |||
-rw-r--r-- | src/client/views/nodes/.QueryBox.tsx.icloud | bin | 0 -> 160 bytes | |||
-rw-r--r-- | src/fields/.ListSpec.ts.icloud | bin | 0 -> 158 bytes | |||
-rw-r--r-- | src/fields/IconField.ts | 26 | ||||
-rw-r--r-- | src/fields/PresField.ts | 6 | ||||
-rw-r--r-- | src/mobile/MobileInterface.tsx | 1 | ||||
-rw-r--r-- | src/server/stats/.userLoginStats.csv.icloud | bin | 0 -> 168 bytes |
16 files changed, 329 insertions, 233 deletions
diff --git a/src/.DS_Store b/src/.DS_Store Binary files differindex 06389d6ae..946e85928 100644 --- a/src/.DS_Store +++ b/src/.DS_Store diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5d8ae19fc..533df5c11 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -74,6 +74,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) { @@ -88,7 +90,7 @@ class BoolInfo extends FInfo { class NumInfo extends FInfo { fieldType? = 'number'; values?: number[] = []; - constructor(d: string, readOnly?: boolean, values?: number[], filterable?:boolean) { + constructor(d: string, readOnly?: boolean, values?: number[], filterable?: boolean) { super(d, readOnly); this.values = values; } @@ -96,15 +98,16 @@ class NumInfo extends FInfo { class StrInfo extends FInfo { fieldType? = 'string'; values?: string[] = []; - constructor(d: string, readOnly?: boolean, values?: string[], filterable?:boolean) { + 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, filterable?:boolean, values?: Doc[] ) { + constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); this.values = values; } @@ -184,7 +187,7 @@ export class DocumentOptions { 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', false); - color?: STRt = new StrInfo('foreground color data doc'); + color?: STRt = new StrInfo('foreground color data doc', true); 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'); diff --git a/src/client/util/.ClientUtils.ts.icloud b/src/client/util/.ClientUtils.ts.icloud Binary files differnew file mode 100644 index 000000000..e5e477586 --- /dev/null +++ b/src/client/util/.ClientUtils.ts.icloud diff --git a/src/client/util/.ReportManager.scss.icloud b/src/client/util/.ReportManager.scss.icloud Binary files differnew file mode 100644 index 000000000..f5d34d292 --- /dev/null +++ b/src/client/util/.ReportManager.scss.icloud diff --git a/src/client/util/.ReportManager.tsx.icloud b/src/client/util/.ReportManager.tsx.icloud Binary files differnew file mode 100644 index 000000000..72924c53a --- /dev/null +++ b/src/client/util/.ReportManager.tsx.icloud diff --git a/src/client/views/.Palette.scss.icloud b/src/client/views/.Palette.scss.icloud Binary files differnew file mode 100644 index 000000000..49a2ac2da --- /dev/null +++ b/src/client/views/.Palette.scss.icloud diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index ae55c8ebf..d6c7b43d5 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -43,7 +43,7 @@ export class DashboardView extends React.Component { @observable private selectedDashboardGroup = DashboardGroup.MyDashboards; @observable private newDashboardName: string | undefined = undefined; - @observable private newDashboardColor: string | undefined = "#AFAFAF"; + @observable private newDashboardColor: string | undefined = '#AFAFAF'; @action abortCreateNewDashboard = () => { this.newDashboardName = undefined; }; @@ -100,24 +100,17 @@ export class DashboardView extends React.Component { const dashboardCount = DocListCast(Doc.MyDashboards.data).length + 1; const placeholder = `Dashboard ${dashboardCount}`; return ( - <div className="new-dashboard" - style={{ + <div + className="new-dashboard" + style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), - color: StrCast(Doc.UserDoc().userColor) - }} - > + color: StrCast(Doc.UserDoc().userColor), + }}> <div className="header">Create New Dashboard</div> - <EditableText - formLabel='Title' - placeholder={placeholder} - type={Type.SEC} - color={StrCast(Doc.UserDoc().userColor)} - setVal={val => this.setNewDashboardName(val as string)} - fillWidth - /> + <EditableText formLabel="Title" placeholder={placeholder} type={Type.SEC} color={StrCast(Doc.UserDoc().userColor)} setVal={val => this.setNewDashboardName(val as string)} fillWidth /> <ColorPicker - formLabel='Background' - colorPickerType='github' + formLabel="Background" + colorPickerType="github" type={Type.TERT} selectedColor={this.newDashboardColor} setSelectedColor={color => { @@ -165,21 +158,14 @@ export class DashboardView extends React.Component { }; render() { - const color = StrCast(Doc.UserDoc().userColor) - const variant = StrCast(Doc.UserDoc().userVariantColor) + const color = StrCast(Doc.UserDoc().userColor); + const variant = StrCast(Doc.UserDoc().userVariantColor); return ( <> <div className="dashboard-view"> <div className="left-menu"> - <Button - text={'My Dashboards'} - active={this.selectedDashboardGroup === DashboardGroup.MyDashboards} - color={color} - align={'flex-start'} - onClick={() => this.selectDashboardGroup(DashboardGroup.MyDashboards)} - fillWidth - /> - <Button + <Button text={'My Dashboards'} active={this.selectedDashboardGroup === DashboardGroup.MyDashboards} color={color} align={'flex-start'} onClick={() => this.selectDashboardGroup(DashboardGroup.MyDashboards)} fillWidth /> + <Button text={'Shared Dashboards' + ' (' + this.getDashboards(DashboardGroup.SharedDashboards).length + ')'} active={this.selectedDashboardGroup === DashboardGroup.SharedDashboards} color={this.getDashboards(DashboardGroup.SharedDashboards).some(dash => !DocListCast(Doc.MySharedDocs.viewed).includes(dash)) ? 'green' : color} @@ -196,11 +182,11 @@ export class DashboardView extends React.Component { .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && !['acl-Me', 'acl-Guest'].includes(key)) .some(key => dashboard[DocAcl][key] !== AclPrivate); return ( - <div - className="dashboard-container" - key={dashboard[Id]} + <div + className="dashboard-container" + key={dashboard[Id]} style={{ background: this.isUnviewedSharedDashboard(dashboard) && this.selectedDashboardGroup === DashboardGroup.SharedDashboards ? '#6CB982' : shared ? variant : '' }} - onContextMenu={e => this.onContextMenu(dashboard, e)} + onContextMenu={e => this.onContextMenu(dashboard, e)} onClick={e => this.clickDashboard(e, dashboard)}> <img src={ @@ -208,12 +194,7 @@ export class DashboardView extends React.Component { } /> <div className="info"> - <EditableText - type={Type.PRIM} - color={color} - val={StrCast(dashboard.title)} - setVal={val => (Doc.GetProto(dashboard).title = val)} - /> + <EditableText type={Type.PRIM} color={color} val={StrCast(dashboard.title)} setVal={val => (Doc.GetProto(dashboard).title = val)} /> {this.selectedDashboardGroup === DashboardGroup.SharedDashboards && this.isUnviewedSharedDashboard(dashboard) ? <div>unviewed</div> : <div></div>} <div className="more" @@ -229,10 +210,13 @@ export class DashboardView extends React.Component { <Button size={Size.SMALL} color={color} icon={<FontAwesomeIcon color={color} icon="bars" />} /> </div> </div> - <div className={`background`} style={{ - background: StrCast(Doc.UserDoc().userColor), - filter: 'opacity(0.2)' - }}/> + <div + className={`background`} + style={{ + background: StrCast(Doc.UserDoc().userColor), + filter: 'opacity(0.2)', + }} + /> <div className={'dashboard-status' + (shared ? '-shared' : '')}>{shared ? 'shared' : ''}</div> </div> ); @@ -243,10 +227,13 @@ export class DashboardView extends React.Component { this.setNewDashboardName(''); }}> + - <div className={`background`} style={{ - background: StrCast(Doc.UserDoc().userColor), - filter: 'opacity(0.2)' - }}/> + <div + className={`background`} + style={{ + background: StrCast(Doc.UserDoc().userColor), + filter: 'opacity(0.2)', + }} + /> </div> </div> </div> @@ -416,6 +403,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.tsx b/src/client/views/FilterPanel.tsx index 127708ca3..1a923a995 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -15,11 +15,12 @@ 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 } from '../documents/Documents'; -//slight bug when you don't click on background canvas before creating filter and the you click on the canvas +//slight bug when you don't click on background canvas before creating filter and the you click on the canvas - //use to -- & determine amount of sigfinict digits -- make all sections blue evn when collapsed - // transform switch to x and y not x coordinate and y coordinate +//use to -- & determine amount of sigfinict digits -- make all sections blue evn when collapsed +// transform switch to x and y not x coordinate and y coordinate interface filterProps { rootDoc: Doc; @@ -51,6 +52,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); } @@ -66,12 +68,17 @@ 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) ) + return StrListCast(this.targetDoc?._childFiltersByRanges).filter((filter, i) => !(i % 3)); } /** @@ -85,25 +92,24 @@ export class FilterPanel extends React.Component<filterProps> { @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 + 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 + // 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]) ) + const activeHeaders = new Array(); + this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0])); - return activeHeaders; } /** @@ -123,7 +129,7 @@ export class FilterPanel extends React.Component<filterProps> { newarray = []; subDocs.forEach(t => { const facetVal = t[facetKey]; - // console.log("facetVal " + facetVal) + // 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)); @@ -137,12 +143,10 @@ export class FilterPanel extends React.Component<filterProps> { } // } // }); - + return { strings: Array.from(valueSet.keys()), rtFields }; } - - public removeFilter = (filterName: string) => { Doc.setDocFilter(this.targetDoc, filterName, undefined, 'remove'); Doc.setDocRangeFilter(this.targetDoc, filterName, undefined); @@ -152,97 +156,85 @@ export class FilterPanel extends React.Component<filterProps> { @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]}) + // "width" => {"rangs", domain:[1978,1992]}) // - @computed get activeRenderedFacetInfos(){ - + @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'} + 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>(); /** - * user clicks on a filter facet because they want to see it. + * 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) => { // just when someone chooses a facet + facetClick = (facetHeader: string) => { + // just when someone chooses a facet this._selectedFacetHeaders.add(facetHeader); - return + return; }; - @action - sortingCurrentFacetValues = (facetHeader:string) => { - this._collapseReturnKeys.splice(0) + sortingCurrentFacetValues = (facetHeader: string) => { + this._collapseReturnKeys.splice(0); Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => { - if ( renderInfo.renderType === "range" && renderInfo.facetHeader === facetHeader) { - this._collapseReturnKeys.push(renderInfo.range) - - } - }) - - 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>) - } - - + if (renderInfo.renderType === 'range' && renderInfo.facetHeader === facetHeader) { + this._collapseReturnKeys.push(renderInfo.range); + } + }); + + 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) => { const allCollectionDocs = new Set<Doc>(); SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); @@ -267,9 +259,15 @@ export class FilterPanel extends React.Component<filterProps> { return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2)); }; - render() { + // console.log('this is frist one today ' + this._allFacets); + this._allFacets.forEach(element => console.log(element)); const options = this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); + // console.log('HEELLLLLL ' + DocumentOptions); + + const freeformOptions: DocumentOptions = {}; + + console.log('wht is this ' + freeformOptions.author); return ( <div className="filterBox-treeView"> @@ -290,50 +288,57 @@ export class FilterPanel extends React.Component<filterProps> { </div> <div className="filterBox-tree" key="tree"> - {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-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> + {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-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> + + {this._chosenFacetsCollapse.get(renderInfo.facetHeader) + ? this.sortingCurrentFacetValues(renderInfo.facetHeader) + : this.displayFacetValueFilterUIs(renderInfo.renderType, renderInfo.facetHeader, renderInfo.domain, renderInfo.range)} + {/* */} </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, renderInfoDomain?: number[] | undefined, renderInfoRange?: number[] ): React.ReactNode { - switch (type /* renderInfo.type */ ) { + 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 @@ -353,82 +358,80 @@ export class FilterPanel extends React.Component<filterProps> { <div> <input style={{ width: 20, marginLeft: 20 }} - checked={ - StrListCast(this.targetDoc._childFilters) - .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' + checked={ + StrListCast(this.targetDoc._childFilters) + .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) + ?.split(Doc.FilterSep)[2] === 'check' } type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} /> {facetValue} </div> ); - }) - - case 'range': - const domain = renderInfoDomain; - if (domain){ - return( - <div className = "sliderBox-outerDiv" style = {{width: "95%", height: 45 }}> - <Slider mode={2} step={Math.min(1, 0.1 * (domain[1] - domain[0]))} domain={[-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': + const domain = renderInfoDomain; + if (domain) { + return ( + <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45 }}> + <Slider + mode={2} + step={Math.min(1, 0.1 * (domain[1] - domain[0]))} + domain={[-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 - - ; + // 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/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/nodes/.QueryBox.scss.icloud b/src/client/views/nodes/.QueryBox.scss.icloud Binary files differnew file mode 100644 index 000000000..26ba46a75 --- /dev/null +++ b/src/client/views/nodes/.QueryBox.scss.icloud diff --git a/src/client/views/nodes/.QueryBox.tsx.icloud b/src/client/views/nodes/.QueryBox.tsx.icloud Binary files differnew file mode 100644 index 000000000..5930b1e0e --- /dev/null +++ b/src/client/views/nodes/.QueryBox.tsx.icloud diff --git a/src/fields/.ListSpec.ts.icloud b/src/fields/.ListSpec.ts.icloud Binary files differnew file mode 100644 index 000000000..2fbd1858e --- /dev/null +++ b/src/fields/.ListSpec.ts.icloud 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'); diff --git a/src/server/stats/.userLoginStats.csv.icloud b/src/server/stats/.userLoginStats.csv.icloud Binary files differnew file mode 100644 index 000000000..4a95297e8 --- /dev/null +++ b/src/server/stats/.userLoginStats.csv.icloud |