aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-08-20 20:03:08 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-08-20 20:03:08 -0400
commitdc587b0fb493d869e6cd38fa94b81105da4fbaab (patch)
tree563f23d9e404678cf93f1574fb923f1d37b49b8b /src
parentaa0e6f5ffc30fdffc3be13a1948981b754544a01 (diff)
finished UI
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DocumentDecorations.scss6
-rw-r--r--src/client/views/DocumentDecorations.tsx92
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx3
-rw-r--r--src/new_fields/RichTextField.ts7
4 files changed, 67 insertions, 41 deletions
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 0b7411fca..ef7159370 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -255,4 +255,8 @@ $linkGap : 3px;
input {
margin-right: 10px;
}
-} \ No newline at end of file
+}
+
+@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
+@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
+@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } \ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 05239073b..7645af054 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,5 +1,5 @@
import { library, IconProp } from '@fortawesome/fontawesome-svg-core';
-import { faLink, faTag, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faStopCircle, faCloudUploadAlt } from '@fortawesome/free-solid-svg-icons';
+import { faLink, faTag, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faStopCircle, faCloudUploadAlt, faSyncAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
@@ -41,8 +41,10 @@ library.add(faArrowAltCircleUp);
library.add(faStopCircle);
library.add(faCheckCircle);
library.add(faCloudUploadAlt);
+library.add(faSyncAlt);
const cloud: IconProp = "cloud-upload-alt";
+const fetch: IconProp = "sync-alt";
@observer
export class DocumentDecorations extends React.Component<{}, { value: string }> {
@@ -76,48 +78,47 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@observable public pushIcon: IconProp = "arrow-alt-circle-up";
@observable public pullIcon: IconProp = "arrow-alt-circle-down";
@observable public pullColor: string = "white";
+ @observable public isAnimatingFetch = false;
public pullColorAnimating = false;
private pullAnimating = false;
private pushAnimating = false;
public startPullOutcome = action((success: boolean) => {
- if (this.pullAnimating) {
- return;
+ if (!this.pullAnimating) {
+ this.pullAnimating = true;
+ this.pullIcon = success ? "check-circle" : "stop-circle";
+ setTimeout(() => runInAction(() => {
+ this.pullIcon = "arrow-alt-circle-down";
+ this.pullAnimating = false;
+ }), 1000);
}
- this.pullAnimating = true;
- this.pullIcon = success ? "check-circle" : "stop-circle";
- setTimeout(() => runInAction(() => {
- this.pullIcon = "arrow-alt-circle-down";
- this.pullAnimating = false;
- }), 1000);
});
public startPushOutcome = action((success: boolean) => {
- if (this.pushAnimating) {
- return;
+ if (!this.pushAnimating) {
+ this.pushAnimating = true;
+ this.pushIcon = success ? "check-circle" : "stop-circle";
+ setTimeout(() => runInAction(() => {
+ this.pushIcon = "arrow-alt-circle-up";
+ this.pushAnimating = false;
+ }), 1000);
}
- this.pushAnimating = true;
- this.pushIcon = success ? "check-circle" : "stop-circle";
- setTimeout(() => runInAction(() => {
- this.pushIcon = "arrow-alt-circle-up";
- this.pushAnimating = false;
- }), 1000);
});
- public setPullState = (unchanged: boolean) => {
- if (this.pullColorAnimating) {
- return;
+ public setPullState = action((unchanged: boolean) => {
+ this.isAnimatingFetch = false;
+ if (!this.pullColorAnimating) {
+ this.pullColorAnimating = true;
+ this.pullColor = unchanged ? "lawngreen" : "red";
+ setTimeout(this.clearPullColor, 1000);
}
- this.pullColorAnimating = true;
- this.pullColor = unchanged ? "lawngreen" : "red";
- setTimeout(() => {
- runInAction(() => {
- this.pullColor = "white";
- this.pullColorAnimating = false;
- });
- }, 2000);
- }
+ });
+
+ private clearPullColor = action(() => {
+ this.pullColor = "white";
+ this.pullColorAnimating = false;
+ });
constructor(props: Readonly<{}>) {
super(props);
@@ -679,7 +680,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let canPush = this.targetDoc.data && this.targetDoc.data instanceof RichTextField;
if (!canPush) return (null);
let published = Doc.GetProto(this.targetDoc)[GoogleRef] !== undefined;
- let icon: IconProp = published ? (this.pushIcon as any) : (cloud as any);
+ let icon: IconProp = published ? (this.pushIcon as any) : cloud;
return (
<div className={"linkButtonWrapper"}>
<div title={`${published ? "Push" : "Publish"} to Google Docs`} className="linkButton-linker" onClick={() => {
@@ -695,14 +696,33 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
considerGoogleDocsPull = () => {
let canPull = this.targetDoc.data && this.targetDoc.data instanceof RichTextField;
let dataDoc = Doc.GetProto(this.targetDoc);
- if (!canPull || !dataDoc[GoogleRef] || dataDoc.unchanged) return (null);
+ if (!canPull || !dataDoc[GoogleRef]) return (null);
+ let icon = !dataDoc.unchanged ? (this.pullIcon as any) : fetch;
+ let animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
return (
<div className={"linkButtonWrapper"}>
- <div style={{ backgroundColor: this.pullColor, transition: "1s ease all" }} title="Pull From Google Docs" className="linkButton-linker" onClick={() => {
- DocumentDecorations.hasPulledHack = false;
- this.targetDoc[Pulls] = NumCast(this.targetDoc[Pulls]) + 1;
- }}>
- <FontAwesomeIcon className="documentdecorations-icon" icon={this.pullIcon} size="sm" />
+ <div
+ title="Pull From Google Docs"
+ className="linkButton-linker"
+ style={{
+ backgroundColor: this.pullColor,
+ transition: "0.2s ease all"
+ }}
+ onClick={() => {
+ this.clearPullColor();
+ DocumentDecorations.hasPulledHack = false;
+ this.targetDoc[Pulls] = NumCast(this.targetDoc[Pulls]) + 1;
+ dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
+ }}>
+ <FontAwesomeIcon
+ style={{
+ WebkitAnimation: animation,
+ MozAnimation: animation
+ }}
+ className="documentdecorations-icon"
+ icon={icon}
+ size="sm"
+ />
</div>
</div>
);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 8a355a425..e06be7079 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -354,7 +354,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
() => {
if (!DocumentDecorations.hasPulledHack) {
DocumentDecorations.hasPulledHack = true;
- this.pullFromGoogleDoc(this.updateState);
+ let unchanged = this.dataDoc.unchanged;
+ this.pullFromGoogleDoc(unchanged ? this.checkState : this.updateState);
}
}
);
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index ab58329f9..cae5623e6 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -38,9 +38,10 @@ export class RichTextField extends ObjectField {
let blockText = (block: any) => block.text;
let concatenateParagraph = (p: any) => (p.content ? p.content.map(blockText).join(joiner) : "") + delimiter;
- // Concatentate paragraphs and string the result together. Trim the last newline, an artifact.
- let textParagraphs = paragraphs.map(concatenateParagraph);
- return textParagraphs.join(joiner).trimEnd(delimiter);
+ // Concatentate paragraphs and string the result together
+ let textParagraphs: string[] = paragraphs.map(concatenateParagraph);
+ let plainText = textParagraphs.join(joiner);
+ return plainText.substring(0, plainText.length - 1);
}
[FromPlainText](plainText: string) {