diff options
Diffstat (limited to 'src/client/views/PropertiesView.tsx')
-rw-r--r-- | src/client/views/PropertiesView.tsx | 114 |
1 files changed, 113 insertions, 1 deletions
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e4e7bec32..c3fdee001 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -2,7 +2,7 @@ import { IconLookup } from '@fortawesome/fontawesome-svg-core'; import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox, Tooltip } from '@mui/material'; -import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; +import { Button, ColorPicker, Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components'; import { concat } from 'lodash'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; @@ -41,6 +41,11 @@ import { DocumentView, OpenWhere } from './nodes/DocumentView'; import { StyleProviderFuncType } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; +import { ExtractColors } from './ExtractColors'; +import TextareaAutosize from 'react-textarea-autosize'; +import { GeneratedResponse, StyleInput, generatePalette } from '../apis/gpt/customization'; +import { FaFillDrip } from 'react-icons/fa'; + import { LinkBox } from './nodes/LinkBox'; const _global = (window /* browser */ || global) /* node */ as any; @@ -101,6 +106,58 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps @observable openAppearance: boolean = true; @observable openTransform: boolean = true; @observable openFilters: boolean = false; + @observable openStyling: boolean = true; + + // GPT styling + public styleInput: StyleInput | undefined; + @observable loadingStyles: boolean = false; + @observable generatedStyles: GeneratedResponse[] = []; + @observable inputDocs: Doc[] = []; + @observable selectedStyle: number = -1; + @observable useImageData = false; + + @observable chatInput: string = ''; + + @action + setChatInput = (input: string) => { + this.chatInput = input; + }; + + @action + setLoading = (loading: boolean) => { + this.loadingStyles = loading; + }; + + @action + gptStyling = async () => { + // this.generatedStyles = []; + this.selectedStyle = -1; + this.setLoading(true); + console.log('Style input: ', this.styleInput); + + if (!this.styleInput) return; + + try { + let res: any; + if (this.generatedStyles.length === 0) { + res = await generatePalette(this.styleInput, this.useImageData, this.chatInput); + } else { + res = await generatePalette(this.styleInput, this.useImageData, this.chatInput, this.generatedStyles); + } + if (typeof res === 'string') { + console.log('Generated palettes: ', res); + const resObj = JSON.parse(res) as GeneratedResponse[]; + this.setGeneratedStyles(resObj); + } + } catch (err) { + console.error(err); + } + this.setLoading(false); + }; + + @action + setGeneratedStyles = (responses: GeneratedResponse[]) => (this.generatedStyles = responses); + setInputDocs = (docs: Doc[]) => (this.inputDocs = docs); //Pres Trails booleans: @observable openPresTransitions: boolean = true; @@ -1139,6 +1196,60 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps } }; + @action + styleCollection = (i: number) => { + this.selectedStyle = i; + const resObj = this.generatedStyles[i]; + if (this.selectedDoc && this.selectedDoc.type === 'collection') { + this.selectedDoc.backgroundColor = resObj.collectionBackgroundColor; + resObj.documentsWithColors.forEach((elem, i) => (this.inputDocs[i].backgroundColor = elem.color)); + } + }; + + // GPT styling + @computed get stylingSubMenu() { + return ( + <PropertiesSection title="Styling" isOpen={this.openStyling} setIsOpen={bool => (this.openStyling = bool)} onDoubleClick={() => this.CloseAll()}> + <div className="propertiesView-content" style={{ position: 'relative', height: 'auto', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' }}> + {this.generatedStyles.length > 0 && + this.generatedStyles.map((style, i) => ( + <div + key={i} + className="propertiesView-palette" + style={{ display: 'flex', gap: '4px', backgroundColor: this.selectedStyle === i ? StrCast(Doc.UserDoc().userVariantColor) : '#00000000' }} + onClick={() => this.styleCollection(i)}> + <div style={{ width: '24px', height: '24px', backgroundColor: style.collectionBackgroundColor, borderRadius: '2px' }}></div> + {ExtractColors.sortColors(style.documentsWithColors.map(doc => ExtractColors.hexToFinalColor(doc.color))).map((c, i) => ( + <div key={i} style={{ width: '24px', height: '24px', backgroundColor: c.hex, borderRadius: '2px' }}></div> + ))} + </div> + ))} + {this.loadingStyles && 'Generating styles...'} + <TextareaAutosize + minRows={3} + placeholder="Customize..." + className="styling-chatbox" + autoFocus={true} + value={this.chatInput} + onChange={e => { + this.setChatInput(e.target.value); + }} + onKeyDown={e => { + e.stopPropagation(); + }} + /> + <div style={{ display: 'flex', justifyContent: 'flex-end', gap: '16px' }}> + <div style={{ display: 'flex', gap: '4px', alignItems: 'center' }}> + <label style={{ margin: '0px' }}>Use Images </label> + <input style={{ margin: '0px' }} type="checkbox" checked={this.useImageData} onChange={action(e => (this.useImageData = e.target.checked))} /> + </div> + <Button text={'Regenerate'} type={Type.TERT} color={StrCast(Doc.UserDoc().userVariantColor)} onClick={this.gptStyling} /> + </div> + </div> + </PropertiesSection> + ); + } + @computed get filtersSubMenu() { return ( <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => (this.openFilters = bool)} onDoubleClick={() => this.CloseAll()}> @@ -1645,6 +1756,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps <div className="propertiesView-name">{this.editableTitle}</div> <div className="propertiesView-type"> {this.currentType} </div> + {this.stylingSubMenu} {this.fieldsSubMenu} {this.optionsSubMenu} {this.linksSubMenu} |