aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/RTFMarkup.tsx12
-rw-r--r--src/client/views/ContextMenuItem.tsx25
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx4
-rw-r--r--src/client/views/nodes/FontIconBox/TrailsIcon.tsx6
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx4
-rw-r--r--src/client/views/nodes/generativeFill/GenerativeFill.tsx31
-rw-r--r--src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx4
-rw-r--r--src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts28
11 files changed, 92 insertions, 39 deletions
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index a0fc617ab..78069d323 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -3,6 +3,8 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { MainViewModal } from '../views/MainViewModal';
import { SettingsManager } from './SettingsManager';
+import { Doc } from '../../fields/Doc';
+import { StrCast } from '../../fields/Types';
@observer
export class RTFMarkup extends React.Component<{}> {
@@ -133,6 +135,14 @@ export class RTFMarkup extends React.Component<{}> {
}
render() {
- return <MainViewModal contents={this.cheatSheet} isDisplayed={this.isOpen} interactive={true} closeOnExternalClick={this.close} />;
+ return (
+ <MainViewModal
+ dialogueBoxStyle={{ backgroundColor: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor), padding: '16px' }}
+ contents={this.cheatSheet}
+ isDisplayed={this.isOpen}
+ interactive={true}
+ closeOnExternalClick={this.close}
+ />
+ );
}
}
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index daa2c152a..b53379435 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -6,12 +6,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { UndoManager } from '../util/UndoManager';
import { Doc } from '../../fields/Doc';
import { StrCast } from '../../fields/Types';
+import { SettingsManager } from '../util/SettingsManager';
export interface OriginalMenuProps {
description: string;
event: (stuff?: any) => void;
undoable?: boolean;
- icon: IconProp; //maybe should be optional (icon?)
+ icon: IconProp | JSX.Element; //maybe should be optional (icon?)
closeMenu?: () => void;
}
@@ -82,19 +83,20 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
);
};
+ isJSXElement(val: any): val is JSX.Element {
+ return React.isValidElement(val);
+ }
+
render() {
if ('event' in this.props) {
return (
<div className={'contextMenu-item' + (this.props.selected ? ' contextMenu-itemSelected' : '')} onPointerDown={this.handleEvent}>
- {this.props.icon ? (
- <span className="contextMenu-item-icon-background">
- <FontAwesomeIcon icon={this.props.icon} size="sm" />
- </span>
- ) : null}
+ {this.props.icon ? <span className="contextMenu-item-icon-background">{this.isJSXElement(this.props.icon) ? this.props.icon : <FontAwesomeIcon icon={this.props.icon} size="sm" />}</span> : null}
<div className="contextMenu-description">{this.props.description.replace(':', '')}</div>
- <div className={`contextMenu-item-background`}
+ <div
+ className={`contextMenu-item-background`}
style={{
- background: StrCast(Doc.UserDoc().userColor)
+ background: SettingsManager.Instance.userColor,
}}
/>
</div>
@@ -110,7 +112,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
style={{
marginLeft: window.innerHeight - this._overPosX - 50 > 0 ? '90%' : '20%',
marginTop,
- background: StrCast(Doc.UserDoc().userBackgroundColor)
+ background: SettingsManager.Instance.userBackgroundColor,
}}>
{this._items.map(prop => (
<ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />
@@ -141,9 +143,10 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
{this.props.description}
<FontAwesomeIcon icon={'angle-right'} size="lg" style={{ position: 'absolute', right: '10px' }} />
</div>
- <div className={`contextMenu-item-background`}
+ <div
+ className={`contextMenu-item-background`}
style={{
- background: StrCast(Doc.UserDoc().userColor)
+ background: SettingsManager.Instance.userColor,
}}
/>
{submenu}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index a785ffd42..8565941fd 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -447,6 +447,7 @@ export class MainView extends React.Component {
fa.faSortUp,
fa.faSortDown,
fa.faTable,
+ fa.faTableColumns,
fa.faTh,
fa.faThList,
fa.faProjectDiagram,
@@ -1019,7 +1020,7 @@ export class MainView extends React.Component {
<OverlayView />
<GPTPopup key="gptpopup" />
<GenerativeFill imageEditorOpen={ImageBox.imageEditorOpen} imageEditorSource={ImageBox.imageEditorSource} imageRootDoc={ImageBox.imageRootDoc} addDoc={ImageBox.addDoc} />
- {/* <NewLightboxView key="newLightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} /> */}
+ {/* <NewLightboxView key="newLightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} /> */}
</div>
);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 533a047b1..b72864567 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -748,7 +748,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
event: undoBatch(action(() => (this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined))),
icon: 'hand-point-up',
});
- !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'compass' });
+ !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' });
}
onClicks.push({ description: 'Enter Portal', event: this.makeIntoPortal, icon: 'window-restore' });
@@ -806,7 +806,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' });
}
}
- constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
+ constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'table-columns' });
cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' });
const help = cm.findByDescription('Help...');
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 225df555b..d132707fa 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -7,6 +7,7 @@ import * as React from 'react';
import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { colorMapping } from '../../../../server/DashSession/Session/utilities/session_config';
import { Utils } from '../../../../Utils';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { SelectionManager } from '../../../util/SelectionManager';
@@ -14,7 +15,6 @@ import { undoable, UndoManager } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { DocComponent } from '../../DocComponent';
import { EditableView } from '../../EditableView';
-import { Colors } from '../../global/globalEnums';
import { SelectedDocView } from '../../selectedDoc';
import { StyleProp } from '../../StyleProvider';
import { OpenWhere } from '../DocumentView';
@@ -93,7 +93,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
else return null;
}
icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
- return !icon ? null : icon === 'pres-trail' ? <TrailsIcon /> : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
+ return !icon ? null : icon === 'pres-trail' ? TrailsIcon(color) : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
};
@computed get dropdown() {
return BoolCast(this.rootDoc.dropDownOpen);
diff --git a/src/client/views/nodes/FontIconBox/TrailsIcon.tsx b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
index 99063b4a0..09fd6e3ae 100644
--- a/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
+++ b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
@@ -1,10 +1,8 @@
import * as React from 'react';
-import { StrCast } from '../../../../fields/Types';
-import { Doc } from '../../../../fields/Doc';
-const TrailsIcon = () => (
+const TrailsIcon = (fill: string) => (
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 1080.000000 1080.000000" preserveAspectRatio="xMidYMid meet">
- <g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)" fill={StrCast(Doc.UserDoc().userColor)} stroke="none">
+ <g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)" fill={fill} stroke="none">
<path
d="M665 9253 c-74 -10 -157 -38 -240 -81 -74 -37 -107 -63 -186 -141
-104 -104 -156 -191 -201 -334 l-23 -72 0 -3215 c0 -3072 1 -3218 18 -3280 10
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 2c8e97512..f5c6a9273 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -59,8 +59,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@observable public static imageEditorOpen: boolean = false;
@observable public static imageEditorSource: string = '';
@observable public static addDoc: ((doc: Doc | Doc[], annotationKey?: string) => boolean) | undefined;
- @action public static setImageEditorOpen(open: boolean) {ImageBox.imageEditorOpen = open;}
- @action public static setImageEditorSource(source: string) {ImageBox.imageEditorSource = source;}
+ @action public static setImageEditorOpen(open: boolean) {
+ ImageBox.imageEditorOpen = open;
+ }
+ @action public static setImageEditorSource(source: string) {
+ ImageBox.imageEditorSource = source;
+ }
private _ignoreScroll = false;
private _forcedScroll = false;
private _dropDisposer?: DragManager.DragDropDisposer;
@@ -307,7 +311,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
choosePath(url: URL) {
- if (!url?.href) return "";
+ if (!url?.href) return '';
const lower = url.href.toLowerCase();
if (url.protocol === 'data') return url.href;
if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index da277826a..200d06a0b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -71,6 +71,7 @@ import { SummaryView } from './SummaryView';
import applyDevTools = require('prosemirror-dev-tools');
import React = require('react');
import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup';
+import { BsMarkdownFill } from 'react-icons/bs';
const translateGoogleApi = require('translate-google-api');
export const GoogleRef = 'googleDocId';
type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void;
@@ -899,7 +900,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight),
icon: this.Document._layout_autoHeight ? 'lock' : 'unlock',
});
- optionItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: 'text' });
+ optionItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: <BsMarkdownFill /> });
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
this._downX = this._downY = Number.NaN;
};
@@ -930,7 +931,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
});
generateImage = async () => {
- console.log('Generate image from text: ', (this.dataDoc.text as RichTextField)?.Text);
GPTPopup.Instance?.setTextAnchor(this.getAnchor(false));
GPTPopup.Instance?.setImgTargetDoc(this.rootDoc);
GPTPopup.Instance.addToCollection = this.props.addDocument;
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index 9c03600cf..1400d0f6d 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -166,20 +166,27 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
// first load
useEffect(() => {
- if (!imageEditorSource || imageEditorSource === '') return;
- const img = new Image();
- img.src = imageEditorSource;
- currImg.current = img;
- originalImg.current = img;
- img.onload = () => {
- const imgWidth = img.naturalWidth;
- const imgHeight = img.naturalHeight;
- const scale = Math.min(canvasSize / imgWidth, canvasSize / imgHeight);
- const width = imgWidth * scale;
- const height = imgHeight * scale;
- setCanvasDims({ width, height });
+ const loadInitial = async () => {
+ if (!imageEditorSource || imageEditorSource === '') return;
+ const img = new Image();
+ const res = await ImageUtility.urlToBase64(imageEditorSource);
+ if (!res) return;
+ img.src = `data:image/png;base64,${res}`;
+
+ img.onload = () => {
+ currImg.current = img;
+ originalImg.current = img;
+ const imgWidth = img.naturalWidth;
+ const imgHeight = img.naturalHeight;
+ const scale = Math.min(canvasSize / imgWidth, canvasSize / imgHeight);
+ const width = imgWidth * scale;
+ const height = imgHeight * scale;
+ setCanvasDims({ width, height });
+ };
};
+ loadInitial();
+
// cleanup
return () => {
setInput('');
diff --git a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
index 0dfcebea3..10eca358e 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
@@ -2,7 +2,8 @@ import './GenerativeFillButtons.scss';
import React = require('react');
import ReactLoading from 'react-loading';
import { activeColor } from './generativeFillUtils/generativeFillConstants';
-import { Button, Type } from 'browndash-components';
+import { Button, IconButton, Type } from 'browndash-components';
+import { AiOutlineInfo } from 'react-icons/ai';
interface ButtonContainerProps {
getEdit: () => Promise<void>;
@@ -35,6 +36,7 @@ const Buttons = ({ loading, getEdit, onReset }: ButtonContainerProps) => {
}}
/>
)}
+ <IconButton type={Type.SEC} color={activeColor} tooltip="Open Documentation" icon={<AiOutlineInfo size={'16px'} />} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/generativeai/#editing', '_blank')} />
</div>
);
};
diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts
index 2ede625f6..47a14135f 100644
--- a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts
+++ b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts
@@ -283,4 +283,32 @@ export class ImageUtility {
}
return canvas;
};
+
+ /**
+ * Converts a url to base64 (tainted canvas workaround)
+ */
+ static urlToBase64 = async (imageUrl: string): Promise<string | undefined> => {
+ try {
+ const res = await fetch(imageUrl);
+ const blob = await res.blob();
+
+ return new Promise<string>((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = () => {
+ const base64Data = reader.result?.toString().split(',')[1];
+ if (base64Data) {
+ resolve(base64Data);
+ } else {
+ reject(new Error('Failed to convert.'));
+ }
+ };
+ reader.onerror = () => {
+ reject(new Error('Error reading image data'));
+ };
+ reader.readAsDataURL(blob);
+ });
+ } catch (err) {
+ console.error(err);
+ }
+ };
}