aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionFreeFormView.scss104
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx20
-rw-r--r--src/client/views/collections/CollectionPDFView.scss27
-rw-r--r--src/client/views/collections/CollectionPDFView.tsx26
-rw-r--r--src/client/views/collections/CollectionSchemaView.scss383
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx32
-rw-r--r--src/client/views/collections/CollectionTreeView.scss32
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx25
-rw-r--r--src/client/views/collections/CollectionVideoView.scss40
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx86
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/collections/MarqueeView.tsx49
-rw-r--r--src/client/views/collections/PreviewCursor.tsx8
13 files changed, 556 insertions, 285 deletions
diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss
index d472cc5c4..9c7a03b52 100644
--- a/src/client/views/collections/CollectionFreeFormView.scss
+++ b/src/client/views/collections/CollectionFreeFormView.scss
@@ -1,29 +1,56 @@
+@import "../global_variables";
+
.collectionfreeformview-container {
+ .collectionfreeformview > .jsx-parser {
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ }
- .collectionfreeformview > .jsx-parser{
- position:absolute;
- height: 100%;
- width: 100%;
- }
-
- border-style: solid;
- box-sizing: border-box;
- position: relative;
+ //nested freeform views
+ .collectionfreeformview-container {
+ // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px),
+ // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px);
+ // background-size: 30px 30px;
+ }
+
+ border: 0px solid $light-color-secondary;
+ border-radius: $border-radius;
+ box-sizing: border-box;
+ position: relative;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
+ .collectionfreeformview {
+ position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
- overflow: hidden;
- .collectionfreeformview {
- position: absolute;
- top: 0;
- left: 0;
- width:100%;
- height: 100%;
- }
+ }
}
.collectionfreeformview-overlay {
+ .collectionfreeformview > .jsx-parser {
+ position: absolute;
+ height: 100%;
+ }
+ .formattedTextBox-cont {
+ background: $light-color-secondary;
+ }
+ position:absolute;
+ border: 0px solid transparent;
+ border-radius: $border-radius;
+ overflow: hidden;
+ box-sizing: border-box;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ .collectionfreeformview {
.collectionfreeformview > .jsx-parser{
position:absolute;
height: 100%;
@@ -32,26 +59,39 @@
background:yellow;
}
- border-style: solid;
- box-sizing: border-box;
+ // overflow: hidden;
+ // border-style: solid;
+ // box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
- overflow: hidden;
- .collectionfreeformview {
- position: absolute;
- top: 0;
- left: 0;
- width:100%;
- height: 100%;
- }
+ }
}
+// selection border...?
.border {
- border-style: solid;
- box-sizing: border-box;
- width: 100%;
- height: 100%;
-} \ No newline at end of file
+ border-style: solid;
+ box-sizing: border-box;
+ width: 98%;
+ height: 98%;
+ border-radius: $border-radius;
+}
+
+//this is an animation for the blinking cursor!
+@keyframes blink {
+ 0% {
+ opacity: 0;
+ }
+ 49% {
+ opacity: 0;
+ }
+ 50% {
+ opacity: 1;
+ }
+}
+
+#prevCursor {
+ animation: blink 1s infinite;
+}
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 3d5326552..5c0eab392 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -52,13 +52,13 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
public getActiveDocuments = () => {
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
+ var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
let active: Document[] = [];
if (lvalue && lvalue != FieldWaiting) {
lvalue.Data.map(doc => {
- var page = doc.GetNumber(KeyStore.Page, 0);
- if (page == curPage || page == 0) {
+ var page = doc.GetNumber(KeyStore.Page, -1);
+ if (page == curPage || page == -1) {
active.push(doc);
}
})
@@ -126,7 +126,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
onPointerUp = (e: PointerEvent): void => {
e.stopPropagation();
- if (!this.MarqueeVisible && Math.abs(this.DownX - e.clientX) < 3 && Math.abs(this.DownY - e.clientY) < 3) {
+ if (Math.abs(this.DownX - e.clientX) < 4 && Math.abs(this.DownY - e.clientY) < 4) {
//show preview text cursor on tap
this.PreviewCursorVisible = true;
//select is not already selected
@@ -140,9 +140,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
onPointerMove = (e: PointerEvent): void => {
if (!e.cancelBubble && this.props.active()) {
- if (e.buttons != 2 && !e.altKey && !e.metaKey && !this.MarqueeVisible) {
+ if (e.buttons == 1 && !e.altKey && !e.metaKey) {
this.MarqueeVisible = true;
- this.PreviewCursorVisible = false;
}
if (this.MarqueeVisible) {
e.stopPropagation();
@@ -152,7 +151,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
- this.PreviewCursorVisible = false;
this.SetPan(x - dx, y - dy);
this._lastX = e.pageX;
this._lastY = e.pageY;
@@ -272,7 +270,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
@computed
get views() {
- var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1);
+ var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
if (lvalue && lvalue != FieldWaiting) {
return lvalue.Data.map(doc => {
@@ -343,10 +341,12 @@ export class CollectionFreeFormView extends CollectionViewBase {
ref={this._canvasRef}>
{this.backgroundView}
<InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} />
- <PreviewCursor container={this} addLiveTextDocuemnt={this.addLiveTextBox} getTransform={this.getTransform} />
+ <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} />
{this.views}
</div>
- <MarqueeView container={this} activeDocuemnts={this.getActiveDocuments} selectDocuments={this.selectDocuments} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} getMarqueeTransform={this.getMarqueeTransform} getTransform={this.getTransform} />
+ <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
+ addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
+ getMarqueeTransform={this.getMarqueeTransform} getTransform={this.getTransform} />
{this.overlayView}
</div>
);
diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss
new file mode 100644
index 000000000..0144625c1
--- /dev/null
+++ b/src/client/views/collections/CollectionPDFView.scss
@@ -0,0 +1,27 @@
+.collectionPdfView-buttonTray {
+ top : 25px;
+ left : 20px;
+ position: relative;
+ transform-origin: left top;
+ position: absolute;
+}
+.collectionPdfView-cont{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+
+}
+.collectionPdfView-backward {
+ color : white;
+ top :0px;
+ left : 0px;
+ position: absolute;
+ background-color: rgba(50, 50, 50, 0.2);
+}
+.collectionPdfView-forward {
+ color : white;
+ top :0px;
+ left : 35px;
+ position: absolute;
+ background-color: rgba(50, 50, 50, 0.2);
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index f22c07060..124d82c8b 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,10 +1,11 @@
-import { action, computed } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import { ContextMenu } from "../ContextMenu";
import { CollectionView, CollectionViewType } from "./CollectionView";
import { CollectionViewProps } from "./CollectionViewBase";
+import "./CollectionPDFView.scss"
import React = require("react");
import { FieldId } from "../../../fields/Field";
@@ -18,22 +19,23 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
}
- public SelectedDocs: FieldId[] = []
- @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0;
- @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0;
+ private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); }
+ private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); }
+ @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : -1;
+ @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : -1;
- @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); }
- @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); }
- @computed private get uIButtons() {
+ private get uIButtons() {
+ let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]);
return (
- <div className="pdfBox-buttonTray" key="tray">
- <button className="pdfButton" onClick={this.onPageBack}>{"<"}</button>
- <button className="pdfButton" onClick={this.onPageForward}>{">"}</button>
+ <div className="collectionPdfView-buttonTray" key="tray" style={{ transform: `scale(${scaling}, ${scaling})` }}>
+ <button className="collectionPdfView-backward" onClick={this.onPageBack}>{"<"}</button>
+ <button className="collectionPdfView-forward" onClick={this.onPageForward}>{">"}</button>
</div>);
}
// "inherited" CollectionView API starts here...
-
+ @observable
+ public SelectedDocs: FieldId[] = []
public active: () => boolean = () => CollectionView.Active(this);
addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
@@ -49,7 +51,7 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
get subView(): any { return CollectionView.SubView(this); }
render() {
- return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
+ return (<div className="collectionPdfView-cont" onContextMenu={this.specificContextMenu}>
{this.subView}
{this.props.isSelected() ? this.uIButtons : (null)}
</div>)
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index d40e6d314..0d615dc01 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,185 +1,162 @@
-
+@import "../global_variables";
.collectionSchemaView-container {
- border-style: solid;
+ border: 1px solid $intermediate-color;
+ border-radius: $border-radius;
+ box-sizing: border-box;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+.collectionSchemaView-content {
+ position: absolute;
+ height:100%;
+ width:100%;
+ overflow:auto;
+}
+ .collectionSchemaView-previewRegion {
+ position: relative;
+ background: $light-color;
+ float: left;
+ height: 100%;
+ }
+ .collectionSchemaView-previewHandle {
+ position: absolute;
+ height: 37px;
+ width: 20px;
+ z-index: 20;
+ right: 0;
+ top: 0;
+ background: $main-accent;
+ }
+ .collectionSchemaView-dividerDragger {
+ position: relative;
box-sizing: border-box;
+ border-left: 1px solid $intermediate-color;
+ border-right: 1px solid $intermediate-color;
+ float: left;
+ height: 100%;
+ }
+ .collectionSchemaView-tableContainer {
+ position: relative;
+ float: left;
+ height: 100%;
+ }
+
+ .ReactTable {
position: absolute;
+ // display: inline-block;
+ // overflow: auto;
width: 100%;
height: 100%;
- .collectionSchemaView-previewRegion {
- position: relative;
- background: black;
- float: left;
- height: 100%;
- }
- .collectionSchemaView-previewHandle {
- position: absolute;
- height: 37px;
- width: 20px;
- z-index: 20;
- right: 0;
- top: 0;
- background: Black ;
- }
- .collectionSchemaView-dividerDragger{
- position: relative;
- background: black;
- float: left;
- height: 100%;
- }
- .collectionSchemaView-tableContainer {
+ background: $light-color;
+ box-sizing: border-box;
+ border: none !important;
+ .rt-table {
+ overflow-y: auto;
+ overflow-x: auto;
+ height: 100%;
+ display: -webkit-inline-box;
+ direction: ltr;
+ // direction:rtl;
+ // display:block;
+ }
+ .rt-tbody {
+ //direction: ltr;
+ direction: rtl;
+ }
+ .rt-tr-group {
+ direction: ltr;
+ max-height: 44px;
+ }
+ .rt-td {
+ border-width: 1px;
+ border-right-color: $intermediate-color;
+ .imageBox-cont {
position: relative;
- float: left;
- height: 100%;
- }
-
- .ReactTable {
- position: absolute;
- // display: inline-block;
- // overflow: auto;
- width: 100%;
+ max-height: 100%;
+ }
+ .imageBox-cont img {
+ object-fit: contain;
+ max-width: 100%;
height: 100%;
- background: white;
- box-sizing: border-box;
- .rt-table {
- overflow-y: auto;
- overflow-x: auto;
- height: 100%;
-
- display: -webkit-inline-box;
- direction: ltr;
- // direction:rtl;
- // display:block;
- }
- .rt-tbody {
- //direction: ltr;
- direction: rtl;
- }
- .rt-tr-group {
- direction: ltr;
- max-height: 44px;
- }
- .rt-td {
- border-width: 1;
- border-right-color: #aaa;
- .imageBox-cont {
- position:relative;
- max-height:100%;
- }
- .imageBox-cont img {
- object-fit: contain;
- max-width: 100%;
- height: 100%
- }
- }
- .rt-tr-group {
- border-width: 1;
- border-bottom-color: #aaa
- }
- }
- .ReactTable .rt-thead.-header {
- background:grey;
- }
- .ReactTable .rt-th, .ReactTable .rt-td {
- max-height: 44;
- padding: 3px 7px;
- }
- .ReactTable .rt-tbody .rt-tr-group:last-child {
- border-bottom: grey;
- border-bottom-style: solid;
- border-bottom-width: 1;
- }
- .documentView-node:first-child {
- background: grey;
- .imageBox-cont img {
- object-fit: contain;
- }
- }
+ }
+ .videobox-cont {
+ object-fit: contain;
+ width:auto;
+ height: 100%;
+ }
+ }
+ }
+ .ReactTable .rt-thead.-header {
+ background: $intermediate-color;
+ color: $light-color;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ font-size: 12px;
+ height: 30px;
+ padding-top: 4px;
+ }
+ .ReactTable .rt-th,
+ .ReactTable .rt-td {
+ max-height: 44;
+ padding: 3px 7px;
+ font-size: 13px;
+ text-align: center;
+ }
+ .ReactTable .rt-tbody .rt-tr-group:last-child {
+ border-bottom: $intermediate-color;
+ border-bottom-style: solid;
+ border-bottom-width: 1;
+ }
+ .documentView-node:first-child {
+ background: $light-color;
+ .imageBox-cont img {
+ object-fit: contain;
+ }
+ }
}
.Resizer {
- box-sizing: border-box;
- background: #000;
- opacity: 0.5;
- z-index: 1;
- background-clip: padding-box;
- &.horizontal {
- height: 11px;
- margin: -5px 0;
- border-top: 5px solid rgba(255, 255, 255, 0);
- border-bottom: 5px solid rgba(255, 255, 255, 0);
- cursor: row-resize;
- width: 100%;
- &:hover {
- border-top: 5px solid rgba(0, 0, 0, 0.5);
- border-bottom: 5px solid rgba(0, 0, 0, 0.5);
- }
- }
- &.vertical {
- width: 11px;
- margin: 0 -5px;
- border-left: 5px solid rgba(255, 255, 255, 0);
- border-right: 5px solid rgba(255, 255, 255, 0);
- cursor: col-resize;
- &:hover {
- border-left: 5px solid rgba(0, 0, 0, 0.5);
- border-right: 5px solid rgba(0, 0, 0, 0.5);
- }
- }
+ box-sizing: border-box;
+ background: #000;
+ opacity: 0.5;
+ z-index: 1;
+ background-clip: padding-box;
+ &.horizontal {
+ height: 11px;
+ margin: -5px 0;
+ border-top: 5px solid rgba(255, 255, 255, 0);
+ border-bottom: 5px solid rgba(255, 255, 255, 0);
+ cursor: row-resize;
+ width: 100%;
&:hover {
- -webkit-transition: all 2s ease;
- transition: all 2s ease;
- }
+ border-top: 5px solid rgba(0, 0, 0, 0.5);
+ border-bottom: 5px solid rgba(0, 0, 0, 0.5);
+ }
+ }
+ &.vertical {
+ width: 11px;
+ margin: 0 -5px;
+ border-left: 5px solid rgba(255, 255, 255, 0);
+ border-right: 5px solid rgba(255, 255, 255, 0);
+ cursor: col-resize;
+ &:hover {
+ border-left: 5px solid rgba(0, 0, 0, 0.5);
+ border-right: 5px solid rgba(0, 0, 0, 0.5);
+ }
+ }
+ &:hover {
+ -webkit-transition: all 2s ease;
+ transition: all 2s ease;
+ }
}
.vertical {
- section {
- width: 100vh;
- height: 100vh;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- }
- header {
- padding: 1rem;
- background: #eee;
- }
- footer {
- padding: 1rem;
- background: #eee;
- }
-}
-
-.horizontal {
- section {
- width: 100vh;
- height: 100vh;
- display: flex;
- flex-direction: column;
- }
- header {
- padding: 1rem;
- background: #eee;
- }
- footer {
- padding: 1rem;
- background: #eee;
- }
-}
-
-.parent {
- width: 100%;
- height: 100%;
- -webkit-box-flex: 1;
- -webkit-flex: 1;
- -ms-flex: 1;
- flex: 1;
+ section {
+ width: 100vh;
+ height: 100vh;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
@@ -189,19 +166,71 @@
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
+ }
+ header {
+ padding: 1rem;
+ background: #eee;
+ }
+ footer {
+ padding: 1rem;
+ background: #eee;
+ }
+}
+
+.horizontal {
+ section {
+ width: 100vh;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+ header {
+ padding: 1rem;
+ background: #eee;
+ }
+ footer {
+ padding: 1rem;
+ background: #eee;
+ }
+}
+
+.parent {
+ width: 100%;
+ height: 100%;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
}
.header {
- background: #aaa;
- height: 3rem;
- line-height: 3rem;
+ background: #aaa;
+ height: 3rem;
+ line-height: 3rem;
}
.wrapper {
- background: #ffa;
- margin: 5rem;
- -webkit-box-flex: 1;
- -webkit-flex: 1;
- -ms-flex: 1;
- flex: 1;
-} \ No newline at end of file
+ background: #ffa;
+ margin: 5rem;
+ -webkit-box-flex: 1;
+ -webkit-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+}
+
+.-even {
+ background: $light-color !important;
+}
+
+.-odd {
+ background: $light-color-secondary !important;
+}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 04f017378..8c1aeef2c 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,5 +1,5 @@
import React = require("react")
-import { action, observable } from "mobx";
+import { action, observable, computed } from "mobx";
import { observer } from "mobx-react";
import Measure from "react-measure";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
@@ -24,14 +24,14 @@ import { setupDrag } from "../../util/DragManager";
@observer
export class CollectionSchemaView extends CollectionViewBase {
private _mainCont = React.createRef<HTMLDivElement>();
- private DIVIDER_WIDTH = 5;
+ private DIVIDER_WIDTH = 4;
@observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView
@observable _dividerX = 0;
@observable _panelWidth = 0;
@observable _panelHeight = 0;
@observable _selectedIndex = 0;
- @observable _splitPercentage: number = 50;
+ @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
renderCell = (rowProps: CellInfo) => {
let props: FieldViewProps = {
@@ -49,7 +49,7 @@ export class CollectionSchemaView extends CollectionViewBase {
let reference = React.createRef<HTMLDivElement>();
let onItemDown = setupDrag(reference, () => props.doc);
return (
- <div onPointerDown={onItemDown} key={props.doc.Id} ref={reference}>
+ <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "36px" }} key={props.doc.Id} ref={reference}>
<EditableView contents={contents}
height={36} GetValue={() => {
let field = props.doc.Get(props.fieldKey);
@@ -89,7 +89,8 @@ export class CollectionSchemaView extends CollectionViewBase {
return {
onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
that._selectedIndex = rowInfo.index;
- this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize
+ // bcz - ugh - needed to force Measure to do its thing and call onResize
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage - 0.05)
if (handleOriginal) {
handleOriginal()
@@ -106,18 +107,18 @@ export class CollectionSchemaView extends CollectionViewBase {
@action
onDividerMove = (e: PointerEvent): void => {
let nativeWidth = this._mainCont.current!.getBoundingClientRect();
- this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100);
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100));
}
@action
onDividerUp = (e: PointerEvent): void => {
document.removeEventListener("pointermove", this.onDividerMove);
document.removeEventListener('pointerup', this.onDividerUp);
- if (this._startSplitPercent == this._splitPercentage) {
- this._splitPercentage = this._splitPercentage == 1 ? 66 : 100;
+ if (this._startSplitPercent == this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
}
}
onDividerDown = (e: React.PointerEvent) => {
- this._startSplitPercent = this._splitPercentage;
+ this._startSplitPercent = this.splitPercentage;
e.stopPropagation();
e.preventDefault();
document.addEventListener("pointermove", this.onDividerMove);
@@ -134,12 +135,12 @@ export class CollectionSchemaView extends CollectionViewBase {
e.preventDefault();
document.removeEventListener("pointermove", this.onExpanderMove);
document.removeEventListener('pointerup', this.onExpanderUp);
- if (this._startSplitPercent == this._splitPercentage) {
- this._splitPercentage = this._splitPercentage == 100 ? 66 : 100;
+ if (this._startSplitPercent == this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
}
}
onExpanderDown = (e: React.PointerEvent) => {
- this._startSplitPercent = this._splitPercentage;
+ this._startSplitPercent = this.splitPercentage;
e.stopPropagation();
e.preventDefault();
document.addEventListener("pointermove", this.onExpanderMove);
@@ -203,7 +204,7 @@ export class CollectionSchemaView extends CollectionViewBase {
)
let previewHandle = !this.props.active() ? (null) : (
<div className="collectionSchemaView-previewHandle" onPointerDown={this.onExpanderDown} />);
- let dividerDragger = this._splitPercentage == 100 ? (null) :
+ let dividerDragger = this.splitPercentage == 0 ? (null) :
<div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
return (
<div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
@@ -213,7 +214,8 @@ export class CollectionSchemaView extends CollectionViewBase {
this._panelHeight = r.entry.height;
})}>
{({ measureRef }) =>
- <div ref={measureRef} className="collectionSchemaView-tableContainer" style={{ width: `${this._splitPercentage}%` }}>
+ <div ref={measureRef} className="collectionSchemaView-tableContainer"
+ style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
<ReactTable
data={children}
pageSize={children.length}
@@ -235,7 +237,7 @@ export class CollectionSchemaView extends CollectionViewBase {
}
</Measure>
{dividerDragger}
- <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)` }}>
+ <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
{content}
</div>
{previewHandle}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index f8d580a7b..fa0f1c761 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,16 +1,25 @@
+@import "../global_variables";
#body {
padding: 20px;
- background: #bbbbbb;
+ background: $light-color-secondary;
+ font-size: 13px;
+ overflow: scroll;
}
ul {
list-style: none;
+ padding-left: 20px;
}
li {
margin: 5px 0;
}
+.collection-child {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
.no-indent {
padding-left: 0;
}
@@ -18,10 +27,17 @@ li {
.bullet {
width: 1.5em;
display: inline-block;
+ color: $intermediate-color;
+}
+
+.coll-title {
+ font-size: 24px;
+ margin-bottom: 20px;
}
.collectionTreeView-dropTarget {
- border-style: solid;
+ border: 0px solid transparent;
+ border-radius: $border-radius;
box-sizing: border-box;
height: 100%;
}
@@ -30,8 +46,16 @@ li {
display: inline-table;
}
+.docContainer:hover {
+ .delete-button {
+ display: inline;
+ }
+}
+
.delete-button {
- color: #999999;
+ color: $intermediate-color;
float: right;
- margin-left: 1em;
+ margin-left: 15px;
+ margin-top: 3px;
+ display: none;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8b06d9ac4..80fc89712 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -12,6 +12,10 @@ import { setupDrag } from "../../util/DragManager";
import { FieldWaiting } from "../../../fields/Field";
import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faTrashAlt, faCaretRight, faCaretDown } from '@fortawesome/free-solid-svg-icons';
+
export interface TreeViewProps {
document: Document;
deleteDoc: (doc: Document) => void;
@@ -23,6 +27,10 @@ export enum BulletType {
List
}
+library.add(faTrashAlt);
+library.add(faCaretDown);
+library.add(faCaretRight);
+
@observer
/**
* Component that takes in a document prop and a boolean whether it's collapsed or not.
@@ -50,11 +58,11 @@ class TreeView extends React.Component<TreeViewProps> {
switch (type) {
case BulletType.Collapsed:
- return <div className="bullet" onClick={onClicked}>&#9654;</div>
+ return <div className="bullet" onClick={onClicked}><FontAwesomeIcon icon="caret-right" /></div>
case BulletType.Collapsible:
- return <div className="bullet" onClick={onClicked}>&#9660;</div>
+ return <div className="bullet" onClick={onClicked}><FontAwesomeIcon icon="caret-down" /></div>
case BulletType.List:
- return <div className="bullet">&mdash;</div>
+ return <div className="bullet"></div>
}
}
@@ -79,7 +87,7 @@ class TreeView extends React.Component<TreeViewProps> {
this.props.document.SetData(KeyStore.Title, value, TextField);
return true;
}} />
- <div className="delete-button" onClick={this.delete}>x</div>
+ <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>
</div >
}
@@ -101,7 +109,7 @@ class TreeView extends React.Component<TreeViewProps> {
<TreeView document={value} deleteDoc={this.remove} />)
)
subView =
- <li key={this.props.document.Id} >
+ <li className="collection-child" key={this.props.document.Id} >
{this.renderBullet(BulletType.Collapsible)}
{titleElement}
<ul key={this.props.document.Id}>
@@ -109,7 +117,7 @@ class TreeView extends React.Component<TreeViewProps> {
</ul>
</li>
} else {
- subView = <li key={this.props.document.Id}>
+ subView = <li className="collection-child" key={this.props.document.Id}>
{this.renderBullet(BulletType.Collapsed)}
{titleElement}
</li>
@@ -157,7 +165,7 @@ export class CollectionTreeView extends CollectionViewBase {
return (
<div id="body" className="collectionTreeView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
- <h3>
+ <div className="coll-title">
<EditableView contents={titleStr}
height={72} GetValue={() => {
return this.props.Document.Title;
@@ -165,7 +173,8 @@ export class CollectionTreeView extends CollectionViewBase {
this.props.Document.SetData(KeyStore.Title, value, TextField);
return true;
}} />
- </h3>
+ </div>
+ <hr />
<ul className="no-indent">
{childrenElement}
</ul>
diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss
new file mode 100644
index 000000000..cbb981b13
--- /dev/null
+++ b/src/client/views/collections/CollectionVideoView.scss
@@ -0,0 +1,40 @@
+
+.collectionVideoView-cont{
+ width: 100%;
+ height: 100%;
+ position: absolute;
+
+}
+.collectionVideoView-time{
+ color : white;
+ top :25px;
+ left : 25px;
+ position: absolute;
+ background-color: rgba(50, 50, 50, 0.2);
+ transform-origin: left top;
+}
+.collectionVideoView-play {
+ width: 25px;
+ height: 20px;
+ bottom: 25px;
+ left : 25px;
+ position: absolute;
+ color : white;
+ background-color: rgba(50, 50, 50, 0.2);
+ border-radius: 4px;
+ text-align: center;
+ transform-origin: left bottom;
+}
+.collectionVideoView-full {
+ width: 25px;
+ height: 20px;
+ bottom: 25px;
+ right : 25px;
+ position: absolute;
+ color : white;
+ background-color: rgba(50, 50, 50, 0.2);
+ border-radius: 4px;
+ text-align: center;
+ transform-origin: right bottom;
+
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index a6471f53c..b64ef3c07 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -1,4 +1,4 @@
-import { action, computed } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
@@ -7,6 +7,7 @@ import { CollectionView, CollectionViewType } from "./CollectionView";
import { CollectionViewProps } from "./CollectionViewBase";
import React = require("react");
import { FieldId } from "../../../fields/Field";
+import "./CollectionVideoView.scss"
@observer
@@ -18,14 +19,29 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
}
- public SelectedDocs: FieldId[] = []
- @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0;
- @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0;
+ private _mainCont = React.createRef<HTMLDivElement>();
+
+ private get uIButtons() {
+ let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]);
+ return ([
+ <div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+ <span>{"" + Math.round(this.ctime)}</span>
+ <span style={{ fontSize: 8 }}>{" " + Math.round((this.ctime - Math.trunc(this.ctime)) * 100)}</span>
+ </div>,
+ <div className="collectionVideoView-play" key="play" onPointerDown={this.onPlayDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+ {this.playing ? "\"" : ">"}
+ </div>,
+ <div className="collectionVideoView-full" key="full" onPointerDown={this.onFullDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+ F
+ </div>
+ ]);
+ }
+
- @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); }
- @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); }
// "inherited" CollectionView API starts here...
+ @observable
+ public SelectedDocs: FieldId[] = []
public active: () => boolean = () => CollectionView.Active(this);
addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
@@ -40,11 +56,63 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; }
get subView(): any { return CollectionView.SubView(this); }
+ componentDidMount() {
+ this.updateTimecode();
+ }
+
+ get player(): HTMLVideoElement | undefined {
+ return this._mainCont.current ? this._mainCont.current.getElementsByTagName("video")[0] : undefined;
+ }
+
+ @action
+ updateTimecode = () => {
+ if (this.player) {
+ this.ctime = this.player.currentTime;
+ this.props.Document.SetNumber(KeyStore.CurPage, Math.round(this.ctime));
+ }
+ setTimeout(() => this.updateTimecode(), 100)
+ }
+
+
+ @observable
+ ctime: number = 0
+ @observable
+ playing: boolean = false;
+
+ @action
+ onPlayDown = () => {
+ if (this.player) {
+ if (this.player.paused) {
+ this.player.play();
+ this.playing = true;
+ } else {
+ this.player.pause();
+ this.playing = false;
+ }
+ }
+ }
+ @action
+ onFullDown = (e: React.PointerEvent) => {
+ if (this.player) {
+ this.player.requestFullscreen();
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+
+ @action
+ onResetDown = () => {
+ if (this.player) {
+ this.player.pause();
+ this.player.currentTime = 0;
+ }
+
+ }
+
render() {
- return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
- {/* <video controls className="videobox-cont"> */}
+ return (<div className="collectionVideoView-cont" ref={this._mainCont} onContextMenu={this.specificContextMenu}>
{this.subView}
- {/* </video> */}
+ {this.uIButtons}
</div>)
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 17a0fbd23..d9b2722a6 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -22,20 +22,19 @@ export enum CollectionViewType {
Tree
}
-export const COLLECTION_BORDER_WIDTH = 2;
+export const COLLECTION_BORDER_WIDTH = 1;
@observer
export class CollectionView extends React.Component<CollectionViewProps> {
- @observable
- public SelectedDocs: FieldId[] = [];
-
public static LayoutString(fieldKey: string = "DataKey") {
return `<${CollectionView.name} Document={Document}
ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings}
isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`;
}
+ @observable
+ public SelectedDocs: FieldId[] = [];
public active: () => boolean = () => CollectionView.Active(this);
addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
@@ -50,7 +49,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
@action
public static AddDocument(props: CollectionViewProps, doc: Document) {
- doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, 0));
+ doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, -1));
if (props.Document.Get(props.fieldKey) instanceof Field) {
//TODO This won't create the field if it doesn't already exist
const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx
index d9e4df1e9..65aaa837f 100644
--- a/src/client/views/collections/MarqueeView.tsx
+++ b/src/client/views/collections/MarqueeView.tsx
@@ -3,21 +3,22 @@ import { observer } from "mobx-react";
import { Document } from "../../../fields/Document";
import { FieldWaiting, Opt } from "../../../fields/Field";
import { KeyStore } from "../../../fields/KeyStore";
-import { ListField } from "../../../fields/ListField";
import { Documents } from "../../documents/Documents";
import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { CollectionFreeFormView } from "./CollectionFreeFormView";
import "./MarqueeView.scss";
import React = require("react");
-
+import { InkField, StrokeData } from "../../../fields/InkField";
+import { Utils } from "../../../Utils";
+import { InkingCanvas } from "../InkingCanvas";
interface MarqueeViewProps {
getMarqueeTransform: () => Transform;
getTransform: () => Transform;
container: CollectionFreeFormView;
addDocument: (doc: Document) => void;
- activeDocuemnts: () => Document[];
+ activeDocuments: () => Document[];
selectDocuments: (docs: Document[]) => void;
removeDocument: (doc: Document) => boolean;
}
@@ -92,31 +93,59 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@action
marqueeCommand = (e: KeyboardEvent) => {
- if (e.key == "Backspace") {
+ if (e.key == "Backspace" || e.key == "Delete") {
this.marqueeSelect().map(d => this.props.removeDocument(d));
+ this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
this.cleanupInteractions();
}
if (e.key == "c") {
let bounds = this.Bounds;
- let selected = this.marqueeSelect().map(m => m);
- this.marqueeSelect().map(d => this.props.removeDocument(d));
- //setTimeout(() => {
- this.props.addDocument(Documents.FreeformDocument(selected.map(d => {
+ let selected = this.marqueeSelect().map(d => {
+ this.props.removeDocument(d);
d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2);
d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2);
d.SetNumber(KeyStore.Page, 0);
d.SetText(KeyStore.Title, "" + d.GetNumber(KeyStore.Width, 0) + " " + d.GetNumber(KeyStore.Height, 0));
return d;
- }), { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, height: bounds.height, title: "a nested collection" }));
+ });
+ let liftedInk = this.marqueeInkSelect(true);
+ this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
+ //setTimeout(() => {
+ this.props.addDocument(Documents.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, backgroundColor: "Transparent", height: bounds.height, ink: liftedInk, title: "a nested collection" }));
// }, 100);
this.cleanupInteractions();
}
}
+ marqueeInkSelect(select: boolean) {
+ let selRect = this.Bounds;
+ let centerShiftX = 0 - (selRect.left + selRect.width / 2); // moves each point by the offset that shifts the selection's center to the origin.
+ let centerShiftY = 0 - (selRect.top + selRect.height / 2);
+ let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
+ if (ink && ink != FieldWaiting) {
+ let idata = new Map();
+ ink.Data.forEach((value: StrokeData, key: string, map: any) => {
+ let inside = InkingCanvas.IntersectStrokeRect(value, selRect);
+ if (inside && select) {
+ idata.set(key,
+ {
+ pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }),
+ color: value.color,
+ width: value.width,
+ tool: value.tool,
+ page: -1
+ });
+ } else if (!inside && !select) {
+ idata.set(key, value);
+ }
+ })
+ return idata;
+ }
+ }
marqueeSelect() {
let selRect = this.Bounds;
let selection: Document[] = [];
- this.props.activeDocuemnts().map(doc => {
+ this.props.activeDocuments().map(doc => {
var x = doc.GetNumber(KeyStore.X, 0);
var y = doc.GetNumber(KeyStore.Y, 0);
var w = doc.GetNumber(KeyStore.Width, 0);
diff --git a/src/client/views/collections/PreviewCursor.tsx b/src/client/views/collections/PreviewCursor.tsx
index ab68fbc46..a1411250a 100644
--- a/src/client/views/collections/PreviewCursor.tsx
+++ b/src/client/views/collections/PreviewCursor.tsx
@@ -16,7 +16,7 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
export interface PreviewCursorProps {
getTransform: () => Transform;
container: CollectionFreeFormView;
- addLiveTextDocuemnt: (doc: Document) => void;
+ addLiveTextDocument: (doc: Document) => void;
}
@observer
@@ -57,11 +57,13 @@ export class PreviewCursor extends React.Component<PreviewCursorProps> {
@action
onKeyPress = (e: KeyboardEvent) => {
//if not these keys, make a textbox if preview cursor is active!
- if (!e.ctrlKey && !e.altKey) {
+ if (!e.ctrlKey && !e.altKey && !e.defaultPrevented) {
//make textbox and add it to this collection
let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY);
let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "new" });
- this.props.addLiveTextDocuemnt(newBox);
+ this.props.addLiveTextDocument(newBox);
+ e.stopPropagation();
+ e.preventDefault();
}
}