From cf791104c0b1608e37c3cf2d25dac7f6f58a1b66 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 18 Feb 2025 09:01:44 -0500 Subject: css fixes for gptPopup + close button --- src/client/util/SnappingManager.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/client/util') diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 2a150dc5a..9d8a41844 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -32,6 +32,7 @@ export class SnappingManager { @observable _hideDecorations: boolean = false; @observable _keepGestureMode: boolean = false; // for whether primitive selection enters a one-shot or persistent mode @observable _inkShape: Gestures | undefined = undefined; + @observable _chatVisible: boolean = false; private constructor() { SnappingManager._manager = this; @@ -66,6 +67,7 @@ export class SnappingManager { public static get HideDecorations(){ return this.Instance._hideDecorations; } // prettier-ignore public static get KeepGestureMode(){ return this.Instance._keepGestureMode; } // prettier-ignore public static get InkShape() { return this.Instance._inkShape; } // prettier-ignore + public static get ChatVisible() { return this.Instance._chatVisible; } // prettier-ignore public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore @@ -85,6 +87,7 @@ export class SnappingManager { public static SetHideDecorations= (state:boolean) =>runInAction(() => {this.Instance._hideDecorations = state}); // prettier-ignore public static SetKeepGestureMode= (state:boolean) =>runInAction(() => {this.Instance._keepGestureMode = state}); // prettier-ignore public static SetInkShape = (shape?:Gestures)=>runInAction(() => {this.Instance._inkShape = shape}); // prettier-ignore + public static SetChatVisible = (vis:boolean) =>runInAction(() => {this.Instance._chatVisible = vis}); // prettier-ignore public static userColor: string | undefined; public static userVariantColor: string | undefined; -- cgit v1.2.3-70-g09d2 From f6581aebd603dcdd84e033acffe46352ce5a4485 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 19 Feb 2025 15:05:47 -0500 Subject: more gptpopup cleanup. --- src/client/apis/gpt/GPT.ts | 59 +++++++------- src/client/util/CurrentUserUtils.ts | 6 +- src/client/util/Import & Export/ImageUtils.ts | 12 +-- src/client/views/StyleProviderQuiz.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 33 ++++---- src/client/views/global/globalScripts.ts | 14 ++-- src/client/views/nodes/ComparisonBox.tsx | 6 +- .../views/nodes/chatbot/agentsystem/Agent.ts | 3 +- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 3 +- .../views/nodes/chatbot/tools/ImageCreationTool.ts | 36 ++++---- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 95 ++++++++++------------ src/fields/Doc.ts | 2 +- 12 files changed, 126 insertions(+), 145 deletions(-) (limited to 'src/client/util') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index e1ae99d97..6d9bc1d06 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -1,12 +1,11 @@ import { ChatCompletionMessageParam, Image } from 'openai/resources'; import { openai } from './setup'; -export enum GPTTypeStyle { +export enum GPTDocCommand { AssignTags = 1, Filter = 2, - DocInfo = 3, - GeneralInfo = 4, - SortDocs = 5, + GetInfo = 3, + Sort = 4, } export const DescriptionSeperator = '======'; @@ -18,8 +17,6 @@ enum GPTCallType { EDIT = 'edit', CHATCARD = 'chatcard', // a single flashcard style response to a question FLASHCARD = 'flashcard', // a set of flashcard qustion/answer responses to a topic - QUIZ = 'quiz', - SORT = 'sort', DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', @@ -27,15 +24,17 @@ enum GPTCallType { PRONUNCIATION = 'pronunciation', DRAW = 'draw', COLOR = 'color', - RUBRIC = 'rubric', // needs to be filled in below - TYPE = 'type', // needs to be filled in below - SUBSET = 'subset', // needs to be filled in below - INFO = 'info', // needs to be filled in below TEMPLATE = 'template', VIZSUM = 'vizsum', VIZSUM2 = 'vizsum2', FILL = 'fill', COMPLETEPROMPT = 'completeprompt', + QUIZDOC = 'quiz_doc', + MAKERUBRIC = 'make_rubric', // create a definition rubric for a document to be used when quizzing the user + COMMANDTYPE = 'command_type', // Determine the type of command being made (GPTQueryType - eg., AssignTags, Sort, Filter, DocInfo, GenInfo) and possibly some parameters (eg, Tag type for Tags) + SUBSETDOCS = 'subset_docs', // select a subset of documents based on their descriptions + DOCINFO = 'doc_info', // provide information about a document + SORTDOCS = 'sort_docs', } type GPTCallOpts = { @@ -69,7 +68,7 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = { temp: 0.5, prompt: "You are a helpful resarch assistant. Analyze the user's data to find meaningful patterns and/or correlation. Please only return a JSON with a correlation column 1 propert, a correlation column 2 property, and an analysis property. ", }, - sort: { + sort_docs: { model: 'gpt-4o', maxTokens: 2048, temp: 0.25, @@ -89,7 +88,7 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = { prompt: 'Make flashcards out of this text with each question and answer labeled as question and answer. Create a title for each question and asnwer that is labeled as "title". Do not label each flashcard and do not include asterisks: ', }, chatcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Answer the following question as a short flashcard response. Do not include a label.' }, - quiz: { + quiz_doc: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, @@ -138,20 +137,20 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = { temp: 0.5, prompt: 'You will be coloring drawings. You will be given what the drawing is, then a list of descriptions for parts of the drawing. Based on each description, respond with the stroke and fill color that it should be. Follow the rules: 1. Avoid using black for stroke color 2. Make the stroke color 1-3 shades darker than the fill color 3. Use the same colors when possible. Format as {#abcdef #abcdef}, making sure theres a color for each description, and do not include any additional text.', }, - type: { + command_type: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, prompt: `I'm going to provide you with a question. Based on the question, is the user asking you to - ${GPTTypeStyle.AssignTags}. Assigns docs with tags(like star / heart etc)/labels, - ${GPTTypeStyle.DocInfo}. Provide information about a specific doc - ${GPTTypeStyle.Filter}. Filter docs based on a question/information - ${GPTTypeStyle.GeneralInfo}. Provide general information - ${GPTTypeStyle.SortDocs}. Put cards in a specific order. - Answer with only the number for 2-5. For number one, provide the number (1) and the appropriate tag`, + ${GPTDocCommand.AssignTags}. Assigns docs with tags(like star / heart etc)/labels. + ${GPTDocCommand.GetInfo}. Provide information about a specific doc. + ${GPTDocCommand.Filter}. Filter docs based on a question/information. + ${GPTDocCommand.Sort}. Put docs in a specific order. + Answer with only the number for ${GPTDocCommand.GetInfo}-${GPTDocCommand.Sort}. + For number one, provide the number (${GPTDocCommand.AssignTags}) and the appropriate tag`, }, - subset: { + subset_docs: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, @@ -164,14 +163,14 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = { It is VERY important that you format it exactly as described, ensuring the proper number of '${DescriptionSeperator[0]}' and '${DocSeperator[0]}' (${DescriptionSeperator.length} of each) and NO commas`, }, - info: { + doc_info: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, prompt: `Answer the user's question with a short (<100 word) response. If a particular document is selected I will provide that information (which may help with your response)`, }, - rubric: { + make_rubric: { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, @@ -188,17 +187,15 @@ let lastResp = ''; * @returns AI Output */ const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: string, dontCache?: boolean) => { - const inputText = inputTextIn + ([GPTCallType.SUMMARY, GPTCallType.FLASHCARD, GPTCallType.QUIZ, GPTCallType.STACK].includes(callType) ? '.' : ''); + const inputText = inputTextIn + ([GPTCallType.SUMMARY, GPTCallType.FLASHCARD, GPTCallType.QUIZDOC, GPTCallType.STACK].includes(callType) ? '.' : ''); const opts = callTypeMap[callType]; if (!opts) { console.log('The query type:' + callType + ' requires a configuration.'); return 'Error connecting with API.'; } - if (lastCall === inputText && dontCache !== true) return lastResp; + if (lastCall === inputText && dontCache !== true && lastResp) return lastResp; try { - lastCall = inputText; - - const usePrompt = prompt ? prompt + opts.prompt : opts.prompt; + const usePrompt = prompt ? prompt + '.' + opts.prompt : opts.prompt; const messages: ChatCompletionMessageParam[] = [ { role: 'system', content: usePrompt }, { role: 'user', content: inputText }, @@ -210,8 +207,12 @@ const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: s temperature: opts.temp, max_tokens: opts.maxTokens, }); - lastResp = response.choices[0].message.content ?? ''; - return lastResp; + const result = response.choices[0].message.content ?? ''; + if (!dontCache) { + lastResp = result; + lastCall = inputText; + } + return result; } catch (err) { console.log(err); return 'Error connecting with API.'; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 6ca181d92..fb349abd9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -710,11 +710,7 @@ pie title Minerals in my tap water { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Sort", icon: "sort" , toolTip: "Manage sort order / lock status", btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, - subMenu: [ - { title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, - { title: "Descending",toolTip: "Sort the cards in descending order",btnType: ButtonType.ToggleButton, icon: "sort-down",toolType:"down",ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, - ]}, + { title: "Reverse", icon: "sort-up", toolTip: "Sort the cards in reverse order", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"reverse", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, ] } diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 8d4eefa7e..f73149fdc 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -4,22 +4,16 @@ import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; +import { Upload } from '../../../server/SharedMediaTypes'; import { Networking } from '../../Network'; export namespace ImageUtils { - export type imgInfo = { - contentSize: number; - nativeWidth: number; - nativeHeight: number; - source: string; - exifData: { error: string | undefined; data: string }; - }; - export const ExtractImgInfo = async (document: Doc): Promise => { + export const ExtractImgInfo = async (document: Doc): Promise => { const field = Cast(document.data, ImageField); return field ? Networking.PostToServer('/inspectImage', { source: field.url.href }) : undefined; }; - export const AssignImgInfo = (document: Doc, data?: imgInfo) => { + export const AssignImgInfo = (document: Doc, data?: Upload.InspectionResults) => { if (data) { data.nativeWidth && (document._height = (NumCast(document._width) * data.nativeHeight) / data.nativeWidth); const proto = document[DocData]; diff --git a/src/client/views/StyleProviderQuiz.tsx b/src/client/views/StyleProviderQuiz.tsx index b3fb8c930..d8eeb3490 100644 --- a/src/client/views/StyleProviderQuiz.tsx +++ b/src/client/views/StyleProviderQuiz.tsx @@ -265,7 +265,7 @@ export namespace styleProviderQuiz { '. ' + rubricText + '. One sentence and evaluate based on meaning, not wording. Provide a hex color at the beginning with a period after it on a scale of green (minor details missed) to red (big error) for how correct the answer is. Example: "#FFFFFF. Pasta is delicious."'; - const response = await gptAPICall(queryText, GPTCallType.QUIZ); + const response = await gptAPICall(queryText, GPTCallType.QUIZDOC); const hexSent = extractHexAndSentences(response); doc.quiz = hexSent.sentences?.replace(/UserAnswer/g, "user's answer").replace(/Rubric/g, 'rubric'); doc.backgroundColor = '#' + hexSent.hexNumber; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 954f9aa4c..b40cd2761 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -37,6 +37,9 @@ export enum docSortings { Tag = 'tag', None = '', } + +export const ChatSortField = 'chat_sortIndex'; + export interface CollectionViewProps extends React.PropsWithChildren { isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc) isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently) @@ -229,23 +232,21 @@ export function CollectionSubView() { childSortedDocs = (docsIn: Doc[], dragIndex: number) => { const sortType = StrCast(this.Document[this._props.fieldKey + '_sort']) as docSortings; - const isDesc = BoolCast(this.Document[this._props.fieldKey + '_sort_desc']); + const isDesc = BoolCast(this.Document[this._props.fieldKey + '_sort_reverse']); const docs = docsIn.slice(); - if (sortType) { - docs.sort((docA, docB) => { - const [typeA, typeB] = (() => { - switch (sortType) { - default: - case docSortings.Type: return [StrCast(docA.type), StrCast(docB.type)]; - case docSortings.Chat: return [NumCast(docA.chatIndex, 9999), NumCast(docB.chatIndex,9999)]; - case docSortings.Time: return [DateCast(docA.author_date)?.date ?? Date.now(), DateCast(docB.author_date)?.date ?? Date.now()]; - case docSortings.Color:return [DashColor(StrCast(docA.backgroundColor)).hsv().hue(), DashColor(StrCast(docB.backgroundColor)).hsv().hue()]; - case docSortings.Tag: return [StrListCast(docA.tags).join(""), StrListCast(docB.tags).join("")]; - } - })(); //prettier-ignore - return (typeA < typeB ? -1 : typeA > typeB ? 1 : 0) * (isDesc ? 1 : -1); - }); - } + sortType && docs.sort((docA, docB) => { + const [typeA, typeB] = (() => { + switch (sortType) { + default: + case docSortings.Type: return [StrCast(docA.type), StrCast(docB.type)]; + case docSortings.Chat: return [NumCast(docA[ChatSortField], 9999), NumCast(docB[ChatSortField], 9999)]; + case docSortings.Time: return [DateCast(docA.author_date)?.date ?? Date.now(), DateCast(docB.author_date)?.date ?? Date.now()]; + case docSortings.Color:return [DashColor(StrCast(docA.backgroundColor)).hsv().hue(), DashColor(StrCast(docB.backgroundColor)).hsv().hue()]; + case docSortings.Tag: return [StrListCast(docA.tags).join(""), StrListCast(docB.tags).join("")]; + } + })(); + return (typeA < typeB ? -1 : typeA > typeB ? 1 : 0) * (isDesc ? -1 : 1); + }); //prettier-ignore if (dragIndex !== -1) { const draggedDoc = DragManager.docsBeingDragged[0]; const originalIndex = docs.findIndex(doc => doc === draggedDoc); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 2bc0e3338..79873ed8f 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -152,7 +152,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function showFreeform( - attr: 'flashcards' | 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down' | 'toggle-chat' | 'toggle-tags' | 'tag', + attr: 'flashcards' | 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'reverse' | 'toggle-chat' | 'toggle-tags' | 'tag', checkResult?: boolean, persist?: boolean ) { @@ -163,7 +163,7 @@ ScriptingGlobals.add(function showFreeform( } // prettier-ignore - const map: Map<'flashcards' | 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down'| 'toggle-chat' | 'toggle-tags' | 'tag', + const map: Map<'flashcards' | 'hcenter' | 'vcenter' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'reverse'| 'toggle-chat' | 'toggle-tags' | 'tag', { waitForRender?: boolean; checkResult: (doc: Doc) => boolean; @@ -214,13 +214,9 @@ ScriptingGlobals.add(function showFreeform( checkResult: (doc: Doc) => StrCast(doc?.[Doc.LayoutFieldKey(doc)+"_sort"]) === "tag", setDoc: (doc: Doc, dv: DocumentView) => { doc[Doc.LayoutFieldKey(doc)+"_sort"] === "tag" ? doc[Doc.LayoutFieldKey(doc)+"_sort"] = '' : doc[Doc.LayoutFieldKey(doc)+"_sort"] = docSortings.Tag}, // prettier-ignore }], - ['up', { - checkResult: (doc: Doc) => BoolCast(!doc?.[Doc.LayoutFieldKey(doc)+"_sort_desc"]), - setDoc: (doc: Doc, dv: DocumentView) => { doc[Doc.LayoutFieldKey(doc)+"_sort_desc"] = undefined; }, - }], - ['down', { - checkResult: (doc: Doc) => BoolCast(doc?.[Doc.LayoutFieldKey(doc)+"_sort_desc"]), - setDoc: (doc: Doc, dv: DocumentView) => { doc[Doc.LayoutFieldKey(doc)+"_sort_desc"] = true; }, + ['reverse', { + checkResult: (doc: Doc) => BoolCast(doc?.[Doc.LayoutFieldKey(doc)+"_sort_reverse"]), + setDoc: (doc: Doc, dv: DocumentView) => { doc[Doc.LayoutFieldKey(doc)+"_sort_reverse"] = !doc[Doc.LayoutFieldKey(doc)+"_sort_reverse"]; }, }], ['toggle-chat', { checkResult: (doc: Doc) => SnappingManager.ChatVisible, diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index cb0831d3c..5315612e1 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -291,7 +291,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() this.askGPTPhonemes(this._inputValue); this._renderSide = this.backKey; this._outputValue = ''; - } else if (this._inputValue) this.askGPT(GPTCallType.QUIZ); + } else if (this._inputValue) this.askGPT(GPTCallType.QUIZDOC); }; onPointerMove = ({ movementX }: PointerEvent) => { @@ -511,7 +511,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() */ askGPT = async (callType: GPTCallType) => { const questionText = this.frontText; - const queryText = questionText + (callType == GPTCallType.QUIZ ? ' UserAnswer: ' + this._inputValue + '. ' + ' Rubric: ' + this.backText : ''); + const queryText = questionText + (callType == GPTCallType.QUIZDOC ? ' UserAnswer: ' + this._inputValue + '. ' + ' Rubric: ' + this.backText : ''); this.loading = true; const res = !this.frontText @@ -522,7 +522,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() case GPTCallType.CHATCARD: DocCast(this.dataDoc[this.backKey])[DocData].text = resp; break; - case GPTCallType.QUIZ: + case GPTCallType.QUIZDOC: this._renderSide = this.backKey; this._outputValue = resp.replace(/UserAnswer/g, "user's answer").replace(/Rubric/g, 'rubric'); break; diff --git a/src/client/views/nodes/chatbot/agentsystem/Agent.ts b/src/client/views/nodes/chatbot/agentsystem/Agent.ts index b2b0c9aea..2ed808622 100644 --- a/src/client/views/nodes/chatbot/agentsystem/Agent.ts +++ b/src/client/views/nodes/chatbot/agentsystem/Agent.ts @@ -22,6 +22,7 @@ import { ChatCompletionMessageParam } from 'openai/resources'; import { Doc } from '../../../../../fields/Doc'; import { parsedDoc } from '../chatboxcomponents/ChatBox'; import { WebsiteInfoScraperTool } from '../tools/WebsiteInfoScraperTool'; +import { Upload } from '../../../../../server/SharedMediaTypes'; //import { CreateTextDocTool } from '../tools/CreateTextDocumentTool'; dotenv.config(); @@ -61,7 +62,7 @@ export class Agent { history: () => string, csvData: () => { filename: string; id: string; text: string }[], addLinkedUrlDoc: (url: string, id: string) => void, - createImage: (result: any, options: DocumentOptions) => void, + createImage: (result: Upload.FileInformation & Upload.InspectionResults, options: DocumentOptions) => void, addLinkedDoc: (doc: parsedDoc) => Doc | undefined, // eslint-disable-next-line @typescript-eslint/no-unused-vars createCSVInDash: (url: string, title: string, id: string, data: string) => void diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx index 16da360fc..6e9307d37 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx @@ -42,6 +42,7 @@ import './ChatBox.scss'; import MessageComponentBox from './MessageComponent'; import { ProgressBar } from './ProgressBar'; import { OpenWhere } from '../../OpenWhere'; +import { Upload } from '../../../../../server/SharedMediaTypes'; dotenv.config(); @@ -412,7 +413,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent() { }); @action - createImageInDash = async (result: any, options: DocumentOptions) => { + createImageInDash = async (result: Upload.FileInformation & Upload.InspectionResults, options: DocumentOptions) => { const newImgSrc = result.accessPaths.agnostic.client.indexOf('dashblobstore') === -1 // ? ClientUtils.prepend(result.accessPaths.agnostic.client) diff --git a/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts b/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts index 177552c5c..dc6140871 100644 --- a/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts +++ b/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts @@ -1,10 +1,10 @@ -import { v4 as uuidv4 } from 'uuid'; import { RTFCast } from '../../../../../fields/Types'; import { DocumentOptions } from '../../../../documents/Documents'; import { Networking } from '../../../../Network'; import { ParametersType, ToolInfo } from '../types/tool_types'; import { Observation } from '../types/types'; import { BaseTool } from './BaseTool'; +import { Upload } from '../../../../../server/SharedMediaTypes'; const imageCreationToolParams = [ { @@ -25,8 +25,8 @@ const imageCreationToolInfo: ToolInfo = { }; export class ImageCreationTool extends BaseTool { - private _createImage: (result: any, options: DocumentOptions) => void; - constructor(createImage: (result: any, options: DocumentOptions) => void) { + private _createImage: (result: Upload.FileInformation & Upload.InspectionResults, options: DocumentOptions) => void; + constructor(createImage: (result: Upload.FileInformation & Upload.InspectionResults, options: DocumentOptions) => void) { super(imageCreationToolInfo); this._createImage = createImage; } @@ -42,23 +42,19 @@ export class ImageCreationTool extends BaseTool { }); console.log('Image generation result:', result); this._createImage(result, { text: RTFCast(image_prompt) }); - if (url) { - const id = uuidv4(); - - return [ - { - type: 'image_url', - image_url: { url }, - }, - ]; - } else { - return [ - { - type: 'text', - text: `An error occurred while generating image.`, - }, - ]; - } + return url + ? [ + { + type: 'image_url', + image_url: { url }, + }, + ] + : [ + { + type: 'text', + text: `An error occurred while generating image.`, + }, + ]; } catch (error) { console.log(error); return [ diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 72381cfad..cb3e9b2d7 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -10,7 +10,7 @@ import { ClientUtils } from '../../../../ClientUtils'; import { Doc } from '../../../../fields/Doc'; import { NumCast, StrCast } from '../../../../fields/Types'; import { Networking } from '../../../Network'; -import { DescriptionSeperator, DocSeperator, GPTCallType, GPTTypeStyle, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT'; +import { DescriptionSeperator, DocSeperator, GPTCallType, GPTDocCommand, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT'; import { DocUtils } from '../../../documents/DocUtils'; import { Docs } from '../../../documents/Documents'; import { SettingsManager } from '../../../util/SettingsManager'; @@ -18,7 +18,7 @@ import { SnappingManager } from '../../../util/SnappingManager'; import { undoable } from '../../../util/UndoManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { TagItem } from '../../TagsView'; -import { docSortings } from '../../collections/CollectionSubView'; +import { ChatSortField, docSortings } from '../../collections/CollectionSubView'; import { DocumentView } from '../../nodes/DocumentView'; import { AnchorMenu } from '../AnchorMenu'; import './GPTPopup.scss'; @@ -36,6 +36,7 @@ export enum GPTPopupMode { export class GPTPopup extends ObservableReactComponent { // eslint-disable-next-line no-use-before-define static Instance: GPTPopup; + static ChatTag = '#chat'; // tag used by GPT popup to filter docs private _messagesEndRef: React.RefObject; private _correlatedColumns: string[] = []; private _dataChatPrompt: string | undefined = undefined; @@ -77,10 +78,10 @@ export class GPTPopup extends ObservableReactComponent { if (hasChildDocs) { this._textToDocMap.clear(); this.setCollectionContext(selDoc.Document); - this.onGptResponse = (sortResult: string, questionType: GPTTypeStyle, tag?: string) => this.processGptResponse(selDoc, this._textToDocMap, sortResult, questionType, tag); + this.onGptResponse = (sortResult: string, questionType: GPTDocCommand, args?: string) => this.processGptResponse(selDoc, this._textToDocMap, sortResult, questionType, args); this.onQuizRandom = () => this.randomlyChooseDoc(selDoc.Document, hasChildDocs()); this._documentDescriptions = Promise.all(hasChildDocs().map(doc => - Doc.getDescription(doc).then(text => this._textToDocMap.set(text, doc) && `${DescriptionSeperator}${text}${DescriptionSeperator}`) + Doc.getDescription(doc).then(text => this._textToDocMap.set(text.trim(), doc) && `${DescriptionSeperator}${text}${DescriptionSeperator}`) )).then(docDescriptions => docDescriptions.join()); // prettier-ignore } }, @@ -110,8 +111,8 @@ export class GPTPopup extends ObservableReactComponent { @action public setMode = (mode: GPTPopupMode) => (this._mode = mode); onQuizRandom?: () => void; - onGptResponse?: (sortResult: string, questionType: GPTTypeStyle, tag?: string) => void; - questionTypeNumberToStyle = (questionType: string) => +questionType.split(' ')[0][0]; + onGptResponse?: (sortResult: string, questionType: GPTDocCommand, args?: string) => void; + NumberToCommandType = (questionType: string) => +questionType.split(' ')[0][0]; /** * Processes gpt's output depending on the type of question the user asked. Converts gpt's string output to @@ -120,44 +121,38 @@ export class GPTPopup extends ObservableReactComponent { * @param questionType * @param tag */ - processGptResponse = (docView: DocumentView, textToDocMap: Map, gptOutput: string, questionType: GPTTypeStyle, tag?: string) => + processGptResponse = (docView: DocumentView, textToDocMap: Map, gptOutput: string, questionType: GPTDocCommand, args?: string) => undoable(() => { - // Split the string into individual list items - const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); - - if (questionType === GPTTypeStyle.Filter) { - docView.ComponentView?.hasChildDocs?.().forEach(d => TagItem.removeTagFromDoc(d, '#chat')); - } - - if (questionType === GPTTypeStyle.SortDocs) { - docView.Document[docView.ComponentView?.fieldKey + '_sort'] = docSortings.Chat; - } - - listItems.forEach((item, index) => { - const normalizedItem = item.replace(/\n/g, ' ').trim(); - // find the corresponding Doc in the textToDoc map - const doc = textToDocMap.get(normalizedItem); - if (doc) { + switch (questionType) { // reset collection based on question typefc + case GPTDocCommand.Sort: + docView.Document[docView.ComponentView?.fieldKey + '_sort'] = docSortings.Chat; + break; + case GPTDocCommand.Filter: + docView.ComponentView?.hasChildDocs?.().forEach(d => TagItem.removeTagFromDoc(d, GPTPopup.ChatTag)); + break; + } // prettier-ignore + + gptOutput.split('======').filter(item => item.trim() !== '') // Split output into individual document contents + .map(docContentRaw => textToDocMap.get(docContentRaw.replace(/\n/g, ' ').trim())) // the find the corresponding Doc using textToDoc map + .filter(doc => doc).map(doc => doc!) // filter out undefined values + .forEach((doc, index) => { switch (questionType) { - case GPTTypeStyle.SortDocs: - doc.chatIndex = index; + case GPTDocCommand.Sort: + doc[ChatSortField] = index; break; - case GPTTypeStyle.AssignTags: - if (tag) { - const hashTag = tag.startsWith('#') ? tag : '#' + tag[0].toLowerCase() + tag.slice(1); - const filterTag = Doc.MyFilterHotKeys.map(key => StrCast(key.toolType)).find(key => key.includes(tag)) ?? hashTag; + case GPTDocCommand.AssignTags: + if (args) { + const hashTag = args.startsWith('#') ? args : '#' + args[0].toLowerCase() + args.slice(1); + const filterTag = Doc.MyFilterHotKeys.map(key => StrCast(key.toolType)).find(key => key.includes(args)) ?? hashTag; TagItem.addTagToDoc(doc, filterTag); } break; - case GPTTypeStyle.Filter: - TagItem.addTagToDoc(doc, '#chat'); - Doc.setDocFilter(docView.Document, 'tags', '#chat', 'check'); + case GPTDocCommand.Filter: + TagItem.addTagToDoc(doc, GPTPopup.ChatTag); + Doc.setDocFilter(docView.Document, 'tags', GPTPopup.ChatTag, 'check'); break; } - } else { - console.warn(`No matching document found for item: ${normalizedItem}`); - } - }); + }); // prettier-ignore }, '')(); /** @@ -173,7 +168,7 @@ export class GPTPopup extends ObservableReactComponent { StrCast(doc.gptRubric) ? Promise.resolve(StrCast(doc.gptRubric)) : Doc.getDescription(doc).then(desc => - gptAPICall(desc, GPTCallType.RUBRIC) + gptAPICall(desc, GPTCallType.MAKERUBRIC) .then(res => (doc.gptRubric = res)) .catch(err => console.error('GPT call failed', err)) ); @@ -191,7 +186,7 @@ export class GPTPopup extends ObservableReactComponent { `Question: ${desc}; UserAnswer: ${quizAnswer}; Rubric: ${StrCast(doc.gptRubric)}`, - GPTCallType.QUIZ + GPTCallType.QUIZDOC ).then(res => { this._conversationArray.push(res || 'GPT provided no answer'); this.onQuizRandom?.(); @@ -205,20 +200,20 @@ export class GPTPopup extends ObservableReactComponent { * @param userPrompt the user's input that chat will respond to */ generateUserPromptResponse = (userPrompt: string) => - gptAPICall(userPrompt, GPTCallType.TYPE).then(questionType => + gptAPICall(userPrompt, GPTCallType.COMMANDTYPE, undefined, true).then((commandType, args = commandType.split(' ').slice(1).join(' ')) => (async () => { - switch (this.questionTypeNumberToStyle(questionType)) { - case GPTTypeStyle.AssignTags: - case GPTTypeStyle.Filter: return this._documentDescriptions?.then(descs => gptAPICall(descs, GPTCallType.SUBSET, userPrompt)) ?? ""; - case GPTTypeStyle.SortDocs: return this._documentDescriptions?.then(descs => gptAPICall(descs, GPTCallType.SORT, userPrompt)) ?? ""; - default: return Doc.getDescription(DocumentView.SelectedDocs().lastElement()).then(desc => gptAPICall(desc, GPTCallType.INFO, userPrompt)); + switch (this.NumberToCommandType(commandType)) { + case GPTDocCommand.AssignTags: + case GPTDocCommand.Filter: return this._documentDescriptions?.then(descs => gptAPICall(userPrompt, GPTCallType.SUBSETDOCS, descs)) ?? ""; + case GPTDocCommand.Sort: return this._documentDescriptions?.then(descs => gptAPICall(userPrompt, GPTCallType.SORTDOCS, descs)) ?? ""; + default: return Doc.getDescription(DocumentView.SelectedDocs().lastElement()).then(desc => gptAPICall(userPrompt, GPTCallType.DOCINFO, desc)); } // prettier-ignore })().then( action(res => { // Trigger the callback with the result - this.onGptResponse?.(res || 'Something went wrong :(', this.questionTypeNumberToStyle(questionType), questionType.split(' ').slice(1).join(' ')); + this.onGptResponse?.(res || 'Something went wrong :(', this.NumberToCommandType(commandType), args); this._conversationArray.push( - [GPTTypeStyle.GeneralInfo, GPTTypeStyle.DocInfo].includes(this.questionTypeNumberToStyle(questionType)) ? res: + this.NumberToCommandType(commandType) === GPTDocCommand.GetInfo ? res: // Extract explanation surrounded by the DocSeperator string (defined in GPT.ts) at the top or both at the top and bottom (res.match(new RegExp(`${DocSeperator}\\s*([\\s\\S]*?)\\s*(?:${DocSeperator}|$)`)) ?? [])[1]?.trim() ?? 'No explanation found' ); @@ -583,10 +578,10 @@ export class GPTPopup extends ObservableReactComponent { tooltip="Clear Chat filter" toggleType={ToggleType.BUTTON} type={Type.PRIM} - toggleStatus={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat')} - text={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat') ? 'filtered' : ''} - color={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat') ? 'red' : 'transparent'} - onClick={() => this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', '#chat', 'remove')} + toggleStatus={Doc.hasDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag)} + text={Doc.hasDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag) ? 'filtered' : ''} + color={Doc.hasDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag) ? 'red' : 'transparent'} + onClick={() => this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag, 'remove')} /> {(this._mode === GPTPopupMode.USER_PROMPT || this._mode === GPTPopupMode.QUIZ_RESPONSE) && ( } onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} /> diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 950d9047c..bdd41b0bb 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1482,7 +1482,7 @@ export namespace Doc { case DocumentType.IMG: return curDescription || imageUrlToBase64(ImageCastWithSuffix(Doc.LayoutField(tdoc), '_o') ?? '') .then(hrefBase64 => gptImageLabel(hrefBase64, 'Give three to five labels to describe this image.')); case DocumentType.RTF: return RTFCast(tdoc[Doc.LayoutFieldKey(tdoc)]).Text; - default: return StrCast(tdoc.title); + default: return StrCast(tdoc.title).startsWith("Untitled") ? "" : StrCast(tdoc.title); }}); // prettier-ignore return docText(doc).then(text => (doc[DocData][Doc.LayoutFieldKey(doc) + '_description'] = text)); } -- cgit v1.2.3-70-g09d2 From 1c7c5bcadc7081e1a7e582413eee37b8201e1c4c Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 24 Feb 2025 18:07:36 -0500 Subject: added borders (width, color, and style) for DocumentViews. fixed dropdown slider buttons to show text labels. --- .../components/NumberDropdown/NumberDropdown.scss | 18 +- .../components/NumberDropdown/NumberDropdown.tsx | 182 +++++++++------------ packages/components/src/components/Popup/Popup.tsx | 8 +- packages/components/src/global/globalTypes.ts | 137 +++++++--------- src/client/documents/DocUtils.ts | 4 + src/client/documents/Documents.ts | 4 +- src/client/util/CurrentUserUtils.ts | 6 +- src/client/views/StyleProp.ts | 1 + src/client/views/StyleProvider.tsx | 51 +++--- src/client/views/global/globalScripts.ts | 55 +++++++ .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 21 +-- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 1 + .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 14 files changed, 263 insertions(+), 229 deletions(-) (limited to 'src/client/util') diff --git a/packages/components/src/components/NumberDropdown/NumberDropdown.scss b/packages/components/src/components/NumberDropdown/NumberDropdown.scss index 0999afb98..4ed5855d9 100644 --- a/packages/components/src/components/NumberDropdown/NumberDropdown.scss +++ b/packages/components/src/components/NumberDropdown/NumberDropdown.scss @@ -1,5 +1,19 @@ @import '../../global/globalCssVariables.scss'; .numberDropdown-container { - -} \ No newline at end of file +} + +.form-wrapper { + .iconButton-label { + position: relative; + z-index: 2; + width: 100%; + overflow: hidden; + white-space: normal; + display: flex; + text-align: center; + justify-content: center; + align-items: center; + font-size: $xsmall-fontSize !important; + } +} diff --git a/packages/components/src/components/NumberDropdown/NumberDropdown.tsx b/packages/components/src/components/NumberDropdown/NumberDropdown.tsx index a26cd71ab..7f12198d5 100644 --- a/packages/components/src/components/NumberDropdown/NumberDropdown.tsx +++ b/packages/components/src/components/NumberDropdown/NumberDropdown.tsx @@ -1,137 +1,101 @@ -import * as React from 'react' -import { Colors, IGlobalProps, INumberProps, Size, Type, getFontSize , getFormLabelSize } from '../../global' -import { Popup } from '../Popup' -import { Toggle, ToggleType } from '../Toggle' -import { useState } from 'react' -import { Slider } from '../Slider' -import { ListBox } from '../ListBox' -import { IListItemProps } from '../ListItem' -import { Group } from '../Group' -import { IconButton } from '../IconButton' -import * as fa from 'react-icons/fa' +import * as React from 'react'; +import { Colors, INumberProps, Size, getFormLabelSize } from '../../global'; +import { Popup } from '../Popup'; +import { Toggle, ToggleType } from '../Toggle'; +import { useState } from 'react'; +import { Slider } from '../Slider'; +import { ListBox } from '../ListBox'; +import { IListItemProps } from '../ListItem'; +import { Group } from '../Group'; +import { IconButton } from '../IconButton'; +import * as fa from 'react-icons/fa'; +import './NumberDropdown.scss'; - -export type NumberDropdownType = 'slider' | 'dropdown' | 'input' +export type NumberDropdownType = 'slider' | 'dropdown' | 'input'; export interface INumberDropdownProps extends INumberProps { - numberDropdownType: NumberDropdownType, - showPlusMinus?: boolean + numberDropdownType: NumberDropdownType; + showPlusMinus?: boolean; } export const NumberDropdown = (props: INumberDropdownProps) => { - const [numberLoc, setNumberLoc] = useState(0) - const { - fillWidth, - numberDropdownType = false, - color = Colors.MEDIUM_BLUE, - type, - formLabelPlacement, - showPlusMinus, - min, - max, - unit, - step = 1, - number = numberLoc, - setNumber = setNumberLoc, - size, - formLabel, - tooltip } = - props; + const [numberLoc, setNumberLoc] = useState(0); + const { fillWidth, numberDropdownType = false, color = Colors.MEDIUM_BLUE, type, formLabelPlacement, showPlusMinus, min, max, unit, step = 1, number = numberLoc, setNumber = setNumberLoc, size, formLabel, tooltip } = props; const [isOpen, setOpen] = useState(false); let toggleText = number.toString(); - if (unit) toggleText = toggleText + unit - let toggle = setOpen(!isOpen)} - />; - + if (unit) toggleText = toggleText + unit; + let toggle = setOpen(!isOpen)} />; + if (showPlusMinus) { - toggle = - } - color={color} - onClick={(e) => { - e.stopPropagation(); - setNumber(number - step); - }} - fillWidth={fillWidth} - tooltip={`Subtract ${step}${unit}`} - /> - {toggle} - } - color={color} - onClick={(e) => { - e.stopPropagation(); - setNumber(number + step); - }} - fillWidth={fillWidth} - tooltip={`Add ${step}${unit}`} - /> - + toggle = ( + + } + color={color} + onClick={e => { + e.stopPropagation(); + setNumber(number - step); + }} + fillWidth={fillWidth} + tooltip={`Subtract ${step}${unit}`} + /> + {toggle} + } + color={color} + onClick={e => { + e.stopPropagation(); + setNumber(number + step); + }} + fillWidth={fillWidth} + tooltip={`Add ${step}${unit}`} + /> + + ); } - + let popup; switch (numberDropdownType) { case 'dropdown': - let items: IListItemProps[] = []; - for (let i = min; i <= max; i += step) { - let text = i.toString() - if (unit) text = i.toString() + unit - items.push( - { + { + const items: IListItemProps[] = []; + for (let i = min; i <= max; i += step) { + let text = i.toString(); + if (unit) text = i.toString() + unit; + items.push({ text: text, val: i, - style: { textAlign: 'center' } - } - ) + style: { textAlign: 'center' }, + }); + } + popup = setNumber(num as number)} items={items} />; } - popup = setNumber(num as number)} - items={items} - /> break; case 'slider': default: - popup = + popup = ; break; case 'input': - popup = + popup = ; break; } - const numberDropdown: JSX.Element =
- -
+ const numberDropdown: JSX.Element = ( +
+ +
+ ); - return ( - formLabel ? -
+ return formLabel ? ( +
{numberDropdown} -
{formLabel}
+
+ {formLabel} +
- : + ) : ( numberDropdown - ) -} \ No newline at end of file + ); +}; diff --git a/packages/components/src/components/Popup/Popup.tsx b/packages/components/src/components/Popup/Popup.tsx index 92e7227bd..aa732d568 100644 --- a/packages/components/src/components/Popup/Popup.tsx +++ b/packages/components/src/components/Popup/Popup.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; -import { Colors, IGlobalProps, Placement, Size, getFormLabelSize, isDark } from '../../global'; +import { Colors, IGlobalProps, Placement, Size, isDark } from '../../global'; import { Toggle, ToggleType } from '../Toggle'; import './Popup.scss'; import { Popper } from '@mui/material'; @@ -16,7 +16,7 @@ export interface IPopupProps extends IGlobalProps { iconPlacement?: Placement; placement?: Placement; size?: Size; - height?: number; + height?: number | string; toggle?: JSX.Element; popup: JSX.Element | string | (() => JSX.Element); trigger?: PopupTrigger; @@ -62,12 +62,12 @@ export const Popup = (props: IPopupProps) => { } = props; const triggerRef = useRef(null); - const popperRef = useRef(null); + const popperRef = useRef(null); let timeout = setTimeout(() => {}); const handlePointerAwayDown = (e: PointerEvent) => { - const rect = (popperRef.current as any)?.getBoundingClientRect(); + const rect = popperRef.current?.getBoundingClientRect(); if (rect && !(rect.left < e.clientX && rect.top < e.clientY && rect.right > e.clientX && rect.bottom > e.clientY) && !popupContainsPt?.(e.clientX, e.clientY)) { e.preventDefault(); setOpen(false); diff --git a/packages/components/src/global/globalTypes.ts b/packages/components/src/global/globalTypes.ts index aa8451a9c..764fe7422 100644 --- a/packages/components/src/global/globalTypes.ts +++ b/packages/components/src/global/globalTypes.ts @@ -1,87 +1,76 @@ -import { PointerEventHandler } from "react" -import { Size } from "./globalEnums" +import { PointerEventHandler } from 'react'; +import { Size } from './globalEnums'; -export interface IGlobalProps { - // Size - size?: Size - height?: number - width?: number - fillWidth?: boolean - color?: string - background?: string +export enum Type { + PRIM = 'primary', + SEC = 'secondary', + TERT = 'tertiary', +} - // Type - type?: Type +export type Placement = 'bottom-end' | 'bottom-start' | 'bottom' | 'left-end' | 'left-start' | 'left' | 'right-end' | 'right-start' | 'right' | 'top-end' | 'top-start' | 'top'; - // Status - inactive?: boolean +export type Alignment = 'flex-start' | 'flex-end' | 'center'; - // Content - tooltip?: string - tooltipPlacement?: Placement +export type TextAlignment = 'center' | 'left' | 'right'; - // Label - label?: string - hideLabel?: boolean +export interface IGlobalProps { + // Size + size?: Size; + height?: number | string; + width?: number; + fillWidth?: boolean; + color?: string; + background?: string; - // Label when used in forms - formLabel?: string - formLabelPlacement?: Placement + // Type + type?: Type; - // Custom style - style?: React.CSSProperties + // Status + inactive?: boolean; - // Global pointer events - onPointerDown?: PointerEventHandler | undefined; - onPointerDownCapture?: PointerEventHandler | undefined; - onPointerMove?: PointerEventHandler | undefined; - onPointerMoveCapture?: PointerEventHandler | undefined; - onPointerUp?: PointerEventHandler | undefined; - onPointerUpCapture?: PointerEventHandler | undefined; - onPointerCancel?: PointerEventHandler | undefined; - onPointerCancelCapture?: PointerEventHandler | undefined; - onPointerEnter?: PointerEventHandler | undefined; - onPointerEnterCapture?: PointerEventHandler | undefined; - onPointerLeave?: PointerEventHandler | undefined; - onPointerLeaveCapture?: PointerEventHandler | undefined; - onPointerOver?: PointerEventHandler | undefined; - onPointerOverCapture?: PointerEventHandler | undefined; - onPointerOut?: PointerEventHandler | undefined; - onPointerOutCapture?: PointerEventHandler | undefined; - onGotPointerCapture?: PointerEventHandler | undefined; - onGotPointerCaptureCapture?: PointerEventHandler | undefined; - onLostPointerCapture?: PointerEventHandler | undefined; - onLostPointerCaptureCapture?: PointerEventHandler | undefined; -} + // Content + tooltip?: string; + tooltipPlacement?: Placement; -export interface INumberProps extends IGlobalProps { - min: number, - max: number, - step?: number, - number: number - setNumber?: (num: number) => unknown, - unit?: string -} + // Label + label?: string; + hideLabel?: boolean; -export enum Type { - PRIM = "primary", - SEC = "secondary", - TERT = "tertiary", -} + // Label when used in forms + formLabel?: string; + formLabelPlacement?: Placement; -export type Placement = 'bottom-end' - | 'bottom-start' - | 'bottom' - | 'left-end' - | 'left-start' - | 'left' - | 'right-end' - | 'right-start' - | 'right' - | 'top-end' - | 'top-start' - | 'top' + // Custom style + style?: React.CSSProperties; -export type Alignment = 'flex-start' | 'flex-end' | 'center' + // Global pointer events + onPointerDown?: PointerEventHandler | undefined; + onPointerDownCapture?: PointerEventHandler | undefined; + onPointerMove?: PointerEventHandler | undefined; + onPointerMoveCapture?: PointerEventHandler | undefined; + onPointerUp?: PointerEventHandler | undefined; + onPointerUpCapture?: PointerEventHandler | undefined; + onPointerCancel?: PointerEventHandler | undefined; + onPointerCancelCapture?: PointerEventHandler | undefined; + onPointerEnter?: PointerEventHandler | undefined; + onPointerEnterCapture?: PointerEventHandler | undefined; + onPointerLeave?: PointerEventHandler | undefined; + onPointerLeaveCapture?: PointerEventHandler | undefined; + onPointerOver?: PointerEventHandler | undefined; + onPointerOverCapture?: PointerEventHandler | undefined; + onPointerOut?: PointerEventHandler | undefined; + onPointerOutCapture?: PointerEventHandler | undefined; + onGotPointerCapture?: PointerEventHandler | undefined; + onGotPointerCaptureCapture?: PointerEventHandler | undefined; + onLostPointerCapture?: PointerEventHandler | undefined; + onLostPointerCaptureCapture?: PointerEventHandler | undefined; +} -export type TextAlignment = 'center' | 'left' | 'right' \ No newline at end of file +export interface INumberProps extends IGlobalProps { + min: number; + max: number; + step?: number; + number: number; + setNumber?: (num: number) => unknown; + unit?: string; +} diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 23032b62e..f1de6fe36 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -692,6 +692,8 @@ export namespace DocUtils { // annotationOn, backgroundColor: backgroundColor ?? StrCast(Doc.UserDoc().textBackgroundColor), + borderColor: Doc.UserDoc().borderColor as string, + borderWidth: Doc.UserDoc().borderWidth as number, x, y, title, @@ -718,6 +720,8 @@ export namespace DocUtils { _layout_fitWidth: true, _layout_autoHeight: true, backgroundColor: StrCast(Doc.UserDoc().textBackgroundColor), + borderColor: Doc.UserDoc().borderColor as string, + borderWidth: Doc.UserDoc().borderWidth as number, text_fitBox: BoolCast(Doc.UserDoc().fitBox), text_align: StrCast(Doc.UserDoc().textAlign), text_fontColor: StrCast(Doc.UserDoc().fontColor), diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 891223952..1ce25165c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -240,8 +240,8 @@ export class DocumentOptions { dataViz?: string; dataViz_savedTemplates?: LISTt; - borderWidth?: STRt = new StrInfo('Width of user-added border', false); - borderColor?: STRt = new StrInfo('Color of user-added border', false); + borderWidth?: NUMt = new NumInfo('Width of docuent border', false); + borderColor?: STRt = new StrInfo('Color of document border', false); text_fontColor?: STRt = new StrInfo('Color of text', false); hCentering?: 'h-left' | 'h-center' | 'h-right'; isDefaultTemplateDoc?: BOOLt = new BoolInfo(''); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index fb349abd9..d2d7cabd2 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -734,7 +734,7 @@ pie title Minerals in my tap water } static viewTools(): Button[] { return [ - { title: "Show Tags", icon: "id-card", toolTip: "Toggle tags", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"toggle-tags",funcs: { }, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Tags", icon: "id-card", toolTip: "Toggle Tags display", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"toggle-tags",funcs: { }, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Fit All", icon: "object-group", toolTip:"Fit Docs to View (double tap to persist)", @@ -833,11 +833,13 @@ pie title Minerals in my tap water { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} }, { title: "Template",icon: "scroll", toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF, scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} }, { title: "Fill", icon: "fill-drip", toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'} }, // Only when a document is selected + { title: "Border", icon: "pen", toolTip: "Border Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBorderColor(value, _readOnly_)'} }, // Only when a document is selected + { title: "B.Width", toolTip: "Border width", btnType: ButtonType.NumberSliderButton, ignoreClick: true, scripts: {script: '{ return setBorderWidth(value, _readOnly_);}'}, numBtnMin: 0, linearBtnWidth:40}, { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}}, { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}}, { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}}, - { title: "Chat", icon:"lightbulb", toolTip: "Toggle Chat Assistant",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, width: 30, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, + { title: "Chat", icon: "lightbulb", toolTip: "Toggle Chat Assistant",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, width: 30, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} }, { title: "Filter", icon: "=", toolTip: "Filter cards by tags", subMenu: CurrentUserUtils.filterTools(), ignoreClick:true, toolType:DocumentType.COL, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, btnType: ButtonType.MultiToggleButton, width: 30, backgroundColor: doc.userVariantColor as string}, { title: "Sort", icon: "Sort", toolTip: "Sort Documents", subMenu: CurrentUserUtils.sortTools(), expertMode: false, toolType:DocumentType.COL, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available diff --git a/src/client/views/StyleProp.ts b/src/client/views/StyleProp.ts index 56367e70b..1ef7a9e1f 100644 --- a/src/client/views/StyleProp.ts +++ b/src/client/views/StyleProp.ts @@ -5,6 +5,7 @@ export enum StyleProp { Opacity = 'opacity', // opacity of the document view BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views BorderRounding = 'borderRounding', // border radius of the document view + Border = 'border', // border of document view Color = 'color', // foreground color of Document view items BackgroundColor = 'backgroundColor', // background color of a document view FillColor = 'fillColor', // fill color of an ink stroke or shape diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index bebc9a341..b04b1ae65 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -206,33 +206,40 @@ export function DefaultStyleProvider(doc: Opt, props: Opt - - - -
- ), - }; - } + // const borderPath = doc && border(doc, NumCast(doc._width), NumCast(doc._height), radius, -ratio/2); + // return !borderPath + // ? null + // : { + // clipPath: `path('${borderPath}')`, + // jsx: ( + //
+ // + // + // + //
+ // ), + // }; + // } case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._type_collection as CollectionViewType) || (doc?.type === DocumentType.RTF && !layoutShowTitle()?.includes('noMargin')) || diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 79873ed8f..b455f76e4 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -66,6 +66,49 @@ ScriptingGlobals.add(function setView(view: string, shiftKey: boolean, checkResu return undefined; }); +// toggle: Set overlay status of selected document +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function setBorderColor(color?: string, checkResult?: boolean) { + const selectedViews = DocumentView.Selected(); + const defaultBorder = () => StrCast(Doc.UserDoc().borderColor, 'transparent'); + const setDefaultBorder = (c: string) => { Doc.UserDoc().borderColor = c; }; // prettier-ignore + const fieldKey = 'borderColor'; + if (selectedViews.length) { + if (checkResult) { + const selView = selectedViews.lastElement(); + const layoutFrameNumber = Cast(selView.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const contentFrameNumber = Cast(selView.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed + return CollectionFreeFormDocumentView.getStringValues(selView?.Document, contentFrameNumber)[fieldKey] || defaultBorder(); + } + setDefaultBorder(color ?? 'transparent'); + selectedViews.forEach(dv => { + const layoutFrameNumber = Cast(dv.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values + const contentFrameNumber = Cast(dv.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed + if (contentFrameNumber !== undefined) { + const obj: { [key: string]: Opt } = {}; + obj[fieldKey] = color; + CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.Document, obj); + } else { + const dataKey = Doc.LayoutFieldKey(dv.Document); + const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', ''); + dv.layoutDoc[fieldKey + alternate] = undefined; + dv.dataDoc[fieldKey + alternate] = color; + } + }); + } else { + const selected = DocumentView.SelectedDocs().length ? DocumentView.SelectedDocs() : LinkManager.Instance.currentLink ? [LinkManager.Instance.currentLink] : []; + if (checkResult) { + return (selected.lastElement() ?? Doc.UserDoc()).borderColor ?? defaultBorder(); + } + if (!selected.length) setDefaultBorder(color ?? 'transparent'); + else + selected.forEach(doc => { + doc[DocData].borderColor = color; + }); + } + return ''; +}); + // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { @@ -408,6 +451,18 @@ ScriptingGlobals.add(function activeEraserTool() { return StrCast(Doc.UserDoc().activeEraserTool, InkEraserTool.Stroke); }, 'returns the current eraser tool'); +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function setBorderWidth(value: number, checkResult?: boolean) { + const selected = DocumentView.SelectedDocs().lastElement(); + if (checkResult) return NumCast((selected ?? Doc.UserDoc()).borderWidth); + if (!selected) Doc.UserDoc().borderWidth = value; + else + DocumentView.SelectedDocs().map(doc => { + doc.borderWidth = value; + }); + return undefined; +}, 'sets the border width of the selected document'); + // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setInkProperty(option: InkProperty, value: string | number, checkResult?: boolean) { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index beea6ab3c..76d6ed80b 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -69,7 +69,7 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames public static from(dv?: DocumentView): CollectionFreeFormDocumentView | undefined { return dv?._props.reactParent instanceof CollectionFreeFormDocumentView ? dv._props.reactParent : undefined; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0193fd328..441d6053f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -131,6 +131,7 @@ export class DocumentViewInternal extends DocComponent this._props.styleProvider?.(doc, this._props, sprop); @computed get opacity() { return this.style(this.layoutDoc, StyleProp.Opacity) as number; } // prettier-ignore @computed get boxShadow() { return this.style(this.layoutDoc, StyleProp.BoxShadow) as string; } // prettier-ignore + @computed get border() { return this.style(this.layoutDoc, StyleProp.Border) as string || ""; } // prettier-ignore @computed get borderRounding() { return this.style(this.layoutDoc, StyleProp.BorderRounding) as string; } // prettier-ignore @computed get widgetDecorations() { return this.style(this.layoutDoc, StyleProp.Decorations) as JSX.Element; } // prettier-ignore @computed get backgroundBoxColor(){ return this.style(this.layoutDoc, StyleProp.BackgroundColor + ':docView') as string; } // prettier-ignore @@ -684,14 +685,14 @@ export class DocumentViewInternal extends DocComponent this._rootSelected; - panelHeight = () => this._props.PanelHeight() - this.headerMargin; + panelHeight = () => this._props.PanelHeight() - this.headerMargin - 2 * NumCast(this.Document.borderWidth); screenToLocalContent = () => this._props .ScreenToLocalTransform() - .translate(0, -this.headerMargin) + .translate(-NumCast(this.Document.borderWidth), -this.headerMargin - NumCast(this.Document.borderWidth)) .scale(this._props.showAIEditor ? (this._props.PanelHeight() || 1) / this.aiContentsHeight() : 1); onClickFunc = this.disableClickScriptFunc ? undefined : () => this.onClickHdlr; - setHeight = (height: number) => { !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height)); } // prettier-ignore + setHeight = (height: number) => { !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height + 2 * NumCast(this.Document.borderWidth))); } // prettier-ignore setContentView = action((view: ViewBoxInterface) => { this._componentView = view; }); // prettier-ignore isContentActive = (): boolean | undefined => this._isContentActive; childFilters = () => [...this._props.childFilters(), ...StrListCast(this.layoutDoc.childFilters)]; @@ -989,15 +990,11 @@ export class DocumentViewInternal extends DocComponent (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)} onPointerLeave={e => !isParentOf(this._contentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.Document)} style={{ - borderRadius: this.borderRounding, + borderRadius: this._componentView?.isUnstyledView?.() ? undefined : this.borderRounding, pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here) }}> {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG || !renderDoc ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} @@ -1487,7 +1484,7 @@ export class DocumentView extends DocComponent() { ShouldNotScale = () => this.shouldNotScale; NativeWidth = () => this.effectiveNativeWidth; NativeHeight = () => this.effectiveNativeHeight; - PanelWidth = () => this.panelWidth; + PanelWidth = () => this.panelWidth - 2 * NumCast(this.Document.borderWidth); PanelHeight = () => this.panelHeight; ReducedPanelWidth = () => this.panelWidth / 2; ReducedPanelHeight = () => this.panelWidth / 2; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index f58862028..f60c83343 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -134,6 +134,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { min={NumCast(this.dataDoc.numBtnMin, 0)} max={NumCast(this.dataDoc.numBtnMax, 100)} number={checkResult} + size={Size.XSMALL} setNumber={undoable(value => numScript(value), `${this.Document.title} button set from list`)} fillWidth /> diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 3abb39ff2..da2131940 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1282,7 +1282,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }), + () => ({ border: this._props.PanelHeight(), sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }), ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight }) => { const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); if ( -- cgit v1.2.3-70-g09d2 From 515707c4561eb526426b8fa07dd50bd499fb91cc Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 25 Feb 2025 01:03:25 -0500 Subject: added a hideUI option to hide buttons. fixed a mess of runtime warnings mostly related to how scss files can be included in each other --- .../components/src/components/Button/Button.scss | 184 +++++------ .../src/components/ColorPicker/ColorPicker.scss | 36 +-- .../src/components/Dropdown/Dropdown.scss | 223 +++++++------- .../components/DropdownSearch/DropdownSearch.scss | 207 +++++++------ .../src/components/EditableText/EditableText.scss | 224 +++++++------- .../src/components/FormInput/FormInput.scss | 112 +++---- .../components/src/components/Group/Group.scss | 23 +- .../src/components/IconButton/IconButton.scss | 190 ++++++------ .../components/src/components/ListBox/ListBox.scss | 4 +- .../src/components/ListItem/ListItem.scss | 132 ++++---- .../components/src/components/Modal/Modal.scss | 74 ++--- .../src/components/MultiToggle/MultiToggle.scss | 6 +- .../components/NumberDropdown/NumberDropdown.scss | 7 +- .../src/components/NumberInput/NumberInput.scss | 4 +- .../components/src/components/Popup/Popup.scss | 40 +-- .../components/src/components/Slider/Slider.scss | 305 +++++++++---------- .../components/src/components/Slider/Slider.tsx | 338 +++++++++++---------- .../src/components/Template/Template.scss | 6 +- .../components/src/components/Toggle/Toggle.scss | 122 ++++---- .../components/src/global/globalCssVariables.scss | 110 +++---- src/client/util/CaptureManager.scss | 2 - src/client/util/CurrentUserUtils.ts | 14 +- src/client/util/SettingsManager.scss | 2 - src/client/util/SnappingManager.ts | 3 + src/client/util/reportManager/ReportManager.scss | 4 +- src/client/views/AntimodeMenu.scss | 6 +- src/client/views/ContextMenu.scss | 16 +- src/client/views/DashboardView.scss | 16 +- src/client/views/DocumentButtonBar.scss | 23 +- src/client/views/DocumentDecorations.scss | 38 +-- src/client/views/LightboxView.tsx | 4 +- src/client/views/Main.scss | 12 +- src/client/views/Main.tsx | 3 +- src/client/views/MainView.scss | 18 +- src/client/views/MainView.tsx | 8 +- src/client/views/PropertiesButtons.scss | 20 +- src/client/views/PropertiesSection.scss | 2 - src/client/views/PropertiesView.scss | 6 +- src/client/views/TemplateMenu.scss | 8 +- src/client/views/animationtimeline/Region.scss | 10 +- src/client/views/animationtimeline/Timeline.scss | 6 +- .../views/animationtimeline/TimelineMenu.scss | 16 +- .../views/animationtimeline/TimelineOverview.scss | 2 +- src/client/views/animationtimeline/Track.scss | 6 +- .../views/collections/CollectionCardDeckView.scss | 2 - .../collections/CollectionCarousel3DView.scss | 12 +- .../views/collections/CollectionDockingView.scss | 22 +- src/client/views/collections/CollectionMenu.scss | 6 +- .../collections/CollectionNoteTakingView.scss | 22 +- .../collections/CollectionStackedTimeline.scss | 26 +- .../views/collections/CollectionStackingView.scss | 22 +- .../views/collections/CollectionTreeView.scss | 10 +- src/client/views/collections/CollectionView.scss | 6 +- src/client/views/collections/TabDocView.scss | 2 +- src/client/views/collections/TreeView.scss | 6 +- .../collectionFreeForm/CollectionFreeFormView.scss | 16 +- .../collectionFreeForm/ImageLabelHandler.tsx | 14 +- .../collectionLinear/CollectionLinearView.scss | 22 +- .../collectionSchema/CollectionSchemaView.scss | 40 ++- src/client/views/linking/LinkMenu.scss | 2 +- src/client/views/linking/LinkMenuItem.scss | 8 +- .../views/newlightbox/ButtonMenu/ButtonMenu.scss | 12 +- .../views/newlightbox/ExploreView/ExploreView.scss | 48 +-- .../views/newlightbox/Header/LightboxHeader.scss | 28 +- .../RecommendationList/RecommendationList.scss | 179 ++++++----- .../components/EditableText/EditableText.scss | 46 +-- .../components/Recommendation/Recommendation.scss | 122 ++++---- .../components/SkeletonDoc/SkeletonDoc.scss | 133 ++++---- .../newlightbox/components/Template/Template.scss | 12 +- src/client/views/nodes/AudioBox.scss | 42 +-- .../views/nodes/DataVizBox/components/Chart.scss | 10 +- src/client/views/nodes/DocumentLinksButton.scss | 18 +- src/client/views/nodes/DocumentView.scss | 6 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/EquationBox.scss | 2 - .../views/nodes/FontIconBox/FontIconBox.scss | 36 +-- src/client/views/nodes/IconTagBox.scss | 4 +- src/client/views/nodes/KeyValueBox.scss | 22 +- src/client/views/nodes/KeyValuePair.scss | 2 +- src/client/views/nodes/LinkDescriptionPopup.scss | 10 +- src/client/views/nodes/MapBox/AnimationUtility.ts | 4 +- src/client/views/nodes/MapBox/MapBox.scss | 16 +- src/client/views/nodes/PDFBox.scss | 8 +- src/client/views/nodes/VideoBox.scss | 16 +- src/client/views/nodes/WebBox.scss | 4 +- .../nodes/chatbot/chatboxcomponents/ChatBox.scss | 11 +- .../views/nodes/formattedText/DashFieldView.scss | 4 +- .../nodes/formattedText/FormattedTextBox.scss | 20 +- .../views/nodes/formattedText/RichTextMenu.scss | 4 +- src/client/views/nodes/imageEditor/ImageEditor.tsx | 8 +- src/client/views/nodes/trails/PresBox.scss | 142 ++++----- src/client/views/search/SearchBox.scss | 10 +- src/client/views/topbar/TopBar.scss | 29 +- 93 files changed, 1909 insertions(+), 1931 deletions(-) (limited to 'src/client/util') diff --git a/packages/components/src/components/Button/Button.scss b/packages/components/src/components/Button/Button.scss index a31923e6d..bbe2e2470 100644 --- a/packages/components/src/components/Button/Button.scss +++ b/packages/components/src/components/Button/Button.scss @@ -1,118 +1,118 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .button-container { - position: relative; - width: fit-content; - padding: $padding; - cursor: pointer; - overflow: hidden; - user-select: none; - display: flex; - justify-content: center; - align-items: center; - gap: 5px; - font-family: $default-font; - border-radius: $standard-border-radius; - white-space: nowrap; - transition: 0.4s; - border: solid 1px; - border-color: transparent; - pointer-events: all; - - &.icon { - padding: 0; - gap: 0; - } - - .button-content { + position: relative; + width: fit-content; + padding: global.$padding; + cursor: pointer; + overflow: hidden; + user-select: none; display: flex; justify-content: center; align-items: center; - width: fit-content; - height: 100%; - z-index: 1; gap: 5px; + font-family: global.$default-font; + border-radius: global.$standard-border-radius; + white-space: nowrap; + transition: 0.4s; + border: solid 1px; + border-color: transparent; + pointer-events: all; - .icon { - display: flex; - justify-content: center; - align-items: center; + &.icon { + padding: 0; + gap: 0; } - } - - .background { - width: 100%; - height: 100%; - z-index: 0; - left: 0; - top: 0; - position: absolute; - transition: 0.4s; - } - &.inactive { - &:hover { - .background { - filter: opacity(0) !important; - } + .button-content { + display: flex; + justify-content: center; + align-items: center; + width: fit-content; + height: 100%; + z-index: 1; + gap: 5px; + + .icon { + display: flex; + justify-content: center; + align-items: center; + } } - } - &.primary { .background { - filter: opacity(0); - - &.active { - filter: opacity(0.2) !important; - } + width: 100%; + height: 100%; + z-index: 0; + left: 0; + top: 0; + position: absolute; + transition: 0.4s; } - &:hover{ - .background { - filter: opacity(0.2) - } + &.inactive { + &:hover { + .background { + filter: opacity(0) !important; + } + } } - } - &.secondary { - .background { - filter: opacity(0); + &.primary { + .background { + filter: opacity(0); - &.active { - filter: opacity(0.2) !important; - } - } + &.active { + filter: opacity(0.2) !important; + } + } - &:hover{ - .background { - filter: opacity(0.2) - } + &:hover { + .background { + filter: opacity(0.2); + } + } } - } - &.tertiary { - &:hover{ - box-shadow: $standard-shadow; - } + &.secondary { + .background { + filter: opacity(0); - .background { - filter: opacity(1) !important; + &.active { + filter: opacity(0.2) !important; + } + } + + &:hover { + .background { + filter: opacity(0.2); + } + } } - &:hover{ - .background { - filter: brightness(0.8); - } + &.tertiary { + &:hover { + box-shadow: global.$standard-shadow; + } + + .background { + filter: opacity(1) !important; + } + + &:hover { + .background { + filter: brightness(0.8); + } + } } - } - .label { - position: absolute; - bottom: 0; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - font-size: $xsmall-fontSize; - } + .label { + position: absolute; + bottom: 0; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + font-size: global.$xsmall-fontSize; + } } diff --git a/packages/components/src/components/ColorPicker/ColorPicker.scss b/packages/components/src/components/ColorPicker/ColorPicker.scss index e3ed32a45..32b912fe5 100644 --- a/packages/components/src/components/ColorPicker/ColorPicker.scss +++ b/packages/components/src/components/ColorPicker/ColorPicker.scss @@ -1,23 +1,23 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .colorPicker-container { - display: flex; - border-radius: $standard-border-radius; - width: fit-content; - height: fit-content; - position: relative; - - .colorPicker-toggle { - width: 100%; - height: 100%; - position: relative; - cursor: pointer; - } - - .colorPicker-popup { - position: absolute; - top: calc(100% + 5px); + display: flex; + border-radius: global.$standard-border-radius; width: fit-content; height: fit-content; - } + position: relative; + + .colorPicker-toggle { + width: 100%; + height: 100%; + position: relative; + cursor: pointer; + } + + .colorPicker-popup { + position: absolute; + top: calc(100% + 5px); + width: fit-content; + height: fit-content; + } } diff --git a/packages/components/src/components/Dropdown/Dropdown.scss b/packages/components/src/components/Dropdown/Dropdown.scss index 34ed84004..f9ea2711a 100644 --- a/packages/components/src/components/Dropdown/Dropdown.scss +++ b/packages/components/src/components/Dropdown/Dropdown.scss @@ -1,135 +1,136 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .dropdown { - margin-top: 10px; + margin-top: 10px; } .divider { - height: 1px; - width: 100%; - background: $medium-gray; + height: 1px; + width: 100%; + background: global.$medium-gray; } .dropdown-container { - display: flex; - flex-direction: column; - justify-content: center; - min-width: fit-content; - width: 100%; - border-radius: $standard-border-radius; - height: 100%; - position: relative; - transition: 0.4s; - - .dropdown-list { - position: absolute; - top: 100%; + display: flex; + flex-direction: column; + justify-content: center; + min-width: fit-content; width: 100%; - } - .dropdown-toggle-mini, - .dropdown-toggle { - width: calc(100% - 2px); - display: grid; - grid-template-columns: calc(100% - 30px) 30px; - grid-template-areas: 'button end'; - grid-template-rows: 1fr; + border-radius: global.$standard-border-radius; + height: 100%; position: relative; - align-items: center; - border: solid 1px; - border-color: transparent; - border-radius: $standard-border-radius; - overflow: hidden; - - &.inactive { - filter: opacity(0.5); - pointer-events: none; - cursor: not-allowed; - } + transition: 0.4s; - .background { - width: 100%; - height: 100%; - z-index: 0; - position: absolute; - transition: 0.4s; + .dropdown-list { + position: absolute; + top: 100%; + width: 100%; } + .dropdown-toggle-mini, + .dropdown-toggle { + width: calc(100% - 2px); + display: grid; + grid-template-columns: calc(100% - 30px) 30px; + grid-template-areas: 'button end'; + grid-template-rows: 1fr; + position: relative; + align-items: center; + border: solid 1px; + border-color: transparent; + border-radius: global.$standard-border-radius; + overflow: hidden; - &.inactive { - &:hover { - .background { - filter: opacity(0) !important; + &.inactive { + filter: opacity(0.5); + pointer-events: none; + cursor: not-allowed; } - } - } - - &.primary { - .background { - filter: opacity(0); - - &.active { - filter: opacity(0.2) !important; - } - } - - &:hover{ + .background { - filter: opacity(0.2) + width: 100%; + height: 100%; + z-index: 0; + position: absolute; + transition: 0.4s; } - } - } - - &.secondary { - .background { - filter: opacity(0); - - &.active { - filter: opacity(0.2) !important; + + &.inactive { + &:hover { + .background { + filter: opacity(0) !important; + } + } } - } - - &:hover{ - .background { - filter: opacity(0.2) + + &.primary { + .background { + filter: opacity(0); + + &.active { + filter: opacity(0.2) !important; + } + } + + &:hover { + .background { + filter: opacity(0.2); + } + } } - } - } - - &.tertiary { - &:hover{ - box-shadow: $standard-button-shadow; - } - - &:hover{ - .background { - filter: brightness(0.8); + + &.secondary { + .background { + filter: opacity(0); + + &.active { + filter: opacity(0.2) !important; + } + } + + &:hover { + .background { + filter: opacity(0.2); + } + } } - } - } - .toggle-button { - grid-area: button; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - min-width: 70px; - justify-self: center; - } + &.tertiary { + &:hover { + box-shadow: global.$standard-button-shadow; + } - .toggle-caret { - cursor: pointer; - grid-area: end; - display: flex; - justify-content: flex-end; - align-items: center; - justify-self: center; + &:hover { + .background { + filter: brightness(0.8); + } + } + } + + .toggle-button { + grid-area: button; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + min-width: 70px; + justify-self: center; + } + + .toggle-caret { + cursor: pointer; + grid-area: end; + display: flex; + justify-content: flex-end; + align-items: center; + justify-self: center; + } } - } - .dropdown-toggle-mini { - .toggle-caret { - position: absolute; - top:0; left:0; + .dropdown-toggle-mini { + .toggle-caret { + position: absolute; + top: 0; + left: 0; + } } - } } diff --git a/packages/components/src/components/DropdownSearch/DropdownSearch.scss b/packages/components/src/components/DropdownSearch/DropdownSearch.scss index e111c822b..d937df540 100644 --- a/packages/components/src/components/DropdownSearch/DropdownSearch.scss +++ b/packages/components/src/components/DropdownSearch/DropdownSearch.scss @@ -1,123 +1,122 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .dropdownsearch { - margin-top: 10px; + margin-top: 10px; } .divider { - height: 1px; - width: 100%; - background: $medium-gray; + height: 1px; + width: 100%; + background: global.$medium-gray; } .dropdownsearch-container { - display: flex; - flex-direction: column; - justify-content: center; - min-width: fit-content; - border-radius: $standard-border-radius; - height: 100%; - position: relative; - transition: 0.4s; - - .dropdownsearch-list { - position: absolute; - top: 100%; - width: 100%; - } - - .dropdownsearch-toggle { - width: 100%; - display: grid; - grid-template-columns: calc(100% - 30px) 30px; - grid-template-areas: 'button end'; - grid-template-rows: 1fr; + display: flex; + flex-direction: column; + justify-content: center; + min-width: fit-content; + border-radius: global.$standard-border-radius; + height: 100%; position: relative; - align-items: center; - border: solid 1px; - border-color: transparent; - border-radius: $standard-border-radius; - overflow: hidden; - - .toggle-background { - width: 100%; - height: 100%; - z-index: 0; - position: absolute; - transition: 0.4s; - - &.active { - filter: opacity(0.2) !important; - } + transition: 0.4s; + + .dropdownsearch-list { + position: absolute; + top: 100%; + width: 100%; } - &.primary { - color: $medium-blue; - .toggle-background { - background: $medium-blue; - filter: opacity(0); - } - - &:hover{ + .dropdownsearch-toggle { + width: 100%; + display: grid; + grid-template-columns: calc(100% - 30px) 30px; + grid-template-areas: 'button end'; + grid-template-rows: 1fr; + position: relative; + align-items: center; + border: solid 1px; + border-color: transparent; + border-radius: global.$standard-border-radius; + overflow: hidden; + .toggle-background { - filter: opacity(0.2) + width: 100%; + height: 100%; + z-index: 0; + position: absolute; + transition: 0.4s; + + &.active { + filter: opacity(0.2) !important; + } } - } - - } - - &.secondary { - .toggle-background { - background: $medium-blue; - filter: opacity(0); - } - - border: solid 1px $medium-blue; - color: $medium-blue; - - &:hover{ - .toggle-background { - filter: opacity(0.2) + + &.primary { + color: global.$medium-blue; + .toggle-background { + background: global.$medium-blue; + filter: opacity(0); + } + + &:hover { + .toggle-background { + filter: opacity(0.2); + } + } } - } - } - - &.tertiary { - color: white; - - .toggle-background { - background: $medium-blue; - } - - &:hover{ - box-shadow: $standard-button-shadow; - } - - &:hover{ - .toggle-background { - filter: brightness(0.8); + + &.secondary { + .toggle-background { + background: global.$medium-blue; + filter: opacity(0); + } + + border: solid 1px global.$medium-blue; + color: global.$medium-blue; + + &:hover { + .toggle-background { + filter: opacity(0.2); + } + } } - } - } - .toggle-button { - grid-area: button; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - min-width: 70px; - justify-self: center; - } + &.tertiary { + color: white; + + .toggle-background { + background: global.$medium-blue; + } - .toggle-caret { - cursor: pointer; - grid-area: end; - display: flex; - justify-content: flex-end; - align-items: center; - justify-self: center; + &:hover { + box-shadow: global.$standard-button-shadow; + } + + &:hover { + .toggle-background { + filter: brightness(0.8); + } + } + } + + .toggle-button { + grid-area: button; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + min-width: 70px; + justify-self: center; + } + + .toggle-caret { + cursor: pointer; + grid-area: end; + display: flex; + justify-content: flex-end; + align-items: center; + justify-self: center; + } } - } } diff --git a/packages/components/src/components/EditableText/EditableText.scss b/packages/components/src/components/EditableText/EditableText.scss index 19e5af2cd..15965e97e 100644 --- a/packages/components/src/components/EditableText/EditableText.scss +++ b/packages/components/src/components/EditableText/EditableText.scss @@ -1,131 +1,129 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .editableText-container { - position: relative; - width: fit-content; - border: solid 1px; - border-color: transparent; - border-radius: $standard-border-radius; - font-family: $default-font; - overflow: hidden; - padding: $padding; - - .password { - position: absolute; - display: flex; - justify-content: center; - align-items: center; - height: 100%; - right: 0; - top: 0; - } - - .editableText-background { - width: 100%; - height: 100%; - z-index: -1; - position: absolute; - transition: 0.4s; - top: 0; - left: 0; - } - - &.primary { - - &:focus-within { - .editableText-background { - filter: opacity(0.2) !important; - } + position: relative; + width: fit-content; + border: solid 1px; + border-color: transparent; + border-radius: global.$standard-border-radius; + font-family: global.$default-font; + overflow: hidden; + padding: global.$padding; + + .password { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + right: 0; + top: 0; } .editableText-background { - filter: opacity(0); - - &.active { - filter: opacity(0.2) !important; - } + width: 100%; + height: 100%; + z-index: -1; + position: absolute; + transition: 0.4s; + top: 0; + left: 0; } - &:hover{ - .editableText-background { - filter: opacity(0.2) - } + &.primary { + &:focus-within { + .editableText-background { + filter: opacity(0.2) !important; + } + } + + .editableText-background { + filter: opacity(0); + + &.active { + filter: opacity(0.2) !important; + } + } + + &:hover { + .editableText-background { + filter: opacity(0.2); + } + } } - } - - &.secondary { - &:focus-within { - .editableText-background { - filter: opacity(0.2) !important; - } - } - - .editableText-background { - filter: opacity(0); - &.active { - filter: opacity(0.2) !important; - } + &.secondary { + &:focus-within { + .editableText-background { + filter: opacity(0.2) !important; + } + } + + .editableText-background { + filter: opacity(0); + + &.active { + filter: opacity(0.2) !important; + } + } + + &:hover { + .editableText-background { + filter: opacity(0.2); + } + } } - &:hover{ - .editableText-background { - filter: opacity(0.2) - } - } - } + &.tertiary { + &:hover { + box-shadow: global.$standard-shadow; + } - &.tertiary { - &:hover{ - box-shadow: $standard-shadow; + &:hover { + .editableText-background { + filter: brightness(0.8); + } + } } - &:hover{ - .editableText-background { - filter: brightness(0.8); - } + .editableText { + -webkit-appearance: none; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-size: inherit; + border: none; + outline: none; + margin: 0px !important; + padding: 0px !important; + box-shadow: none !important; + background: transparent; + color: inherit; + z-index: 1; + + &.center { + display: flex; + justify-content: center; + align-items: center; + } } - } - .editableText { - -webkit-appearance: none; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-size: inherit; - border: none; - outline: none; - margin: 0px !important; - padding: 0px !important; - box-shadow: none !important; - background: transparent; - color: inherit; - z-index: 1; - - &.center { - display: flex; - justify-content: center; - align-items: center; + .displayText { + cursor: text !important; + width: 100%; + height: 100%; + white-space: nowrap; + text-overflow: ellipsis; + display: flex; + align-items: center; + font-size: inherit; + color: inherit; + z-index: 1; + + &.center { + display: flex; + justify-content: center; + align-items: center; + } } - } - - .displayText { - cursor: text !important; - width: 100%; - height: 100%; - white-space: nowrap; - text-overflow: ellipsis; - display: flex; - align-items: center; - font-size: inherit; - color: inherit; - z-index: 1; - - &.center { - display: flex; - justify-content: center; - align-items: center; - } - } } - diff --git a/packages/components/src/components/FormInput/FormInput.scss b/packages/components/src/components/FormInput/FormInput.scss index db04ff8cf..2554cbd01 100644 --- a/packages/components/src/components/FormInput/FormInput.scss +++ b/packages/components/src/components/FormInput/FormInput.scss @@ -1,69 +1,69 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .formInput-container { - display: flex; - flex-direction: column; - width: 100%; - height: fit-content; - position: relative; - margin-top: 20px; - - .formInput { - font-family: inherit; + display: flex; + flex-direction: column; width: 100%; - border: 0; - border-bottom: 2px solid black; - outline: 0; - font-size: 1rem; - color: black; - padding: 7px 0; - background: transparent; - transition: border-color 0.2s; - - &::placeholder { - color: transparent; - } + height: fit-content; + position: relative; + margin-top: 20px; - &:focus { - ~ .formInput-label { - position: absolute; - transform: translate(0px, -13px); - display: block; - transition: 0.2s; + .formInput { + font-family: inherit; + width: 100%; + border: 0; + border-bottom: 2px solid black; + outline: 0; font-size: 1rem; - font-weight: 700; - } - padding-bottom: 6px; - font-weight: 700; - border-width: 3px; - border-image: linear-gradient(to right, black, white); - border-image-slice: 1; + color: black; + padding: 7px 0; + background: transparent; + transition: border-color 0.2s; + + &::placeholder { + color: transparent; + } + + &:focus { + ~ .formInput-label { + position: absolute; + transform: translate(0px, -13px); + display: block; + transition: 0.2s; + font-size: 1rem; + font-weight: 700; + } + padding-bottom: 6px; + font-weight: 700; + border-width: 3px; + border-image: linear-gradient(to right, black, white); + border-image-slice: 1; + } + + &:valid { + ~ .formInput-label { + position: absolute; + transform: translate(0px, -13px); + display: block; + transition: 0.2s; + font-size: 1rem; + } + } + + &:required, + &:invalid { + box-shadow: none; + } } - &:valid { - ~ .formInput-label { + .formInput-label { position: absolute; - transform: translate(0px, -13px); + top: 0; + transform: translate(0px, 8px); display: block; transition: 0.2s; font-size: 1rem; - } + color: gray; + pointer-events: none; } - - &:required, - &:invalid { - box-shadow: none; - } - } - - .formInput-label { - position: absolute; - top: 0; - transform: translate(0px, 8px); - display: block; - transition: 0.2s; - font-size: 1rem; - color: gray; - pointer-events: none; - } } diff --git a/packages/components/src/components/Group/Group.scss b/packages/components/src/components/Group/Group.scss index 885472a5d..7cd3dfd9e 100644 --- a/packages/components/src/components/Group/Group.scss +++ b/packages/components/src/components/Group/Group.scss @@ -1,16 +1,15 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .group-wrapper { - overflow: hidden; + overflow: hidden; - .group-container { - width: fit-content; - display: flex; - flex-flow: row wrap; - height: fit-content; - flex-flow: row; - justify-content: flex-start; - align-items: center; - } + .group-container { + width: fit-content; + display: flex; + flex-flow: row wrap; + height: fit-content; + flex-flow: row; + justify-content: flex-start; + align-items: center; + } } - diff --git a/packages/components/src/components/IconButton/IconButton.scss b/packages/components/src/components/IconButton/IconButton.scss index 9a0b53c0f..f899dc50f 100644 --- a/packages/components/src/components/IconButton/IconButton.scss +++ b/packages/components/src/components/IconButton/IconButton.scss @@ -1,121 +1,119 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .iconButton-container { - position: relative; - cursor: pointer; - overflow: hidden; - user-select: none; - display: flex; - justify-content: center; - align-items: center; - font-family: $default-font; - border-radius: $standard-border-radius; - white-space: nowrap; - transition: 0.4s; - border: solid 1px; - border-color: transparent; - pointer-events: all; - - - .iconButton-content { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: 100%; - width: 100%; - z-index: 1; - font-family: Verdana, sans-serif; - font-weight: 500; - } - - .icon { - z-index: 1; + position: relative; + cursor: pointer; + overflow: hidden; + user-select: none; display: flex; justify-content: center; align-items: center; - } - - .background { - width: 100%; - height: 100%; - z-index: 0; - position: absolute; + font-family: global.$default-font; + border-radius: global.$standard-border-radius; + white-space: nowrap; transition: 0.4s; - } + border: solid 1px; + border-color: transparent; + pointer-events: all; + + .iconButton-content { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + z-index: 1; + font-family: Verdana, sans-serif; + font-weight: 500; + } - &.inactive { - .background { - filter: opacity(0) !important; + .icon { + z-index: 1; + display: flex; + justify-content: center; + align-items: center; } - } - &.primary { .background { - filter: opacity(0); - - &.active { - filter: opacity(0.2) !important; - } + width: 100%; + height: 100%; + z-index: 0; + position: absolute; + transition: 0.4s; } - &:hover{ - .background { - filter: opacity(0.2) - } + &.inactive { + .background { + filter: opacity(0) !important; + } } - } + &.primary { + .background { + filter: opacity(0); - &.secondary { - .background { - filter: opacity(0); + &.active { + filter: opacity(0.2) !important; + } + } - &.active { - filter: opacity(0.2) !important; - } + &:hover { + .background { + filter: opacity(0.2); + } + } } - &:hover{ - .background { - filter: opacity(0.2) - } - } - } + &.secondary { + .background { + filter: opacity(0); + + &.active { + filter: opacity(0.2) !important; + } + } - &.tertiary { - &:hover{ - box-shadow: $standard-button-shadow; + &:hover { + .background { + filter: opacity(0.2); + } + } } - &:hover{ - .background { - filter: brightness(0.8); - } + &.tertiary { + &:hover { + box-shadow: global.$standard-button-shadow; + } + + &:hover { + .background { + filter: brightness(0.8); + } + } } - } - .color { - position: relative; - width: 70%; - height: 15%; - z-index: 3; - margin-top: 2px; - border-radius: 10px; - outline: solid 0.3px; - outline-offset: -0.3px; - } + .color { + position: relative; + width: 70%; + height: 15%; + z-index: 3; + margin-top: 2px; + border-radius: 10px; + outline: solid 0.3px; + outline-offset: -0.3px; + } - .iconButton-label { - position: relative; - z-index: 2; - max-width: 100%; - overflow: hidden; - white-space: normal; - display: flex; - text-align: center; - justify-content: center; - align-items: center; - font-size: $xsmall-fontSize; - } + .iconButton-label { + position: relative; + z-index: 2; + max-width: 100%; + overflow: hidden; + white-space: normal; + display: flex; + text-align: center; + justify-content: center; + align-items: center; + font-size: global.$xsmall-fontSize; + } } diff --git a/packages/components/src/components/ListBox/ListBox.scss b/packages/components/src/components/ListBox/ListBox.scss index dc449c943..dc2a44513 100644 --- a/packages/components/src/components/ListBox/ListBox.scss +++ b/packages/components/src/components/ListBox/ListBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .listBox-container { position: relative; @@ -13,4 +13,4 @@ max-width: 300px; padding: 5px; gap: 2px; -} \ No newline at end of file +} diff --git a/packages/components/src/components/ListItem/ListItem.scss b/packages/components/src/components/ListItem/ListItem.scss index 736078360..8d46605d0 100644 --- a/packages/components/src/components/ListItem/ListItem.scss +++ b/packages/components/src/components/ListItem/ListItem.scss @@ -1,78 +1,78 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .listItem-container { - position: relative; - width: 100%; - border-radius: $standard-border-radius; - display: flex; - justify-content: center; - align-items: flex-start; - flex-direction: column; - cursor: pointer; - font-family: Verdana, sans-serif; - overflow: hidden; - text-align: left; - - .listItem-background { - position: absolute; + position: relative; width: 100%; - height: 100%; - background: $medium-blue; - filter: opacity(0); - transition: 0.4s; - } - - .listItem-top { + border-radius: global.$standard-border-radius; display: flex; - height: 30px; - width: 100%; - justify-content: space-between; - align-items: center; - gap: 20px; + justify-content: center; + align-items: flex-start; + flex-direction: column; + cursor: pointer; + font-family: Verdana, sans-serif; + overflow: hidden; + text-align: left; - .content { - display: flex; - justify-content: flex-start; - align-items: center; - padding: $padding; - width: 100%; - height: 100%; - z-index: 1; - gap: 5px; - font-weight: 500; - - .text { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + .listItem-background { + position: absolute; width: 100%; - } + height: 100%; + background: global.$medium-blue; + filter: opacity(0); + transition: 0.4s; } - .shortcut { - grid-area: end; - padding: $padding; - display: flex; - justify-content: center; - align-items: center; - font-size: $xsmall-fontSize; - font-family: $default-font; - } + .listItem-top { + display: flex; + height: 30px; + width: 100%; + justify-content: space-between; + align-items: center; + gap: 20px; - .caret { - grid-area: end; - display: flex; - justify-content: flex-end; - align-items: center; - justify-self: center; + .content { + display: flex; + justify-content: flex-start; + align-items: center; + padding: global.$padding; + width: 100%; + height: 100%; + z-index: 1; + gap: 5px; + font-weight: 500; + + .text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } + } + + .shortcut { + grid-area: end; + padding: global.$padding; + display: flex; + justify-content: center; + align-items: center; + font-size: global.$xsmall-fontSize; + font-family: global.$default-font; + } + + .caret { + grid-area: end; + display: flex; + justify-content: flex-end; + align-items: center; + justify-self: center; + } } - } - .listItem-description { - font-size: $small-fontSize; - display: flex; - padding: 0px 5px 10px 5px; - justify-content: flex-start; - width: calc(100% - 10px); - } + .listItem-description { + font-size: global.$small-fontSize; + display: flex; + padding: 0px 5px 10px 5px; + justify-content: flex-start; + width: calc(100% - 10px); + } } diff --git a/packages/components/src/components/Modal/Modal.scss b/packages/components/src/components/Modal/Modal.scss index c0667ed26..a5698432d 100644 --- a/packages/components/src/components/Modal/Modal.scss +++ b/packages/components/src/components/Modal/Modal.scss @@ -1,46 +1,46 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .modal-container { - top: 0px; - left: 0px; - width: 100vw; - height: 100vh; - position: fixed; - display: flex; - justify-content: center; - align-items: center; - z-index: 100; - - .modal-popup { - position: relative; + top: 0px; + left: 0px; + width: 100vw; + height: 100vh; + position: fixed; display: flex; - flex-direction: column; - align-items: left; - z-index: 10; - width: 400px; - height: fit-content; - padding: 20px; - border-radius: $standard-border-radius; - font-weight: bold; - font-size: 1.5rem; + justify-content: center; + align-items: center; + z-index: 100; + + .modal-popup { + position: relative; + display: flex; + flex-direction: column; + align-items: left; + z-index: 10; + width: 400px; + height: fit-content; + padding: 20px; + border-radius: global.$standard-border-radius; + font-weight: bold; + font-size: 1.5rem; - .modal-closeButton { - top: -15px; - right: -15px; - position: absolute; - width: fit-content; - height: fit-content; + .modal-closeButton { + top: -15px; + right: -15px; + position: absolute; + width: fit-content; + height: fit-content; + } } - } } .modal-background { - z-index: 9; - position: absolute; - top: -10vh; - left: -10vw; - backdrop-filter: blur(15px); - width: 200vw; - height: 200vh; - background: $modal-background; + z-index: 9; + position: absolute; + top: -10vh; + left: -10vw; + backdrop-filter: blur(15px); + width: 200vw; + height: 200vh; + background: global.$modal-background; } diff --git a/packages/components/src/components/MultiToggle/MultiToggle.scss b/packages/components/src/components/MultiToggle/MultiToggle.scss index 2522549e9..854abdca0 100644 --- a/packages/components/src/components/MultiToggle/MultiToggle.scss +++ b/packages/components/src/components/MultiToggle/MultiToggle.scss @@ -1,5 +1 @@ -@import '../../global/globalCssVariables.scss'; - -.multiToggle-container { - -} \ No newline at end of file +@use '../../global/globalCssVariables.scss' as global; diff --git a/packages/components/src/components/NumberDropdown/NumberDropdown.scss b/packages/components/src/components/NumberDropdown/NumberDropdown.scss index 4ed5855d9..b3111623b 100644 --- a/packages/components/src/components/NumberDropdown/NumberDropdown.scss +++ b/packages/components/src/components/NumberDropdown/NumberDropdown.scss @@ -1,7 +1,4 @@ -@import '../../global/globalCssVariables.scss'; - -.numberDropdown-container { -} +@use '../../global/globalCssVariables.scss' as global; .form-wrapper { .iconButton-label { @@ -14,6 +11,6 @@ text-align: center; justify-content: center; align-items: center; - font-size: $xsmall-fontSize !important; + font-size: global.$xsmall-fontSize !important; } } diff --git a/packages/components/src/components/NumberInput/NumberInput.scss b/packages/components/src/components/NumberInput/NumberInput.scss index 2a562d395..887d64857 100644 --- a/packages/components/src/components/NumberInput/NumberInput.scss +++ b/packages/components/src/components/NumberInput/NumberInput.scss @@ -1,5 +1,5 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .numberInput-container { width: 100%; -} \ No newline at end of file +} diff --git a/packages/components/src/components/Popup/Popup.scss b/packages/components/src/components/Popup/Popup.scss index 39dd2c947..3087293f1 100644 --- a/packages/components/src/components/Popup/Popup.scss +++ b/packages/components/src/components/Popup/Popup.scss @@ -1,30 +1,30 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .popup-wrapper { - width: fit-content; - - &.fillWidth { - width: 100%; - } - - .trigger-container { width: fit-content; - height: fit-content; &.fillWidth { - width: 100%; + width: 100%; + } + + .trigger-container { + width: fit-content; + height: fit-content; + + &.fillWidth { + width: 100%; + } } - } } .popup-container { - display: flex; - height: fit-content; - min-width: fit-content; - width: fit-content; - position: relative; - border: solid 1px $black; - border-radius: $standard-border-radius; - overflow: hidden; - background: $white; + display: flex; + height: fit-content; + min-width: fit-content; + width: fit-content; + position: relative; + border: solid 1px global.$black; + border-radius: global.$standard-border-radius; + overflow: hidden; + background: global.$white; } diff --git a/packages/components/src/components/Slider/Slider.scss b/packages/components/src/components/Slider/Slider.scss index 9a9fc6172..a653f024f 100644 --- a/packages/components/src/components/Slider/Slider.scss +++ b/packages/components/src/components/Slider/Slider.scss @@ -1,168 +1,163 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .slider-container { - display: flex; - position: relative; - justify-content: center; - align-items: center; - min-width: 200px; - width: 100%; - height: 100%; - font-family: $default-font; - - .selected-range { - width: 100%; - background: $medium-blue; - } - - .range { - position: absolute; - background: $light-gray; - } - - .box-minmax{ - width: 100%; display: flex; - justify-content: space-between; - font-size: 20px; - color: $medium-blue; - position: absolute; - top: 110%; - } - .range-slider { - margin: 0px; - position: absolute; + position: relative; + justify-content: center; + align-items: center; + min-width: 200px; width: 100%; height: 100%; - top: 0px; - left: 0px; - - .rs-label-container { - display: flex; - position: absolute; - justify-content: center; - align-items: center; - overflow: visible; - border-radius: $standard-border-radius; - z-index: 45; - pointer-events: none; - - .rs-label { - display: flex; - font-size: smaller; - white-space: nowrap; - border-radius: 100%; - text-align: center; - text-wrap: wrap; - word-break: break-all; - justify-content: center; - align-items: center; - font-family: $default-font; - user-select: none; - pointer-events: none; - top: 0px; - width: fit-content; - border-radius: $standard-border-radius; - z-index: 40; - } - - } - - .rs-range { - width: 100%; - position: relative; - background: transparent; - pointer-events: none; - -webkit-appearance: none; - margin: 0px; - z-index: 20; - - &:focus { - outline: none; - } - - &::-webkit-slider-runnable-track { - width: 100%; - background: none; - cursor: pointer; - box-shadow: none; - -webkit-appearance: none; - pointer-events: none; - } - &::-moz-range-track { - width: 100%; - cursor: pointer; - box-shadow: none; - -webkit-appearance: none; - pointer-events: none; - } - - &::-webkit-slider-thumb { - cursor: ew-resize; - -webkit-appearance: none; - pointer-events: auto; - } - &::-moz-range-thumb { - cursor: pointer; - -webkit-appearance: none; - pointer-events: auto; - } - - &::-moz-focus-outer { - border: 0; - } - - &.xsmall { - &::-webkit-slider-runnable-track { - height: $xsmall; - } + font-family: global.$default-font; - &::-webkit-slider-thumb { - height: $xsmall; - width: $xsmall; - border-radius: $xsmall; - } + .selected-range { + width: 100%; + background: global.$medium-blue; } - &.small { - &::-webkit-slider-runnable-track { - height: $small; - } - - &::-webkit-slider-thumb { - height: $small; - width: $small; - border-radius: $small; - } + .range { + position: absolute; + background: global.$light-gray; } - &.medium { - &::-webkit-slider-runnable-track { - height: $medium; - } - - &::-webkit-slider-thumb { - height: $medium; - width: $medium; - border-radius: $medium; - } + .box-minmax { + width: 100%; + display: flex; + justify-content: space-between; + font-size: 20px; + color: global.$medium-blue; + position: absolute; + top: 110%; } - - &.large { - &::-webkit-slider-runnable-track { - height: $large; - } - - &::-webkit-slider-thumb { - height: $large; - width: $large; - border-radius: $large; - } + .range-slider { + margin: 0px; + position: absolute; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + + .rs-label-container { + display: flex; + position: absolute; + justify-content: center; + align-items: center; + overflow: visible; + border-radius: global.$standard-border-radius; + z-index: 45; + pointer-events: none; + + .rs-label { + display: flex; + font-size: smaller; + white-space: nowrap; + border-radius: 100%; + text-align: center; + text-wrap: wrap; + word-break: break-all; + justify-content: center; + align-items: center; + font-family: global.$default-font; + user-select: none; + pointer-events: none; + top: 0px; + width: fit-content; + border-radius: global.$standard-border-radius; + z-index: 40; + } + } + + .rs-range { + width: 100%; + position: relative; + background: transparent; + pointer-events: none; + -webkit-appearance: none; + margin: 0px; + z-index: 20; + + &:focus { + outline: none; + } + + &::-webkit-slider-runnable-track { + width: 100%; + background: none; + cursor: pointer; + box-shadow: none; + -webkit-appearance: none; + pointer-events: none; + } + &::-moz-range-track { + width: 100%; + cursor: pointer; + box-shadow: none; + -webkit-appearance: none; + pointer-events: none; + } + + &::-webkit-slider-thumb { + cursor: ew-resize; + -webkit-appearance: none; + pointer-events: auto; + } + &::-moz-range-thumb { + cursor: pointer; + -webkit-appearance: none; + pointer-events: auto; + } + + &::-moz-focus-outer { + border: 0; + } + + &.xsmall { + &::-webkit-slider-runnable-track { + height: global.$xsmall; + } + + &::-webkit-slider-thumb { + height: global.$xsmall; + width: global.$xsmall; + border-radius: global.$xsmall; + } + } + + &.small { + &::-webkit-slider-runnable-track { + height: global.$small; + } + + &::-webkit-slider-thumb { + height: global.$small; + width: global.$small; + border-radius: global.$small; + } + } + + &.medium { + &::-webkit-slider-runnable-track { + height: global.$medium; + } + + &::-webkit-slider-thumb { + height: global.$medium; + width: global.$medium; + border-radius: global.$medium; + } + } + + &.large { + &::-webkit-slider-runnable-track { + height: global.$large; + } + + &::-webkit-slider-thumb { + height: global.$large; + width: global.$large; + border-radius: global.$large; + } + } + } } - } - } - } - - - diff --git a/packages/components/src/components/Slider/Slider.tsx b/packages/components/src/components/Slider/Slider.tsx index 3ca51efed..f6f53799c 100644 --- a/packages/components/src/components/Slider/Slider.tsx +++ b/packages/components/src/components/Slider/Slider.tsx @@ -1,178 +1,188 @@ -import React, { useEffect, useRef, useState } from 'react' -import { Colors, getFontSize, getHeight, IGlobalProps, Size , getFormLabelSize, isDark, INumberProps } from '../../global' -import './Slider.scss' +import React, { useState } from 'react'; +import { Colors, getFontSize, getHeight, Size, getFormLabelSize, isDark, INumberProps } from '../../global'; +import './Slider.scss'; export interface ISliderProps extends INumberProps { - multithumb: boolean - autorangeMinVal?: number // minimimum value that min can have when autoranging - autorangeMinSize?: number // minimum difference between min and max when autoranging - autorange?: number // automatically adjust min/max to be +/- autorange/2 around the current value when the thumb is 15% from the min/max, or when the multithumbs are within 20% of the range and the range is bigger than autorange - endNumber?: number - setEndNumber?: (newVal: number) => void - setFinalNumber?: (newVal: number) => void - setFinalEndNumber?: (newVal: number) => void - decimals?: number; - step?: number - minDiff?: number + multithumb: boolean; + autorangeMinVal?: number; // minimimum value that min can have when autoranging + autorangeMinSize?: number; // minimum difference between min and max when autoranging + autorange?: number; // automatically adjust min/max to be +/- autorange/2 around the current value when the thumb is 15% from the min/max, or when the multithumbs are within 20% of the range and the range is bigger than autorange + endNumber?: number; + setEndNumber?: (newVal: number) => void; + setFinalNumber?: (newVal: number) => void; + setFinalEndNumber?: (newVal: number) => void; + decimals?: number; + step?: number; + minDiff?: number; } -let lastVal = 0; // bcz: WHY do I have to do this?? the pointerdown event locks in the value of 'valLoc' when it's created so need some other way to get the current value to that old handler... +let lastVal = 0; // bcz: WHY do I have to do this?? the pointerdown event locks in the value of 'valLoc' when it's created so need some other way to get the current value to that old handler... let lastEndVal = 0; export const Slider = (props: ISliderProps) => { - const [width, setWidth] = useState(100); - const [valLoc, setNumberLoc] = useState(props.number??(props.min + (props.max-props.min)/2)); - const [endNumberLoc, setEndNumberLoc] = useState(props.endNumber??(props.min + 2*(props.max-props.min)/3)); - const [min, setMin] = useState(props.min); - const [max, setMax] = useState(props.max); - const { - formLabel, - formLabelPlacement, - multithumb, - autorange, - autorangeMinVal, - autorangeMinSize, - decimals, - step = 1, - number = valLoc, - endNumber = endNumberLoc, - minDiff = (max-min)/20, - size = Size.SMALL, - height, - unit, - onPointerDown, - setNumber, - setEndNumber, - setFinalNumber, - setFinalEndNumber, - color = Colors.MEDIUM_BLUE, - fillWidth - } = props + const [width, setWidth] = useState(100); + const [valLoc, setNumberLoc] = useState(props.number ?? props.min + (props.max - props.min) / 2); + const [endNumberLoc, setEndNumberLoc] = useState(props.endNumber ?? props.min + (2 * (props.max - props.min)) / 3); + const [min, setMin] = useState(props.min); + const [max, setMax] = useState(props.max); + const { + formLabel, + formLabelPlacement, + multithumb, + autorange, + autorangeMinVal, + autorangeMinSize, + decimals, + step = 1, + number = valLoc, + endNumber = endNumberLoc, + minDiff = (max - min) / 20, + size = Size.SMALL, + height, + unit, + onPointerDown, + setNumber, + setEndNumber, + setFinalNumber, + setFinalEndNumber, + color = Colors.MEDIUM_BLUE, + fillWidth, + } = props; - const toDecimal = (num:number) => decimals !== undefined ? Math.round(num*Math.pow(10,decimals))/Math.pow(10,decimals): num; + const toDecimal = (num: number) => (decimals !== undefined ? Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals) : num); - const getLeftPos = (locVal: number) => { - const dragger = getHeight(height,size) - return (((locVal-min)/ (max-min)) * (width-dragger)) - } + const getLeftPos = (locVal: number) => { + const dragger = getHeight(+(height || 0), size); + return ((locVal - min) / (max - min)) * (width - dragger); + }; - const getValueLabel = (locVal: number): JSX.Element => { - return (
- - {toDecimal(locVal)} - -
) - } - const checkAutorange = () => { - if (autorange) { - const minval = multithumb ? Math.min(lastVal, lastEndVal) : lastVal; - const maxval = multithumb ? Math.max(lastVal, lastEndVal) : lastVal; - const autosize = Math.max(autorangeMinSize??0,(autorange ?? (maxval-minval)))/2; - if ((Math.abs((minval - min)/(max-min)) < .15) || (Math.abs((max - maxval)/(max-min)) < .15) || - (multithumb && maxval - minval < (max-min)/5 && autosize < max-min) - ) { - const newminval = autorangeMinVal !== undefined && minval-autosize < autorangeMinVal? autorangeMinVal : minval-autosize; - setMin(newminval) - setMax(newminval !== minval ? Math.max(maxval + autosize, newminval +autosize): maxval+autosize ) - } - } - } + const getValueLabel = (locVal: number): JSX.Element => { + return ( +
+ {toDecimal(locVal)} +
+ ); + }; + const checkAutorange = () => { + if (autorange) { + const minval = multithumb ? Math.min(lastVal, lastEndVal) : lastVal; + const maxval = multithumb ? Math.max(lastVal, lastEndVal) : lastVal; + const autosize = Math.max(autorangeMinSize ?? 0, autorange ?? maxval - minval) / 2; + if (Math.abs((minval - min) / (max - min)) < 0.15 || Math.abs((max - maxval) / (max - min)) < 0.15 || (multithumb && maxval - minval < (max - min) / 5 && autosize < max - min)) { + const newminval = autorangeMinVal !== undefined && minval - autosize < autorangeMinVal ? autorangeMinVal : minval - autosize; + setMin(newminval); + setMax(newminval !== minval ? Math.max(maxval + autosize, newminval + autosize) : maxval + autosize); + } + } + }; - const valSlider = (which: string, val:number, onchange: (val:number) => void, setFinal: () => void) => { - const valPointerup = (e:PointerEvent) => { - document.removeEventListener('pointerup', valPointerup, true) - setFinal(); - checkAutorange(); - } - return (
- {getValueLabel(val)} - document.addEventListener('pointerup', valPointerup, true)} - onChange={e => { - onchange(+e.target.value); - e.stopPropagation(); - }} - /> -
); - } - const onchange = (val:number) => { - if (autorangeMinVal && val < autorangeMinVal) val = autorangeMinVal; - setNumber?.(lastVal = Math.min(multithumb ? endNumber - (minDiff??0):Number.MAX_VALUE, val)) - setNumberLoc(lastVal = Math.min(multithumb ? endNumber - (minDiff??0):Number.MAX_VALUE, val)) - } - const onendchange = (val:number) => { - setEndNumber?.(lastEndVal = Math.max(number + (minDiff??0), val)) - setEndNumberLoc(lastEndVal = Math.max(number + (minDiff??0), val)) - } - const Slider:(JSX.Element|null)[] = [ - !multithumb ? (null) : valSlider("end", endNumberLoc,onendchange, () => setFinalEndNumber?.(lastEndVal)), - valSlider("start", valLoc, onchange, () => setFinalNumber?.(lastVal)) - ]; + const valSlider = (which: string, val: number, onchange: (val: number) => void, setFinal: () => void) => { + const valPointerup = () => { + document.removeEventListener('pointerup', valPointerup, true); + setFinal(); + checkAutorange(); + }; + return ( +
+ {getValueLabel(val)} + document.addEventListener('pointerup', valPointerup, true)} + onChange={e => { + onchange(+e.target.value); + e.stopPropagation(); + }} + /> +
+ ); + }; + const onchange = (val: number) => { + // eslint-disable-next-line no-param-reassign + if (autorangeMinVal && val < autorangeMinVal) val = autorangeMinVal; + setNumber?.((lastVal = Math.min(multithumb ? endNumber - (minDiff ?? 0) : Number.MAX_VALUE, val))); + setNumberLoc((lastVal = Math.min(multithumb ? endNumber - (minDiff ?? 0) : Number.MAX_VALUE, val))); + }; + const onendchange = (val: number) => { + setEndNumber?.((lastEndVal = Math.max(number + (minDiff ?? 0), val))); + setEndNumberLoc((lastEndVal = Math.max(number + (minDiff ?? 0), val))); + }; + const Slider: (JSX.Element | null)[] = [!multithumb ? null : valSlider('end', endNumberLoc, onendchange, () => setFinalEndNumber?.(lastEndVal)), valSlider('start', valLoc, onchange, () => setFinalNumber?.(lastVal))]; - const slider: JSX.Element = ( -
{ - lastVal = valLoc; - lastEndVal = endNumberLoc; - }} - style={{ - padding: `5px 0px ${getHeight(height, size)}px 0px`, - width: fillWidth ? '100%' : 'fit-content' - }}> -
{ - r && new ResizeObserver(() => setWidth(+(r?.clientWidth??100))).observe(r); - setWidth(+(r?.clientWidth??100)); - }} - style={{height: getHeight(height, size)}} - onPointerDown={onPointerDown} - > - {Slider} -
-
-
- {toDecimal(min)}{unit} - {toDecimal(max)}{unit} + const slider: JSX.Element = ( +
{ + lastVal = valLoc; + lastEndVal = endNumberLoc; + }} + style={{ + padding: `5px 0px ${getHeight(+(height || 0), size)}px 0px`, + width: fillWidth ? '100%' : 'fit-content', + }}> +
{ + r && new ResizeObserver(() => setWidth(+(r?.clientWidth ?? 100))).observe(r); + setWidth(+(r?.clientWidth ?? 100)); + }} + style={{ height: getHeight(+(height || 0), size) }} + onPointerDown={onPointerDown}> + {Slider} +
+
+
+ + {toDecimal(min)} + {unit} + + + {toDecimal(max)} + {unit} + +
+
-
-
- ) - - return ( - formLabel ? -
-
{formLabel}
- {slider} -
- : - slider -) -} + ); + return formLabel ? ( +
+
+ {formLabel} +
+ {slider} +
+ ) : ( + slider + ); +}; diff --git a/packages/components/src/components/Template/Template.scss b/packages/components/src/components/Template/Template.scss index c91147200..854abdca0 100644 --- a/packages/components/src/components/Template/Template.scss +++ b/packages/components/src/components/Template/Template.scss @@ -1,5 +1 @@ -@import '../../global/globalCssVariables.scss'; - -.template-container { - -} \ No newline at end of file +@use '../../global/globalCssVariables.scss' as global; diff --git a/packages/components/src/components/Toggle/Toggle.scss b/packages/components/src/components/Toggle/Toggle.scss index b2faa8d99..d65cb8e23 100644 --- a/packages/components/src/components/Toggle/Toggle.scss +++ b/packages/components/src/components/Toggle/Toggle.scss @@ -1,77 +1,77 @@ -@import '../../global/globalCssVariables.scss'; +@use '../../global/globalCssVariables.scss' as global; .toggle-label { - position: relative; - bottom: 0; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - font-size: $xsmall-fontSize; + position: relative; + bottom: 0; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + font-size: global.$xsmall-fontSize; } .toggle-container { - position: relative; - width: fit-content; - cursor: pointer; - overflow: hidden; - user-select: none; - display: flex; - justify-content: center; - align-items: center; - gap: 5px; - font-family: $default-font; - font-size: $medium-fontSize; - border-radius: 100px; - white-space: nowrap; - transition: 0.4s ease; - border: solid 1px; - border-color: $medium-blue; + position: relative; + width: fit-content; + cursor: pointer; + overflow: hidden; + user-select: none; + display: flex; + justify-content: center; + align-items: center; + gap: 5px; + font-family: global.$default-font; + font-size: global.$medium-fontSize; + border-radius: 100px; + white-space: nowrap; + transition: 0.4s ease; + border: solid 1px; + border-color: global.$medium-blue; - &:hover { - .toggle-background { - filter: opacity(0.2); + &:hover { + .toggle-background { + filter: opacity(0.2); + } } - } - &.switch { - &:hover { - .toggle-background { - filter: opacity(0); - } + &.switch { + &:hover { + .toggle-background { + filter: opacity(0); + } + } } - } - .toggle-content { - position: absolute; - display: flex; - align-items: center; - width: 100%; - height: 100%; - z-index: 1; - text-transform: uppercase; - font-family: Verdana, sans-serif; - font-weight: 500; - transition: 0.4s; + .toggle-content { + position: absolute; + display: flex; + align-items: center; + width: 100%; + height: 100%; + z-index: 1; + text-transform: uppercase; + font-family: Verdana, sans-serif; + font-weight: 500; + transition: 0.4s; - .toggle-switch { - background: $medium-blue; - transition: 0.4s; - border-radius: 100px; + .toggle-switch { + background: global.$medium-blue; + transition: 0.4s; + border-radius: 100px; + } } - } - .toggle-background { - width: 100%; - height: 100%; - z-index: 0; - position: absolute; - background: $medium-blue; - transition: 0.4s ease; - filter: opacity(0); + .toggle-background { + width: 100%; + height: 100%; + z-index: 0; + position: absolute; + background: global.$medium-blue; + transition: 0.4s ease; + filter: opacity(0); - &.active { - filter: opacity(0.4) !important; + &.active { + filter: opacity(0.4) !important; + } } - } } diff --git a/packages/components/src/global/globalCssVariables.scss b/packages/components/src/global/globalCssVariables.scss index 1ac2ef45c..ebc44106d 100644 --- a/packages/components/src/global/globalCssVariables.scss +++ b/packages/components/src/global/globalCssVariables.scss @@ -75,8 +75,10 @@ $standard-border-radius: 5px; // shadow $standard-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); -$standard-button-shadow: rgb(0 0 0 / 20%) 0px 2px 4px -1px, - rgb(0 0 0 / 14%) 0px 4px 5px 0px, rgb(0 0 0 / 12%) 0px 1px 10px 0px; +$standard-button-shadow: + rgb(0 0 0 / 20%) 0px 2px 4px -1px, + rgb(0 0 0 / 14%) 0px 4px 5px 0px, + rgb(0 0 0 / 12%) 0px 1px 10px 0px; $dashboardselector-height: 32px; $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc @@ -91,70 +93,68 @@ $LEFT_MENU_WIDTH: 60px; $TREE_BULLET_WIDTH: 20px; :export { - contextMenuZindex: $contextMenu-zindex; - SCHEMA_DIVIDER_WIDTH: $SCHEMA_DIVIDER_WIDTH; - COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH; - MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; - MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; - SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; - ANTIMODEMENU_HEIGHT: $antimodemenu-height; - DASHBOARD_SELECTOR_HEIGHT: $dashboardselector-height; - DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; - LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH; - TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; + contextMenuZindex: $contextMenu-zindex; + SCHEMA_DIVIDER_WIDTH: $SCHEMA_DIVIDER_WIDTH; + COLLECTION_BORDER_WIDTH: $COLLECTION_BORDER_WIDTH; + MINIMIZED_ICON_SIZE: $MINIMIZED_ICON_SIZE; + MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; + SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; + ANTIMODEMENU_HEIGHT: $antimodemenu-height; + DASHBOARD_SELECTOR_HEIGHT: $dashboardselector-height; + DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; + LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH; + TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; } .form-wrapper { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - gap: 0px; - padding-bottom: 5px; - - - .formLabel { display: flex; - font-family: $default-font; - text-transform: uppercase; - opacity: 0.8; - min-width: 'fit-content' - } - - &.left { - flex-direction: row; - align-items: center; - gap: 3px; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 0px; + padding-bottom: 5px; .formLabel { - text-align: left; + display: flex; + font-family: $default-font; + text-transform: uppercase; + opacity: 0.8; + min-width: 'fit-content'; } - } - &.right { - flex-direction: row-reverse; - justify-content: flex-end; - align-items: center; - gap: 3px; + &.left { + flex-direction: row; + align-items: center; + gap: 3px; - .formLabel { - text-align: right; + .formLabel { + text-align: left; + } } - } - &.top { - flex-direction: column; - gap: 1px; - } + &.right { + flex-direction: row-reverse; + justify-content: flex-end; + align-items: center; + gap: 3px; - &.top-start { - flex-direction: column; - align-items: flex-start; - } + .formLabel { + text-align: right; + } + } - &.top-end { - flex-direction: column; - align-items: flex-end; - } -} + &.top { + flex-direction: column; + gap: 1px; + } + &.top-start { + flex-direction: column; + align-items: flex-start; + } + + &.top-end { + flex-direction: column; + align-items: flex-end; + } +} diff --git a/src/client/util/CaptureManager.scss b/src/client/util/CaptureManager.scss index 8679a0101..e7cbb4287 100644 --- a/src/client/util/CaptureManager.scss +++ b/src/client/util/CaptureManager.scss @@ -1,5 +1,3 @@ -@import '../views/global/globalCssVariables.module'; - .capture-interface { //background-color: whitesmoke !important; width: 450px; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d2d7cabd2..60acd5b21 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -445,7 +445,6 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a view slide", title: "View Slide", icon: "address-card", dragFactory: doc.emptyViewSlide as Doc, clickFactory: DocCast(doc.emptyViewSlide), openFactoryLocation: OpenWhere.overlay,funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize", dragFactory: doc.emptyHeader as Doc, clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true, funcs: { hidden: "IsNoviceMode()"} }, { toolTip: "Toggle a Calculator REPL", title: "replviewer", icon: "calculator", clickFactory: '' as unknown as Doc, openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script - // { toolTip: "Toggle an UndoStack", title: "undostacker", icon: "calculator", clickFactory: "" as any, openFactoryLocation: OpenWhere.overlay}, ].map(tuple => ( { openFactoryLocation: OpenWhere.addRight, scripts: { onClick: 'openDoc(copyDragFactory(this.clickFactory,this.openFactoryAsDelegate), this.openFactoryLocation)', @@ -674,12 +673,13 @@ pie title Minerals in my tap water CurrentUserUtils.createToolButton(opts), scripts, funcs); const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet - { scripts: { onClick: "undo()"}, opts: { title: "Undo", icon: "undo-alt", toolTip: "Undo ⌘Z" }}, - { scripts: { onClick: "redo()"}, opts: { title: "Redo", icon: "redo-alt", toolTip: "Redo ⌘⇧Z" }}, - { scripts: { }, opts: { title: "undoStack", layout: "", toolTip: "Undo/Redo Stack"}}, // note: layout fields are hacks -- they don't actually run through the JSX parser (yet) - { scripts: { }, opts: { title: "linker", layout: "", toolTip: "link started"}}, - { scripts: { }, opts: { title: "currently playing", layout: "", toolTip: "currently playing media"}}, - { scripts: { }, opts: { title: "Branching", layout: "", toolTip: "Branch, baby!"}} + { scripts: { onClick: "undo()"}, opts: { title: "Undo", icon: "undo-alt", toolTip: "Undo ⌘Z" }}, + { scripts: { onClick: "redo()"}, opts: { title: "Redo", icon: "redo-alt", toolTip: "Redo ⌘⇧Z" }}, + { scripts: { }, opts: { title: "undoStack", layout: "", toolTip: "Undo/Redo Stack"}}, // note: layout fields are hacks -- they don't actually run through the JSX parser (yet) + { scripts: { }, opts: { title: "linker", layout: "", toolTip: "link started"}}, + { scripts: { }, opts: { title: "currently playing", layout: "", toolTip: "currently playing media"}}, + { scripts: { onClick: "hideUI()"},opts: { title: "Toggle UI", icon: "portrait", toolTip: "Toggle visibility of UI buttons"}}, + { scripts: { }, opts: { title: "Branching", layout: "", toolTip: "Branch, baby!"}} ]; const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts)); const dockBtnsReqdOpts:DocumentOptions = { diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index dbfc48c63..f81f17589 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -1,5 +1,3 @@ -@import '../views/global/globalCssVariables.module'; - .settings-interface { //background-color: whitesmoke !important; width: 450px; diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 9d8a41844..3bbc297b8 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -16,6 +16,7 @@ export class SnappingManager { @observable _shiftKey = false; @observable _ctrlKey = false; @observable _metaKey = false; + @observable _hideUI = false; @observable _showPresPaths = false; @observable _isLinkFollowing = false; @observable _isDragging: boolean = false; @@ -53,6 +54,7 @@ export class SnappingManager { public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore public static get MetaKey() { return this.Instance._metaKey; } // prettier-ignore + public static get HideUI() { return this.Instance._hideUI; } // prettier-ignore public static get ShowPresPaths() { return this.Instance._showPresPaths; } // prettier-ignore public static get IsLinkFollowing(){ return this.Instance._isLinkFollowing; } // prettier-ignore public static get IsDragging() { return this.Instance._isDragging; } // prettier-ignore @@ -73,6 +75,7 @@ export class SnappingManager { public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore public static SetCtrlKey = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore public static SetMetaKey = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore + public static SetHideUI = (vis: boolean) => runInAction(() => {this.Instance._hideUI = vis}); // prettier-ignore public static SetShowPresPaths = (paths:boolean) => runInAction(() => {this.Instance._showPresPaths = paths}); // prettier-ignore public static SetIsLinkFollowing= (follow:boolean)=> runInAction(() => {this.Instance._isLinkFollowing = follow}); // prettier-ignore public static SetIsDragging = (drag: boolean) => runInAction(() => {this.Instance._isDragging = drag}); // prettier-ignore diff --git a/src/client/util/reportManager/ReportManager.scss b/src/client/util/reportManager/ReportManager.scss index fd343ac8e..806741c22 100644 --- a/src/client/util/reportManager/ReportManager.scss +++ b/src/client/util/reportManager/ReportManager.scss @@ -1,4 +1,4 @@ -@import '../../views/global/globalCssVariables.module'; +@use '../../views/global/globalCssVariables.module' as global; // header @@ -97,7 +97,7 @@ background: transparent; // &:hover { - // // border-bottom-color: $text-gray; + // // border-bottom-color: global.$text-gray; // } // &:focus { // // border-bottom-color: #4476f7; diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index 2ebf673fe..48fa86276 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -1,11 +1,11 @@ -@import './global/globalCssVariables.module'; +@use './global/globalCssVariables.module' as global; .antimodeMenu-cont { position: absolute; z-index: 10001; - height: $antimodemenu-height; + height: global.$antimodemenu-height; width: fit-content; - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; overflow: hidden; // box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); // border-radius: 0px 6px 6px 6px; diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 88e147a03..d22c4d096 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,9 +1,9 @@ -@import 'global/globalCssVariables.module.scss'; +@use 'global/globalCssVariables.module.scss' as global; .contextMenu-cont { position: absolute; display: flex; - z-index: $contextMenu-zindex; + z-index: global.$contextMenu-zindex; box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%); flex-direction: column; background: whitesmoke; @@ -109,7 +109,7 @@ .contextMenu-item:hover { border-width: 0.11px; border-style: none; - border-color: $medium-gray; // rgb(187, 186, 186); + border-color: global.$medium-gray; // rgb(187, 186, 186); border-bottom-style: solid; border-top-style: solid; @@ -139,7 +139,7 @@ transition: all 0.1s; border-width: 0.11px; border-style: none; - border-color: $medium-gray; // rgb(187, 186, 186); + border-color: global.$medium-gray; // rgb(187, 186, 186); // padding: 10px 0px 10px 0px; white-space: nowrap; font-size: 13px; @@ -184,7 +184,7 @@ .top-bar { height: 20px; width: 100%; - display: flex; + display: flex; .close-menu { margin-top: 0; @@ -200,7 +200,7 @@ } } - .bottom-box{ + .bottom-box { display: flex; flex-direction: row; justify-content: center; @@ -209,11 +209,11 @@ height: 100%; width: 100%; - .width-selector{ + .width-selector { width: 100px; } - .max-min-selector{ + .max-min-selector { height: 15px; width: 30px; } diff --git a/src/client/views/DashboardView.scss b/src/client/views/DashboardView.scss index 25feca7bf..daa711bc4 100644 --- a/src/client/views/DashboardView.scss +++ b/src/client/views/DashboardView.scss @@ -1,4 +1,4 @@ -@import './global/globalCssVariables.module'; +@use './global/globalCssVariables.module' as global; $dashboard-left-menu-width: 250px; $dashboard-view-padding: 20px; @@ -61,9 +61,9 @@ $dashboard-container-width: 250px; font-size: 120px; font-weight: 100; text-align: center; - border: solid 2px $light-gray; + border: solid 2px global.$light-gray; cursor: pointer; - color: $light-gray; + color: global.$light-gray; display: flex; display: flex; justify-content: center; @@ -71,8 +71,8 @@ $dashboard-container-width: 250px; position: relative; &:hover { - color: $light-blue; - border: solid 2px $light-blue; + color: global.$light-blue; + border: solid 2px global.$light-blue; } .background { @@ -91,14 +91,14 @@ $dashboard-container-width: 250px; cursor: pointer; width: $dashboard-container-width; height: $dashboard-container-height; - outline: solid 2px $light-gray; + outline: solid 2px global.$light-gray; outline-offset: -2px; display: flex; flex-direction: column; overflow: hidden; &:hover { - outline: solid 2px $light-blue; + outline: solid 2px global.$light-blue; } .title { @@ -144,7 +144,7 @@ $dashboard-container-width: 250px; } .new-dashboard { - color: $dark-gray; + color: global.$dark-gray; padding: 10px; display: flex; width: 100%; diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index ede277aae..f19fecfa6 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables.module'; +@use 'global/globalCssVariables.module' as global; $linkGap: 3px; @@ -7,13 +7,13 @@ $linkGap: 3px; } .documentButtonBar-linkButton-empty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } .documentButtonBar-linkButton-nonempty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } @@ -32,7 +32,6 @@ $linkGap: 3px; .tags { width: 40px; - } } .documentButtonBar-followTypes { @@ -92,8 +91,8 @@ $linkGap: 3px; border-radius: 50%; opacity: 0.9; pointer-events: auto; - background-color: $dark-gray; - color: $white; + background-color: global.$dark-gray; + color: global.$white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -104,7 +103,7 @@ $linkGap: 3px; align-items: center; &:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } @@ -132,12 +131,12 @@ $linkGap: 3px; text-align: center; border-radius: 50%; pointer-events: auto; - background-color: $dark-gray; + background-color: global.$dark-gray; border: none; transition: 0.2s ease all; &:hover { - background-color: $medium-gray; + background-color: global.$medium-gray; } } @@ -148,7 +147,7 @@ $linkGap: 3px; text-align: center; border-radius: 50%; pointer-events: auto; - background-color: $dark-gray; + background-color: global.$dark-gray; border: none; transition: 0.2s ease all; display: flex; @@ -157,8 +156,8 @@ $linkGap: 3px; align-items: center; &:hover { - background-color: $black; - + background-color: global.$black; + .documentButtonBar-pinTypes { display: flex; } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 346df10d5..a5afb1305 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables.module'; +@use 'global/globalCssVariables.module' as global; $linkGap: 3px; $headerHeight: 20px; @@ -195,14 +195,14 @@ $resizeHandler: 8px; .documentDecorations-titleSpan { width: 100%; border-radius: 8px; - background: $light-gray; + background: global.$contextMenu-zindex; display: inline-block; cursor: move; } } .documentDecorations-titleBackground { - background: $light-gray; + background: global.$light-gray; border-radius: 8px; width: 100%; height: 100%; @@ -314,7 +314,7 @@ $resizeHandler: 8px; .documentDecorations-bottomResizer, .documentDecorations-rightResizer { pointer-events: auto; - background: $medium-gray-dim; + background: global.$medium-gray-dim; //opacity: 0.2; &:hover { opacity: 1; @@ -344,7 +344,7 @@ $resizeHandler: 8px; border-radius: 100%; left: 7px; top: 7px; - background: $medium-gray; + background: global.$medium-gray; height: 10; width: 10; opacity: 0.5; @@ -378,7 +378,7 @@ $resizeHandler: 8px; transform: translate(0px, -25%); padding-bottom: 100%; border-radius: 100%; - border: solid $medium-gray 10px; + border: solid global.$medium-gray 10px; } .documentDecorations-topLeftResizer, @@ -497,13 +497,13 @@ $resizeHandler: 8px; } .linkButton-empty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } .linkButton-nonempty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } @@ -520,7 +520,7 @@ $resizeHandler: 8px; align-items: center; gap: 5px; //top: 4px; - background: $light-gray; + background: global.$light-gray; opacity: 0.2; pointer-events: all; transition: opacity 1s; @@ -542,8 +542,8 @@ $resizeHandler: 8px; text-align: center; border-radius: 50%; pointer-events: auto; - color: $dark-gray; - border: $dark-gray 1px solid; + color: global.$dark-gray; + border: global.$dark-gray 1px solid; } .linkButton-linker:hover { @@ -558,8 +558,8 @@ $resizeHandler: 8px; border-radius: 50%; opacity: 0.9; pointer-events: auto; - background-color: $dark-gray; - color: $white; + background-color: global.$dark-gray; + color: global.$white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -570,7 +570,7 @@ $resizeHandler: 8px; align-items: center; &:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } @@ -600,13 +600,13 @@ $resizeHandler: 8px; border-radius: 50%; opacity: 0.9; font-size: 14; - background-color: $dark-gray; - color: $white; + background-color: global.$dark-gray; + color: global.$white; text-align: center; cursor: pointer; &:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); } } @@ -616,9 +616,9 @@ $resizeHandler: 8px; top: 25px; left: 0px; width: max-content; - font-family: $sans-serif; + font-family: global.$sans-serif; font-size: 12px; - background-color: $light-gray; + background-color: global.$light-gray; padding: 2px 12px; list-style: none; diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index e3df01bbb..0d3feb073 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -18,7 +18,7 @@ import { GestureOverlay } from './GestureOverlay'; import './LightboxView.scss'; import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; -import { DefaultStyleProvider, returnEmptyDocViewList, wavyBorderPath } from './StyleProvider'; +import { DefaultStyleProvider, returnEmptyDocViewList /* wavyBorderPath */ } from './StyleProvider'; import { DocumentView } from './nodes/DocumentView'; import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; import { StickerPalette } from './smartdraw/StickerPalette'; @@ -283,7 +283,7 @@ export class LightboxView extends ObservableReactComponent { top: this.topBorder, width: this.lightboxWidth(), height: this.lightboxHeight(), - clipPath: `path('${Doc.UserDoc().renderStyle === 'comic' ? wavyBorderPath(this.lightboxWidth(), this.lightboxHeight()) : undefined}')`, + // clipPath: `path('${Doc.UserDoc().renderStyle === 'comic' ? wavyBorderPath(this.lightboxWidth(), this.lightboxHeight()) : undefined}')`, background: SnappingManager.userBackgroundColor, }}> diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 02916e48e..bea1de435 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -1,5 +1,5 @@ -@import 'global/globalCssVariables.module'; -@import 'nodeModuleOverrides'; +@use 'global/globalCssVariables.module' as global; +// bcz: fix @import 'nodeModuleOverrides'; :root { --flyoutHandleWidth: 28px; @@ -10,8 +10,8 @@ body { width: 100%; height: 100%; overflow: hidden; - font-family: $sans-serif; - font-size: $body-text; + font-family: global.$sans-serif; + font-size: global.$body-text; margin: 0; position: absolute; top: 0; @@ -54,7 +54,7 @@ button { background: black; outline: none; border: 0px; - color: $white; + color: global.$white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -63,7 +63,7 @@ button { } button:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index dda543470..3c1da88cc 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -87,10 +87,9 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; await CurrentUserUtils.loadUserDocument(info); setTimeout(() => { // prevent zooming browser - document.getElementById('root')!.addEventListener('wheel', event => event.ctrlKey && event.preventDefault(), true); + document.getElementById('root')!.addEventListener('wheel', event => event.ctrlKey && event.preventDefault(), { capture: true, passive: true }); const startload = (document as unknown as { startLoad: number }).startLoad; // see index.html in deploy/ const loading = Date.now() - (startload ? Number(startload) : Date.now() - 3000); - console.log('Loading Time = ' + loading); const d = new Date(); d.setTime(d.getTime() + 100 * 24 * 60 * 60 * 1000); const expires = 'expires=' + d.toUTCString(); diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index e204759ab..2170e0c34 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -1,5 +1,5 @@ -@import 'global/globalCssVariables.module.scss'; -@import 'nodeModuleOverrides'; +@use 'global/globalCssVariables.module.scss' as global; +// bcz: fix @import 'nodeModuleOverrides'; html { overscroll-behavior-x: none; } @@ -68,10 +68,10 @@ body { } .mainView-container { - color: $dark-gray; + color: global.$dark-gray; .lm_goldenlayout { - background: $medium-gray; + background: global.$medium-gray; } } @@ -93,7 +93,7 @@ body { .mainView-propertiesDragger-minified, .mainView-propertiesDragger { //background-color: rgb(140, 139, 139); - background-color: $light-gray; + background-color: global.$light-gray; height: 55px; width: 17px; position: absolute; @@ -133,10 +133,10 @@ body { flex-direction: column; position: relative; height: 100%; - background: $medium-gray; + background: global.$medium-gray; .documentView-node-topmost { - background: $light-gray; + background: global.$light-gray; } } @@ -153,12 +153,12 @@ body { } .mainView-libraryHandle { - background-color: $light-gray; + background-color: global.$light-gray; } .mainView-leftMenuPanel { min-width: var(--menuPanelWidth); - border-right: $standard-border; + border-right: global.$standard-border; .collectionStackingView { scrollbar-width: none; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 195b1c572..8b0354471 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -99,7 +99,7 @@ export class MainView extends ObservableReactComponent { @observable private _sidebarContent: Doc = Doc.MyLeftSidebarPanel; @observable private _leftMenuFlyoutWidth: number = 0; @computed get _hideUI() { - return this.mainDoc && this.mainDoc._type_collection !== CollectionViewType.Docking; + return SnappingManager.HideUI || (this.mainDoc && this.mainDoc._type_collection !== CollectionViewType.Docking); } @computed private get dashboardTabHeight() { @@ -712,7 +712,7 @@ export class MainView extends ObservableReactComponent { childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} suppressSetHeight - renderDepth={this._hideUI ? 0 : -1} + renderDepth={-1} /> ); @@ -1168,6 +1168,10 @@ ScriptingGlobals.add(function selectMainMenu(doc: Doc) { MainView.Instance.selectMenu(doc); }); // eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function hideUI() { + SnappingManager.SetHideUI(!SnappingManager.HideUI); +}); +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, 'creates a new presentation when called'); diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index b8c73b6d3..6c2cda346 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables.module.scss'; +@use 'global/globalCssVariables.module.scss' as global; $linkGap: 3px; @@ -7,13 +7,13 @@ $linkGap: 3px; } .propertiesButtons-linkButton-empty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } .propertiesButtons-linkButton-nonempty:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } @@ -46,19 +46,19 @@ $linkGap: 3px; // margin-left: 4px; &:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); cursor: pointer; } } .propertiesButtons-linkButton-empty.toggle-on { - background-color: $medium-blue; - color: $white; + background-color: global.$medium-blue; + color: global.$white; width: 100%; } .propertiesButtons-linkButton-empty.toggle-hover { - background-color: $light-blue; - color: $black; + background-color: global.$light-blue; + color: global.$black; width: 100%; } .propertiesButtons-linkButton-empty.toggle-off { @@ -88,7 +88,7 @@ $linkGap: 3px; cursor: pointer; text-align: center; margin-top: 5px; - border: 0.5px solid $medium-gray; + border: 0.5px solid global.$medium-gray; background-color: rgb(230, 230, 230); border-radius: 5px; padding: 4px; @@ -111,7 +111,7 @@ $linkGap: 3px; .list-item { cursor: pointer; - color: $black; + color: global.$black; width: 100%; height: 25px; font-weight: 400; diff --git a/src/client/views/PropertiesSection.scss b/src/client/views/PropertiesSection.scss index d32da1bf1..f7138dd50 100644 --- a/src/client/views/PropertiesSection.scss +++ b/src/client/views/PropertiesSection.scss @@ -1,5 +1,3 @@ -@import './global/globalCssVariables.module.scss'; - .propertiesView-section { .propertiesView-content { padding: 10px; diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 7866e67e7..280de4893 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -1,4 +1,4 @@ -@import './global/globalCssVariables.module.scss'; +@use './global/globalCssVariables.module.scss' as global; .propertiesView-presentationTrails-title { display: flex; @@ -28,7 +28,7 @@ font-family: 'Roboto'; font-size: 12px; cursor: auto; - border-left: $standard-border; + border-left: global.$standard-border; .slider-text { font-size: 8px; @@ -567,7 +567,7 @@ height: fit-content; &:hover { - border: 0.75px solid $medium-blue; + border: 0.75px solid global.$medium-blue; } } diff --git a/src/client/views/TemplateMenu.scss b/src/client/views/TemplateMenu.scss index 36a9ce6d0..8879fc20d 100644 --- a/src/client/views/TemplateMenu.scss +++ b/src/client/views/TemplateMenu.scss @@ -1,4 +1,4 @@ -@import 'global/globalCssVariables.module.scss'; +@use 'global/globalCssVariables.module.scss' as global; .templating-menu { position: absolute; pointer-events: auto; @@ -24,15 +24,15 @@ cursor: pointer; &:hover { - background: $medium-gray; + background: global.$medium-gray; transform: scale(1.05); } } .template-list { - font-family: $sans-serif; + font-family: global.$sans-serif; font-size: 12px; - background-color: $light-gray; + background-color: global.$light-gray; padding: 2px 12px; list-style: none; position: relative; diff --git a/src/client/views/animationtimeline/Region.scss b/src/client/views/animationtimeline/Region.scss index b390ae34e..df82febea 100644 --- a/src/client/views/animationtimeline/Region.scss +++ b/src/client/views/animationtimeline/Region.scss @@ -1,4 +1,4 @@ -@import './../global/globalCssVariables.module.scss'; +@use './../global/globalCssVariables.module.scss' as global; $timelineColor: #9acedf; $timelineDark: #77a1aa; @@ -14,11 +14,11 @@ $timelineDark: #77a1aa; height: 200px; top: 50%; position: relative; - background-color: $white; + background-color: global.$white; .menutable { tr:nth-child(odd) { - background-color: $light-gray; + background-color: global.$light-gray; } } } @@ -70,7 +70,7 @@ $timelineDark: #77a1aa; height: 100%; position: absolute; pointer-events: none; - background: linear-gradient(to left, $timelineColor 10%, $white); + background: linear-gradient(to left, $timelineColor 10%, global.$white); } .fadeRight { @@ -78,7 +78,7 @@ $timelineDark: #77a1aa; height: 100%; position: absolute; pointer-events: none; - background: linear-gradient(to right, $timelineColor 10%, $white); + background: linear-gradient(to right, $timelineColor 10%, global.$white); } .divider { diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss index 35ba0fa7f..e1d3b190c 100644 --- a/src/client/views/animationtimeline/Timeline.scss +++ b/src/client/views/animationtimeline/Timeline.scss @@ -1,4 +1,4 @@ -@import './../global/globalCssVariables.module.scss'; +@use './../global/globalCssVariables.module.scss' as global; $timelineColor: #9acedf; $timelineDark: #77a1aa; @@ -159,7 +159,7 @@ $timelineDark: #77a1aa; width: 100%; height: 300px; position: absolute; - background-color: $light-gray; + background-color: global.$light-gray; border-bottom: 2px solid $timelineDark; transition: transform 500ms ease; @@ -247,7 +247,7 @@ $timelineDark: #77a1aa; top: 0px; width: 100px; height: 30%; - border: 1px solid $dark-gray; + border: 1px solid global.$dark-gray; font-size: 12px; line-height: 11px; background-color: $timelineDark; diff --git a/src/client/views/animationtimeline/TimelineMenu.scss b/src/client/views/animationtimeline/TimelineMenu.scss index de2042f17..5398a4a97 100644 --- a/src/client/views/animationtimeline/TimelineMenu.scss +++ b/src/client/views/animationtimeline/TimelineMenu.scss @@ -1,9 +1,9 @@ -@import './../global/globalCssVariables.module.scss'; +@use './../global/globalCssVariables.module.scss' as global; .timeline-menu-container { position: absolute; display: flex; - box-shadow: $medium-gray 0.2vw 0.2vw 0.4vw; + box-shadow: global.$medium-gray 0.2vw 0.2vw 0.4vw; flex-direction: column; background: whitesmoke; z-index: 10000; @@ -14,7 +14,7 @@ border: solid #bbbbbbbb 1px; .timeline-menu-input { - font: $sans-serif; + font: global.$sans-serif; font-size: 13px; width: 100%; text-transform: uppercase; @@ -33,11 +33,11 @@ border-top-left-radius: 15px; border-top-right-radius: 15px; text-transform: uppercase; - background: $dark-gray; + background: global.$dark-gray; letter-spacing: 2px; .timeline-menu-header-desc { - font: $sans-serif; + font: global.$sans-serif; font-size: 13px; text-align: center; color: whitesmoke; @@ -72,15 +72,15 @@ .timeline-menu-item:hover { border-width: 0.11px; border-style: none; - border-color: $medium-gray; + border-color: global.$medium-gray; border-bottom-style: solid; border-top-style: solid; - background: $medium-blue; + background: global.$medium-blue; } .timeline-menu-desc { padding-left: 10px; - font: $sans-serif; + font: global.$sans-serif; font-size: 13px; } } diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss index 2878232e6..8336f2b2f 100644 --- a/src/client/views/animationtimeline/TimelineOverview.scss +++ b/src/client/views/animationtimeline/TimelineOverview.scss @@ -1,4 +1,4 @@ -@import './../global/globalCssVariables.module.scss'; +@use './../global/globalCssVariables.module.scss' as global; $timelineColor: #9acedf; $timelineDark: #77a1aa; diff --git a/src/client/views/animationtimeline/Track.scss b/src/client/views/animationtimeline/Track.scss index f56b2fe5f..7f5e8b8f3 100644 --- a/src/client/views/animationtimeline/Track.scss +++ b/src/client/views/animationtimeline/Track.scss @@ -1,12 +1,12 @@ -@import './../global/globalCssVariables.module.scss'; +@use './../global/globalCssVariables.module.scss' as global; .track-container { .track { .inner { top: 0px; width: calc(100%); - background-color: $white; - border: 1px solid $dark-gray; + background-color: global.$white; + border: 1px solid global.$dark-gray; position: relative; z-index: 100; } diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index 79c53db08..06dd4627f 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -1,5 +1,3 @@ -@import '../global/globalCssVariables.module.scss'; - .collectionCardView-outer { height: 100%; width: 100%; diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss index 42e112906..13e6b54c2 100644 --- a/src/client/views/collections/CollectionCarousel3DView.scss +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionCarousel3DView-outer { height: 100%; position: relative; @@ -10,8 +10,8 @@ .carousel-wrapper { display: flex; position: absolute; - top: $CAROUSEL3D_TOP * 1%; - height: ($CAROUSEL3D_SIDE_SCALE * 100) * 1%; + top: global.$CAROUSEL3D_TOP * 1%; + height: (global.$CAROUSEL3D_SIDE_SCALE * 100) * 1%; align-items: center; transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); @@ -24,7 +24,7 @@ pointer-events: none; opacity: 0.5; z-index: 1; - transform: scale($CAROUSEL3D_SIDE_SCALE); + transform: scale(global.$CAROUSEL3D_SIDE_SCALE); user-select: none; } @@ -32,7 +32,7 @@ pointer-events: unset; opacity: 1; z-index: 2; - transform: scale($CAROUSEL3D_CENTER_SCALE); + transform: scale(global.$CAROUSEL3D_CENTER_SCALE); } } @@ -80,7 +80,7 @@ .carousel3DView-back { top: 0; background: transparent; - width: calc((1 - #{$CAROUSEL3D_CENTER_SCALE} * 0.33) / 2 * 100%); + width: calc((1 - #{global.$CAROUSEL3D_CENTER_SCALE} * 0.33) / 2 * 100%); height: 100%; } diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index a747ef45f..7c19d39da 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .lm_root { position: relative; @@ -285,7 +285,7 @@ background: transparent; border: solid 0px transparent; cursor: grab; - color: $black; + color: global.$black; } .collectiondockingview-container .lm_splitter { opacity: 0.2; @@ -378,7 +378,7 @@ ul.lm_tabs::before { z-index: 1; text-align: center; font-size: 18; - color: $dark-gray; + color: global.$dark-gray; img { position: relative; @@ -491,7 +491,7 @@ ul.lm_tabs::before { } .lm_content { - background: $white; + background: global.$white; } .lm_controls { @@ -557,7 +557,7 @@ ul.lm_tabs::before { } .flexlayout__splitter { - background-color: $dark-gray; + background-color: global.$dark-gray; } .flexlayout__splitter:hover { @@ -626,7 +626,7 @@ ul.lm_tabs::before { position: absolute; box-sizing: border-box; background-color: #222; - color: $dark-gray; + color: global.$dark-gray; } .flexlayout__tab_button { @@ -709,7 +709,7 @@ ul.lm_tabs::before { } .flexlayout__tab_header_outer { - background-color: $dark-gray; + background-color: global.$dark-gray; position: absolute; left: 0; right: 0; @@ -769,28 +769,28 @@ ul.lm_tabs::before { } .flexlayout__border_top { - background-color: $dark-gray; + background-color: global.$dark-gray; border-bottom: 1px solid #ddd; box-sizing: border-box; overflow: hidden; } .flexlayout__border_bottom { - background-color: $dark-gray; + background-color: global.$dark-gray; border-top: 1px solid #333; box-sizing: border-box; overflow: hidden; } .flexlayout__border_left { - background-color: $dark-gray; + background-color: global.$dark-gray; border-right: 1px solid #333; box-sizing: border-box; overflow: hidden; } .flexlayout__border_right { - background-color: $dark-gray; + background-color: global.$dark-gray; border-left: 1px solid #333; box-sizing: border-box; overflow: hidden; diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 45d9394ed..11fce720c 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -1,13 +1,13 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionMenu-container { display: flex; position: relative; align-content: center; justify-content: space-between; - background-color: $dark-gray; + background-color: global.$dark-gray; height: 40px; - border-bottom: $standard-border; + border-bottom: global.$standard-border; padding: 0 10px; align-items: center; overflow-x: auto; diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss index 95fda7b0a..0d24a56b5 100644 --- a/src/client/views/collections/CollectionNoteTakingView.scss +++ b/src/client/views/collections/CollectionNoteTakingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionNoteTakingView-DocumentButtons { opacity: 0; @@ -58,7 +58,7 @@ .documentButtonMenu { position: relative; height: fit-content; - border-bottom: $standard-border; + border-bottom: global.$standard-border; display: flex; justify-content: center; flex-direction: column; @@ -70,11 +70,11 @@ width: 90%; margin: 5px; font-size: 11px; - background-color: $light-blue; - color: $medium-blue; + background-color: global.$light-blue; + color: global.$medium-blue; padding: 10px; border-radius: 10px; - border: solid 2px $medium-blue; + border: solid 2px global.$medium-blue; } } @@ -146,9 +146,9 @@ padding: 10px; height: 2vw; width: 100%; - font-family: $sans-serif; - background: $dark-gray; - color: $white; + font-family: global.$sans-serif; + background: global.$dark-gray; + color: global.$white; } .collectionNoteTakingView-columnDragger { @@ -206,7 +206,7 @@ margin-left: 2px; margin-right: 2px; margin-top: 2px; - background: $medium-gray; + background: global.$medium-gray; height: 5px; &.active { @@ -258,7 +258,7 @@ text-align: center; margin: auto; margin-bottom: 10px; - background: $medium-gray; + background: global.$medium-gray; // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong .editableView-input:hover, @@ -279,7 +279,7 @@ display: flex; align-items: center; justify-content: center; - color: $dark-gray; + color: global.$dark-gray; .editableView-container-editing-oneLine, .editableView-container-editing { diff --git a/src/client/views/collections/CollectionStackedTimeline.scss b/src/client/views/collections/CollectionStackedTimeline.scss index 0ced3f9e3..d05c0ffde 100644 --- a/src/client/views/collections/CollectionStackedTimeline.scss +++ b/src/client/views/collections/CollectionStackedTimeline.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionStackedTimeline-timelineContainer { height: 100%; @@ -6,7 +6,7 @@ overflow-x: auto; overflow-y: hidden; border: none; - background-color: $white; + background-color: global.$white; border-width: 0 2px 0 2px; &:hover { @@ -28,7 +28,7 @@ .collectionStackedTimeline { position: absolute; - background: $off-white; + background: global.$off-white; z-index: 1000; height: 100%; overflow: hidden; @@ -36,7 +36,7 @@ .collectionStackedTimeline-trim-shade { position: absolute; height: 100%; - background-color: $dark-gray; + background-color: global.$dark-gray; opacity: 0.3; top: 0; } @@ -45,7 +45,7 @@ height: 100%; position: absolute; box-sizing: border-box; - border: 2px solid $medium-blue; + border: 2px solid global.$medium-blue; display: flex; justify-content: space-between; max-width: 100%; @@ -53,7 +53,7 @@ left: 0; .collectionStackedTimeline-trim-handle { - background-color: $medium-blue; + background-color: global.$medium-blue; height: 100%; width: 5px; cursor: ew-resize; @@ -65,12 +65,12 @@ width: 10px; top: 2.5%; height: 95%; - background: $light-blue; + background: global.$light-blue; border-radius: 3px; opacity: 0.3; z-index: 500; border-style: solid; - border-color: $medium-blue; + border-color: global.$medium-blue; border-width: 1px; } @@ -84,12 +84,12 @@ } .collectionStackedTimeline-current { - background-color: $pink; + background-color: global.$pink; } .collectionStackedTimeline-hover { display: none; - background-color: $medium-blue; + background-color: global.$medium-blue; } .collectionStackedTimeline-marker-timeline { @@ -97,14 +97,14 @@ top: 2.5%; height: 95%; border-radius: 4px; - //background: $light-gray; + //background: global.$light-gray; &:hover { opacity: 1; } .collectionStackedTimeline-left-resizer, .collectionStackedTimeline-resizer { - background: $dark-gray; + background: global.$dark-gray; position: absolute; top: 0; height: 100%; @@ -141,7 +141,7 @@ .hoverTime { position: absolute; - color: $dark-gray; + color: global.$dark-gray; transform: translate(0, -100%); font-weight: bold; diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 6400a0a8e..5237bdffb 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionMasonryView { display: inline; @@ -18,7 +18,7 @@ .documentButtonMenu { position: relative; height: fit-content; - border-bottom: $standard-border; + border-bottom: global.$standard-border; display: flex; justify-content: center; flex-direction: column; @@ -30,10 +30,10 @@ width: 90%; margin: 5px; font-size: 11px; - color: $medium-blue; + color: global.$medium-blue; padding: 10px; border-radius: 5px; - border: solid 0.5px $medium-blue; + border: solid 0.5px global.$medium-blue; } } @@ -115,9 +115,9 @@ padding: 10px; height: 2vw; width: 100%; - font-family: $sans-serif; - background: $dark-gray; - color: $white; + font-family: global.$sans-serif; + background: global.$dark-gray; + color: global.$white; } .collectionStackingView-columnDragger { @@ -149,7 +149,7 @@ .collectionStackingView-collapseBar { margin-top: 2px; - background: $medium-gray; + background: global.$medium-gray; height: 5px; width: 100%; display: none; @@ -207,11 +207,11 @@ text-align: center; margin: auto; margin-bottom: 10px; - background: $medium-gray; + background: global.$medium-gray; // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong .editableView-input { - color: $dark-gray; + color: global.$dark-gray; } .editableView-input:hover, @@ -232,7 +232,7 @@ display: flex; align-items: center; justify-content: center; - color: $dark-gray; + color: global.$dark-gray; .editableView-container-editing-oneLine, .editableView-container-editing { diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index bbbef78b4..2a03ea708 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionTreeView-container { transform-origin: top left; @@ -12,7 +12,7 @@ width: 100%; position: relative; top: 0; - // background: $light-gray; + // background: global.$light-gray; font-size: 13px; overflow: auto; user-select: none; @@ -21,7 +21,7 @@ ul { list-style: none; - padding-left: $TREE_BULLET_WIDTH; + padding-left: global.$TREE_BULLET_WIDTH; margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason.... > .contentFittingDocumentView { width: unset; @@ -47,7 +47,7 @@ } .delete-button { - color: $medium-gray; + color: global.$medium-gray; // float: right; margin-left: 15px; // margin-top: 3px; @@ -90,7 +90,7 @@ .collectionTreeView-subtitle { font-style: italic; font-size: 8pt; - color: $medium-gray; + color: global.$medium-gray; } .docContainer { diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss index de53a2c62..06c324bd0 100644 --- a/src/client/views/collections/CollectionView.scss +++ b/src/client/views/collections/CollectionView.scss @@ -1,10 +1,10 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .collectionView { border-width: 0; - border-color: $light-gray; + border-color: global.$light-gray; border-style: solid; - border-radius: 0 0 $border-radius $border-radius; + border-radius: 0 0 global.$border-radius global.$border-radius; box-sizing: border-box; border-radius: inherit; width: 100%; diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss index dd4c0b881..397e35ca9 100644 --- a/src/client/views/collections/TabDocView.scss +++ b/src/client/views/collections/TabDocView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .tabDocView-content { height: 100%; diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 2ab1a5ac1..78794d112 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .treeView-label { max-height: 1.5em; @@ -14,7 +14,7 @@ .bullet-outline { position: relative; width: fit-content; - color: $medium-gray; + color: global.$medium-gray; transform: scale(0.5); display: inline-flex; align-items: center; @@ -66,7 +66,7 @@ min-height: 20px; min-width: 15px; margin-right: 3px; - color: $medium-gray; + color: global.$medium-gray; border: #80808030 1px solid; border-radius: 5px; z-index: 1; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 46bd37f6d..cce0ff684 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; .collectionfreeformview-none { position: inherit; @@ -32,9 +32,9 @@ .collectionfreeformview-mask-empty, .collectionfreeformview-mask { z-index: 5000; - width: $INK_MASK_SIZE; - height: $INK_MASK_SIZE; - transform: translate($INK_MASK_SIZE_HALF, $INK_MASK_SIZE_HALF); + width: global.$INK_MASK_SIZE; + height: global.$INK_MASK_SIZE; + transform: translate(global.$INK_MASK_SIZE_HALF, global.$INK_MASK_SIZE_HALF); pointer-events: none; position: absolute; background-color: transparent; @@ -211,11 +211,11 @@ //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-image: linear-gradient(to right, global.$light-color-secondary 1px, transparent 1px), + // linear-gradient(to bottom, global.$light-color-secondary 1px, transparent 1px); // background-size: 30px 30px; // } - border: 0px solid $light-gray; + border: 0px solid global.$light-gray; border-radius: inherit; box-sizing: border-box; position: absolute; @@ -233,7 +233,7 @@ box-sizing: border-box; width: 98%; height: 98%; - border-radius: $border-radius; + border-radius: global.$border-radius; } //this is an animation for the blinking cursor! diff --git a/src/client/views/collections/collectionFreeForm/ImageLabelHandler.tsx b/src/client/views/collections/collectionFreeForm/ImageLabelHandler.tsx index f050b9846..1a44e094d 100644 --- a/src/client/views/collections/collectionFreeForm/ImageLabelHandler.tsx +++ b/src/client/views/collections/collectionFreeForm/ImageLabelHandler.tsx @@ -9,7 +9,8 @@ import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './ImageLabelHandler.scss'; @observer -export class ImageLabelHandler extends ObservableReactComponent<{}> { +export class ImageLabelHandler extends ObservableReactComponent { + // eslint-disable-next-line no-use-before-define static Instance: ImageLabelHandler; @observable _display: boolean = false; @@ -19,11 +20,10 @@ export class ImageLabelHandler extends ObservableReactComponent<{}> { @observable _currentLabel: string = ''; @observable _labelGroups: string[] = []; - constructor(props: any) { + constructor(props: object) { super(props); makeObservable(this); ImageLabelHandler.Instance = this; - console.log('Instantiated label handler!'); } @action @@ -41,8 +41,8 @@ export class ImageLabelHandler extends ObservableReactComponent<{}> { }; @action - addLabel = (label: string) => { - label = label.toUpperCase().trim(); + addLabel = (labelIn: string) => { + const label = labelIn.toUpperCase().trim(); if (label.length > 0) { if (!this._labelGroups.includes(label)) { this._labelGroups = [...this._labelGroups, label]; @@ -96,10 +96,10 @@ export class ImageLabelHandler extends ObservableReactComponent<{}> {
{this._labelGroups.map(group => { return ( -
+

{group}

{ this.removeLabel(group); }} diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.scss b/src/client/views/collections/collectionLinear/CollectionLinearView.scss index b8ceec139..0dfaed38a 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.scss +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.scss @@ -1,12 +1,12 @@ -@import '../../global/globalCssVariables.module.scss'; -@import '../../_nodeModuleOverrides'; +@use '../../global/globalCssVariables.module.scss' as global; +// bcz fix @import '../../_nodeModuleOverrides'; .collectionLinearView { width: 100%; } .collectionLinearView-label { color: black; - background-color: $light-gray; + background-color: global.$light-gray; width: 100%; } .collectionLinearView-outer { @@ -32,8 +32,8 @@ } > span { - background: $dark-gray; - color: $white; + background: global.$dark-gray; + color: global.$white; border-radius: 18px; margin-right: 6px; cursor: pointer; @@ -44,7 +44,7 @@ } .bottomPopup-background { - background: $medium-blue; + background: global.$medium-blue; display: flex; border-radius: 10px; height: 35; @@ -55,7 +55,7 @@ } .bottomPopup-text { - color: $white; + color: global.$white; display: inline; white-space: nowrap; padding-left: 8px; @@ -72,7 +72,7 @@ padding-left: 8px; padding-right: 8px; vertical-align: middle; - background-color: $light-gray; + background-color: global.$light-gray; border-radius: 3px; color: black; margin-right: 5px; @@ -86,7 +86,7 @@ padding-left: 8px; padding-right: 8px; vertical-align: middle; - background-color: $close-red; + background-color: global.$close-red; border-radius: 3px; color: black; } @@ -94,13 +94,13 @@ > label { pointer-events: all; cursor: pointer; - background-color: $medium-blue; + background-color: global.$medium-blue; padding: 5; border-radius: 2px; height: 100%; min-width: 25; margin: 0; - color: $white; + color: global.$white; display: flex; font-weight: 100; transition: transform 0.2s; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 817ceac97..0bf78f57c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; .collectionSchemaView { cursor: default; @@ -7,7 +7,7 @@ flex-direction: row; .schema-table { - background-color: $white; + background-color: global.$white; cursor: grab; width: 100%; @@ -49,10 +49,10 @@ .schema-column-menu, .schema-filter-menu { - background: $light-gray; + background: global.$light-gray; position: absolute; - border: 1px solid $medium-gray; - border-bottom: 2px solid $medium-gray; + border: 1px solid global.$medium-gray; + border-bottom: 2px solid global.$medium-gray; max-height: 201px; display: flex; overflow: hidden; @@ -66,7 +66,7 @@ width: 100%; &:hover { - background-color: $medium-gray; + background-color: global.$medium-gray; } .schema-search-result-type { font-family: 'Courier New', Courier, monospace; @@ -74,8 +74,8 @@ .schema-search-result-type, .schema-search-result-desc { - color: $dark-gray; - font-size: $body-text; + color: global.$dark-gray; + font-size: global.$body-text; } .schema-search-result-desc { font-style: italic; @@ -120,9 +120,9 @@ .schema-column-menu-button { cursor: pointer; padding: 2px 5px; - background: $medium-blue; + background: global.$medium-blue; border-radius: 9999px; - color: $white; + color: global.$white; width: fit-content; margin: 5px; align-self: center; @@ -141,7 +141,7 @@ } .schema-column-header { - background-color: $light-gray; + background-color: global.$light-gray; font-weight: bold; display: flex; flex-direction: row; @@ -149,7 +149,7 @@ align-items: center; padding: 0; z-index: 1; - border: 1px solid $medium-gray; + border: 1px solid global.$medium-gray; .schema-column-title { flex-grow: 2; @@ -175,7 +175,7 @@ cursor: ew-resize; &:hover { - background-color: $light-blue; + background-color: global.$light-blue; } } @@ -188,7 +188,7 @@ min-width: 5px; transform: translate(-3px, 0px); align-self: flex-start; - background-color: $medium-gray; + background-color: global.$medium-gray; }*/ // creates awkward thick gray borders between colheaders } @@ -202,7 +202,7 @@ } .schema-header-row { - background-color: $light-gray; + background-color: global.$light-gray; overflow: hidden; } @@ -226,7 +226,7 @@ .schema-table-cell, .row-menu { - border: 1px solid $medium-gray; + border: 1px solid global.$medium-gray; overflow-x: hidden; overflow-y: auto; display: inline-flex; @@ -264,7 +264,7 @@ .row-menu-infos { position: absolute; top: 3; - left: 3; + left: 3; z-index: 1; display: flex; justify-content: flex-end; @@ -278,7 +278,7 @@ .schema-row-button, .schema-header-button { - color: $dark-gray; + color: global.$dark-gray; margin: 3px; cursor: pointer; display: flex; @@ -294,7 +294,7 @@ width: 17px; height: 17px; border-radius: 30%; - background-color: $dark-gray; + background-color: global.$dark-gray; color: white; margin: 3px; cursor: pointer; @@ -311,5 +311,3 @@ outline: none; height: 100%; } - - diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 636b6415c..ebf60b287 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .linkMenu { width: auto; diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index 66ddd6eca..3cd60c87f 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -1,7 +1,7 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .linkMenu-item { - // border-top: 0.5px solid $medium-gray; + // border-top: 0.5px solid global.$medium-gray; position: relative; display: flex; border-top: 0.5px solid #cdcdcd; @@ -120,7 +120,7 @@ border-radius: 50%; pointer-events: auto; background-color: red; - color: $white; + color: global.$white; font-size: 65%; transition: transform 0.2s; text-align: center; @@ -138,7 +138,7 @@ } &:hover { - background: $medium-gray; + background: global.$medium-gray; cursor: pointer; } } diff --git a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.scss b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.scss index 74fbfbb2c..cb1e11780 100644 --- a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.scss +++ b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.scss @@ -1,15 +1,15 @@ -@import '../NewLightboxStyles.scss'; +@use '../NewLightboxStyles.scss' as newstyles; .newLightboxButtonMeny-container { width: 100vw; height: 100vh; - + &.dark { - background: $black; + background: newstyles.$black; } - + &.light, &.default { - background: $white; + background: newstyles.$white; } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/ExploreView/ExploreView.scss b/src/client/views/newlightbox/ExploreView/ExploreView.scss index 5a8ab2f87..2c264c514 100644 --- a/src/client/views/newlightbox/ExploreView/ExploreView.scss +++ b/src/client/views/newlightbox/ExploreView/ExploreView.scss @@ -1,4 +1,4 @@ -@import '../NewLightboxStyles.scss'; +@use '../NewLightboxStyles.scss' as newstyles; .exploreView-container { width: 100%; @@ -6,39 +6,39 @@ border-radius: 20px; position: relative; // transform: scale(1); - background: $gray-l1; - border-top: $standard-border; - border-color: $gray-l2; + background: newstyles.$gray-l1; + border-top: newstyles.$standard-border; + border-color: newstyles.$gray-l2; border-radius: 0px 0px 20px 20px; transform-origin: 50% 50%; overflow: hidden; &.dark { - background: $black; + background: newstyles.$black; } - + &.light, &.default { - background: $gray-l1; + background: newstyles.$gray-l1; } .exploreView-doc { - width: 60px; - height: 80px; - position: absolute; - background: $blue-l2; - // opacity: 0.8; - transform-origin: 50% 50%; - transform: translate(-50%, -50%) scale(1); - cursor: pointer; - transition: 0.2s ease; - overflow: hidden; - font-size: 9px; - padding: 10px; - border-radius: 5px; + width: 60px; + height: 80px; + position: absolute; + background: newstyles.$blue-l2; + // opacity: 0.8; + transform-origin: 50% 50%; + transform: translate(-50%, -50%) scale(1); + cursor: pointer; + transition: 0.2s ease; + overflow: hidden; + font-size: 9px; + padding: 10px; + border-radius: 5px; - &:hover { - transform: translate(calc(-50% * 1.125), calc(-50% * 1.125)) scale(1.5); - } + &:hover { + transform: translate(calc(-50% * 1.125), calc(-50% * 1.125)) scale(1.5); + } } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/Header/LightboxHeader.scss b/src/client/views/newlightbox/Header/LightboxHeader.scss index a9e60ea98..5b316890d 100644 --- a/src/client/views/newlightbox/Header/LightboxHeader.scss +++ b/src/client/views/newlightbox/Header/LightboxHeader.scss @@ -1,9 +1,9 @@ -@import '../NewLightboxStyles.scss'; +@use '../NewLightboxStyles.scss' as newstyles; .newLightboxHeader-container { width: 100%; height: 100%; - background: $gray-l1; + background: newstyles.$gray-l1; border-radius: 20px 20px 0px 0px; padding: 20px; display: grid; @@ -29,13 +29,13 @@ grid-row: 2; .type { padding: 2px 7px !important; - background: $gray-l2; + background: newstyles.$gray-l2; } } .lb-label { - color: $gray-l3; - font-weight: $h1-weight; + color: newstyles.$gray-l3; + font-weight: newstyles.$h1-weight; } .lb-button { @@ -47,25 +47,25 @@ justify-content: space-evenly; align-items: center; transition: 0.2s ease; - gap: 5px; - font-size: $body-size; + gap: 5px; + font-size: newstyles.$body-size; height: fit-content; &:hover { - background: $gray-l2; + background: newstyles.$gray-l2; } &.true { - background: $blue-l1; + background: newstyles.$blue-l1; } } - + &.dark { - background: $black; + background: newstyles.$black; } - + &.light, &.default { - background: $white; + background: newstyles.$white; } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/RecommendationList/RecommendationList.scss b/src/client/views/newlightbox/RecommendationList/RecommendationList.scss index 40dd47e47..99c935e0c 100644 --- a/src/client/views/newlightbox/RecommendationList/RecommendationList.scss +++ b/src/client/views/newlightbox/RecommendationList/RecommendationList.scss @@ -1,4 +1,4 @@ -@import '../NewLightboxStyles.scss'; +@use '../NewLightboxStyles.scss' as newstyles; .recommendationlist-container { height: calc(100% - 40px); @@ -7,111 +7,110 @@ overflow-y: scroll; .recommendations { - height: fit-content; - padding: 20px; - display: flex; - flex-direction: column; - gap: 20px; - background: $gray-l1; - border-radius: 0px 0px 20px 20px; + height: fit-content; + padding: 20px; + display: flex; + flex-direction: column; + gap: 20px; + background: newstyles.$gray-l1; + border-radius: 0px 0px 20px 20px; } .header { - top: 0px; - position: sticky; - background: $gray-l1; - border-bottom: $standard-border; - border-color: $gray-l2; - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; - border-radius: 20px 20px 0px 0px; - padding: 20px; - z-index: 2; - gap: 10px; - color: $text-color-lm; - - .lb-label { - color: $gray-l3; - font-weight: $h1-weight; - font-size: $body-size; - } - - .lb-caret { + top: 0px; + position: sticky; + background: newstyles.$gray-l1; + border-bottom: newstyles.$standard-border; + border-color: newstyles.$gray-l2; display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: center; - gap: 5px; - cursor: pointer; - width: 100%; - user-select: none; - font-size: $body-size; - } + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + border-radius: 20px 20px 0px 0px; + padding: 20px; + z-index: 2; + gap: 10px; + color: newstyles.$text-color-lm; - .more { - width: 100%; - } + .lb-label { + color: newstyles.$gray-l3; + font-weight: newstyles.$h1-weight; + font-size: newstyles.$body-size; + } - &.dark { - color: $text-color-dm; - } + .lb-caret { + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + gap: 5px; + cursor: pointer; + width: 100%; + user-select: none; + font-size: newstyles.$body-size; + } - .title { - height: 30px; - min-height: 30px; - font-size: $h1-size; - font-weight: $h1-weight; - text-align: left; - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - } + .more { + width: 100%; + } - .keywords { - display: flex; - flex-flow: row wrap; - gap: 5px; + &.dark { + color: newstyles.$text-color-dm; + } - .keyword-input { - padding: 3px 7px; - background: $gray-l2; - outline: none; - border: none; - height: 21.5px; - color: $text-color-lm; + .title { + height: 30px; + min-height: 30px; + font-size: newstyles.$h1-size; + font-weight: newstyles.$h1-weight; + text-align: left; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; } - .keyword { - padding: 3px 7px; - width: fit-content; - background: $gray-l2; - display: flex; - justify-content: center; - align-items: center; - flex-direction: row; - gap: 10px; - font-size: $body-size; - font-weight: $body-weight; + .keywords { + display: flex; + flex-flow: row wrap; + gap: 5px; - &.loading { - animation: skeleton-loading-l2 1s linear infinite alternate; - min-width: 70px; - height: 21.5px; - } - } + .keyword-input { + padding: 3px 7px; + background: newstyles.$gray-l2; + outline: none; + border: none; + height: 21.5px; + color: newstyles.$text-color-lm; + } + + .keyword { + padding: 3px 7px; + width: fit-content; + background: newstyles.$gray-l2; + display: flex; + justify-content: center; + align-items: center; + flex-direction: row; + gap: 10px; + font-size: newstyles.$body-size; + font-weight: newstyles.$body-weight; - } + &.loading { + animation: skeleton-loading-l2 1s linear infinite alternate; + min-width: 70px; + height: 21.5px; + } + } + } } - + &.dark { - background: $black; + background: newstyles.$black; } - + &.light, &.default { - background: $gray-l1; + background: newstyles.$gray-l1; } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/components/EditableText/EditableText.scss b/src/client/views/newlightbox/components/EditableText/EditableText.scss index 7828538ab..8007e8d43 100644 --- a/src/client/views/newlightbox/components/EditableText/EditableText.scss +++ b/src/client/views/newlightbox/components/EditableText/EditableText.scss @@ -1,34 +1,34 @@ -@import '../../NewLightboxStyles.scss'; +@use '../../NewLightboxStyles.scss' as newstyles; .lb-editableText, .lb-displayText { padding: 4px 7px !important; - border: $standard-border !important; - border-color: $gray-l2 !important; + border: newstyles.$standard-border !important; + border-color: newstyles.$gray-l2 !important; } .lb-editableText { - -webkit-appearance: none; - overflow: hidden; - font-size: inherit; - border: none; - outline: none; - width: 100%; - margin: 0px; - padding: 0px; - box-shadow: none !important; - background: none; - - &:focus { + -webkit-appearance: none; + overflow: hidden; + font-size: inherit; + border: none; outline: none; - background-color: $blue-l1; - } + width: 100%; + margin: 0px; + padding: 0px; + box-shadow: none !important; + background: none; + + &:focus { + outline: none; + background-color: newstyles.$blue-l1; + } } .lb-displayText { - cursor: text !important; - width: 100%; - display: flex; - align-items: center; - font-size: inherit; -} \ No newline at end of file + cursor: text !important; + width: 100%; + display: flex; + align-items: center; + font-size: inherit; +} diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.scss b/src/client/views/newlightbox/components/Recommendation/Recommendation.scss index c86c63ba0..cf6b5ccb1 100644 --- a/src/client/views/newlightbox/components/Recommendation/Recommendation.scss +++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.scss @@ -1,4 +1,4 @@ -@import '../../NewLightboxStyles.scss'; +@use '../../NewLightboxStyles.scss' as newstyles; .recommendation-container { width: 100%; @@ -8,22 +8,22 @@ display: grid; grid-template-columns: 0% 100%; grid-template-rows: auto auto auto auto auto; - gap: 5px 0px; + gap: 5px 0px; padding: 10px; cursor: pointer; transition: 0.2s ease; - border: $standard-border; - border-color: $gray-l2; + border: newstyles.$standard-border; + border-color: newstyles.$gray-l2; background: white; &:hover { - // background: white !important; - transform: scale(1.02); - z-index: 0; + // background: white !important; + transform: scale(1.02); + z-index: 0; - .title { - text-decoration: underline; - } + .title { + text-decoration: underline; + } } &.previewUrl { @@ -39,18 +39,18 @@ grid-template-rows: auto auto auto auto auto; gap: 5px 10px; - .image-container, - .title, - .info, - .source, - .explainer, - .hide-rec { - animation: skeleton-loading-l3 1s linear infinite alternate; - } + .image-container, + .title, + .info, + .source, + .explainer, + .hide-rec { + animation: skeleton-loading-l3 1s linear infinite alternate; + } - .title { - border-radius: 20px; - } + .title { + border-radius: 20px; + } } .distance-container, @@ -64,62 +64,62 @@ } .image-container { - grid-row: 2/5; - grid-column: 1; - border-radius: 20px; - overflow: hidden; + grid-row: 2/5; + grid-column: 1; + border-radius: 20px; + overflow: hidden; - .image { - width: 100%; - height: 100%; - object-fit: cover; - } + .image { + width: 100%; + height: 100%; + object-fit: cover; + } } .title { - grid-row: 1; - grid-column: 1/3; - border-radius: 20px; - font-size: $h2-size; - font-weight: $h2-weight; - overflow: hidden; - border-radius: 0px; - min-height: 30px; + grid-row: 1; + grid-column: 1/3; + border-radius: 20px; + font-size: newstyles.$h2-size; + font-weight: newstyles.$h2-weight; + overflow: hidden; + border-radius: 0px; + min-height: 30px; } .info { - grid-row: 2; - grid-column: 2; - border-radius: 20px; - display: flex; - flex-direction: row; - gap: 5px; - font-size: $body-size; + grid-row: 2; + grid-column: 2; + border-radius: 20px; + display: flex; + flex-direction: row; + gap: 5px; + font-size: newstyles.$body-size; .lb-type { padding: 2px 7px !important; - background: $gray-l2; + background: newstyles.$gray-l2; } } .lb-label { - color: $gray-l3; - font-weight: $h1-weight; - font-size: $body-size; + color: newstyles.$gray-l3; + font-weight: newstyles.$h1-weight; + font-size: newstyles.$body-size; } .source { grid-row: 3; grid-column: 2; border-radius: 20px; - font-size: $body-size; + font-size: newstyles.$body-size; display: flex; justify-content: flex-start; align-items: center; .lb-source { padding: 2px 7px !important; - background: $gray-l2; + background: newstyles.$gray-l2; border-radius: 10px; white-space: nowrap; max-width: 130px; @@ -134,7 +134,7 @@ border-radius: 20px; font-size: 10px; width: 100%; - background: $blue-l1; + background: newstyles.$blue-l1; border-radius: 0; padding: 10px; @@ -145,7 +145,7 @@ gap: 3px; .concept { padding: 2px 7px !important; - background: $gray-l2; + background: newstyles.$gray-l2; } } } @@ -154,7 +154,7 @@ grid-row: 5; grid-column: 2; border-radius: 20px; - font-size: $body-size; + font-size: newstyles.$body-size; display: flex; align-items: center; margin-top: 5px; @@ -162,15 +162,15 @@ justify-content: flex-end; text-transform: underline; } - + &.dark { - background: $black; - border-color: $white; + background: newstyles.$black; + border-color: newstyles.$white; } - + &.light, &.default { - background: $white; - border-color: $white; + background: newstyles.$white; + border-color: newstyles.$white; } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/components/SkeletonDoc/SkeletonDoc.scss b/src/client/views/newlightbox/components/SkeletonDoc/SkeletonDoc.scss index e541e3f3c..bbc730144 100644 --- a/src/client/views/newlightbox/components/SkeletonDoc/SkeletonDoc.scss +++ b/src/client/views/newlightbox/components/SkeletonDoc/SkeletonDoc.scss @@ -1,82 +1,81 @@ -@import '../../NewLightboxStyles.scss'; +@use '../../NewLightboxStyles.scss' as newstyles; .skeletonDoc-container { - display: flex; - flex-direction: column; - height: calc(100% - 40px); - margin: 20px; - gap: 20px; + display: flex; + flex-direction: column; + height: calc(100% - 40px); + margin: 20px; + gap: 20px; - .header { - width: calc(100% - 20px); - height: 80px; - background: $gray-l2; - animation: skeleton-loading-l2 1s linear infinite alternate; - display: grid; - grid-template-rows: 60% 40%; - padding: 10px; - grid-template-columns: auto auto auto auto; - border-radius: 20px; + .header { + width: calc(100% - 20px); + height: 80px; + background: newstyles.$gray-l2; + animation: skeleton-loading-l2 1s linear infinite alternate; + display: grid; + grid-template-rows: 60% 40%; + padding: 10px; + grid-template-columns: auto auto auto auto; + border-radius: 20px; - .title { - grid-row: 1; - grid-column: 1 / 5; - display: flex; - width: fit-content; - height: 100%; - min-width: 500px; - font-size: $title-size; - animation: skeleton-loading-l3 1s linear infinite alternate; - border-radius: 20px; - } + .title { + grid-row: 1; + grid-column: 1 / 5; + display: flex; + width: fit-content; + height: 100%; + min-width: 500px; + font-size: newstyles.$title-size; + animation: skeleton-loading-l3 1s linear infinite alternate; + border-radius: 20px; + } - .type { - display: flex; - padding: 3px 7px; - width: fit-content; - height: fit-content; - margin-top: 8px; - min-height: 15px; - min-width: 60px; - grid-row: 2; - grid-column: 1; - animation: skeleton-loading-l3 1s linear infinite alternate; - border-radius: 20px; - } + .type { + display: flex; + padding: 3px 7px; + width: fit-content; + height: fit-content; + margin-top: 8px; + min-height: 15px; + min-width: 60px; + grid-row: 2; + grid-column: 1; + animation: skeleton-loading-l3 1s linear infinite alternate; + border-radius: 20px; + } - .buttons-container { - grid-row: 1 / 3; - grid-column: 5; - display: flex; - justify-content: flex-end; - align-items: center; - gap: 10px; + .buttons-container { + grid-row: 1 / 3; + grid-column: 5; + display: flex; + justify-content: flex-end; + align-items: center; + gap: 10px; - .button { - width: 50px; - height: 50px; - border-radius: 100%; - animation: skeleton-loading-l3 1s linear infinite alternate; - } + .button { + width: 50px; + height: 50px; + border-radius: 100%; + animation: skeleton-loading-l3 1s linear infinite alternate; + } + } } - } - - .content { - width: 100%; - flex: 1; - -webkit-flex: 1; /* Chrome */ - background: $gray-l2; - animation: skeleton-loading-l2 1s linear infinite alternate; - border-radius: 20px; - } + .content { + width: 100%; + flex: 1; + -webkit-flex: 1; /* Chrome */ + background: newstyles.$gray-l2; + animation: skeleton-loading-l2 1s linear infinite alternate; + border-radius: 20px; + } // &.dark { - // background: $black; + // background: newstyles.$black; // } - + // &.light, // &.default { - // background: $white; + // background: newstyles.$white; // } -} \ No newline at end of file +} diff --git a/src/client/views/newlightbox/components/Template/Template.scss b/src/client/views/newlightbox/components/Template/Template.scss index 5b72ddaf9..c2fb9fba4 100644 --- a/src/client/views/newlightbox/components/Template/Template.scss +++ b/src/client/views/newlightbox/components/Template/Template.scss @@ -1,15 +1,15 @@ -@import '../../NewLightboxStyles.scss'; +@use '../../NewLightboxStyles.scss' as newstyles; .template-container { width: 100vw; height: 100vh; - + &.dark { - background: $black; + background: newstyles.$black; } - + &.light, &.default { - background: $white; + background: newstyles.$white; } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 4337401e3..933a383ea 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .audiobox-container { width: 100%; @@ -19,30 +19,30 @@ .audiobox-dictation { width: 40px; - background: $medium-gray; - color: $dark-gray; + background: global.$medium-gray; + color: global.$dark-gray; display: flex; justify-content: center; align-items: center; &:hover { - color: $black; + color: global.$black; } } .audiobox-start-record { - color: $white; - background: $dark-gray; + color: global.$white; + background: global.$dark-gray; display: flex; align-items: center; justify-content: center; - font-size: $body-text; + font-size: global.$body-text; width: 100%; height: 100%; gap: 5px; &:hover { - background: $black; + background: global.$black; } } @@ -54,11 +54,11 @@ gap: 5px; width: 100%; height: 100%; - background: $dark-gray; + background: global.$dark-gray; color: white; .record-timecode { - font-size: $large-header; + font-size: global.$large-header; } .record-button { @@ -66,7 +66,7 @@ width: 30px; height: 30px; border-radius: 50%; - background: $dark-gray; + background: global.$dark-gray; display: flex; align-items: center; justify-content: center; @@ -76,7 +76,7 @@ } &:hover { - background: $black; + background: global.$black; } } } @@ -87,10 +87,10 @@ display: flex; flex-direction: column; align-items: center; - background: $dark-gray; + background: global.$dark-gray; width: 100%; height: 100%; - color: $white; + color: global.$white; .audiobox-button { margin: 2.5px; @@ -98,7 +98,7 @@ width: 25px; height: 25px; border-radius: 50%; - background: $dark-gray; + background: global.$dark-gray; display: flex; align-items: center; justify-content: center; @@ -108,7 +108,7 @@ } &:hover { - background: $black; + background: global.$black; } } @@ -132,7 +132,7 @@ height: 6px; cursor: pointer; box-shadow: 0; - background: $light-gray; + background: global.$light-gray; border-radius: 3px; } @@ -142,7 +142,7 @@ height: 10px; width: 10px; border-radius: 10px; - background: $medium-blue; + background: global.$medium-blue; cursor: pointer; -webkit-appearance: none; margin-top: -2px; @@ -180,12 +180,12 @@ .audiobox-playback { width: 100%; height: 100%; - background: $white; + background: global.$white; .audiobox-timeline { height: calc(100% - 50px); width: 100%; - background: $white; + background: global.$white; position: absolute; } @@ -203,7 +203,7 @@ width: 100%; height: 20px; padding: 3px; - font-size: $small-text; + font-size: global.$small-text; .bottom-controls-middle { display: flex; diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss index 0eb27b65b..ff1fa343d 100644 --- a/src/client/views/nodes/DataVizBox/components/Chart.scss +++ b/src/client/views/nodes/DataVizBox/components/Chart.scss @@ -1,4 +1,4 @@ -@import '../../../global/globalCssVariables.module.scss'; +@use '../../../global/globalCssVariables.module.scss' as global; .chart-container { display: flex; flex-direction: column; @@ -108,7 +108,7 @@ } } tr td { - height: $DATA_VIZ_TABLE_ROW_HEIGHT !important; // bcz: hack. you can't set a height directly, but you can set the height of all of it's s. So this is the height of a tableBox row. + height: global.$DATA_VIZ_TABLE_ROW_HEIGHT !important; // bcz: hack. you can't set a height directly, but you can set the height of all of it's s. So this is the height of a tableBox row. padding: 0 !important; vertical-align: middle !important; } @@ -135,7 +135,7 @@ } .tableBox-filterPopup { - background: $light-gray; + background: global.$light-gray; position: absolute; min-width: 235px; top: 60px; @@ -152,7 +152,7 @@ .tableBox-filterPopup-selectColumn-each { margin-left: 25px; border-radius: 3px; - background: $light-gray; + background: global.$light-gray; } } .tableBox-filterPopup-setValue { @@ -162,7 +162,7 @@ .tableBox-filterPopup-setValue-each { margin-right: 5px; border-radius: 3px; - background: $light-gray; + background: global.$light-gray; } .tableBox-filterPopup-setValue-input { margin: 5px; diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index b32b27e65..e1b83dc59 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .documentLinksButton-wrapper { transform-origin: top left; @@ -29,7 +29,7 @@ pointer-events: auto; display: flex; align-items: center; - background-color: $light-blue; + background-color: global.$light-blue; color: black; } .documentLinksButton, @@ -59,30 +59,30 @@ } } .documentLinksButton { - background-color: $dark-gray; - color: $white; + background-color: global.$dark-gray; + color: global.$white; font-weight: bold; font-size: 100%; font-family: 'Roboto'; transition: 0.2s ease all; &:hover { - background-color: $black; + background-color: global.$black; } } .documentLinksButton.startLink { - background-color: $medium-blue; + background-color: global.$medium-blue; width: 75%; height: 75%; - color: $white; + color: global.$white; font-weight: bold; font-size: 100%; transition: 0.2s ease all; } .documentLinksButton-endLink { - border: $medium-blue 2px dashed; - color: $medium-blue; + border: global.$medium-blue 2px dashed; + color: global.$medium-blue; background-color: none !important; font-size: 100%; transition: 0.2s ease all; diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 7e5507586..294af4d96 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .documentView-effectsWrapper { border-radius: inherit; @@ -28,7 +28,7 @@ // overflow: hidden; // need this so that title will be clipped when borderRadius is set // transition: outline 0.3s linear; - // background: $white; //overflow: hidden; + // background: global.$white; //overflow: hidden; transform-origin: center; &.minimized { @@ -180,7 +180,7 @@ .documentView-titleWrapper, .documentView-titleWrapper-hover { - color: $black; + color: global.$black; transform-origin: top left; top: 0; width: 100%; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 441d6053f..b40ead03a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -778,7 +778,7 @@ export class DocumentViewInternal extends DocComponent {this._props.DocumentView?.() ? : null}
diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss index 55e0f5184..bcbb44e68 100644 --- a/src/client/views/nodes/EquationBox.scss +++ b/src/client/views/nodes/EquationBox.scss @@ -1,5 +1,3 @@ -@import '../global/globalCssVariables.module.scss'; - .equationBox-cont { transform-origin: center; width: fit-content; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.scss b/src/client/views/nodes/FontIconBox/FontIconBox.scss index 2405889cf..186d24e92 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox/FontIconBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; // bcz: something's messed up with the IconButton css. this mostly fixes the fit-all button, the color buttons, the undo +/- expander and the dropdown doc type list (eg 'text') .iconButton-container { @@ -23,7 +23,7 @@ justify-content: center; align-items: center; font-size: 80%; - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; transition: 0.15s; .menuButton-wrap { @@ -34,7 +34,7 @@ } .fontIconBox-label { - color: $white; + color: global.$white; bottom: -1; position: absolute; text-align: center; @@ -124,17 +124,17 @@ width: 21px; left: 2px; bottom: 2px; - background-color: $white; + background-color: global.$white; -webkit-transition: 0.4s; transition: 0.4s; } input:checked + .slider { - background-color: $medium-blue; + background-color: global.$medium-blue; } input:focus + .slider { - box-shadow: 0 0 1px $medium-blue; + box-shadow: 0 0 1px global.$medium-blue; } input:checked + .slider:before { @@ -145,11 +145,11 @@ /* Rounded sliders */ .slider.round { - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; } .slider.round:before { - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; } } @@ -259,12 +259,12 @@ height: fit-content; top: 100%; z-index: 21; - background-color: $white; + background-color: global.$white; box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); padding: 1px; .list-item { - color: $black; + color: global.$black; width: 100%; height: 25px; font-weight: 400; @@ -285,7 +285,7 @@ background: transparent; &.slider { - color: $white; + color: global.$white; cursor: pointer; flex-direction: column; background: transparent; @@ -302,7 +302,7 @@ z-index: 21; background-color: #e3e3e3; box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; .menu-slider { height: 10px; @@ -340,7 +340,7 @@ border: none; text-align: right; width: 100%; - color: $white; + color: global.$white; height: 100%; text-align: center; } @@ -354,7 +354,7 @@ &.list { width: 100%; justify-content: space-around; - border: $standard-border; + border: global.$standard-border; .menuButton-dropdownList { position: absolute; @@ -365,12 +365,12 @@ overflow-y: scroll; top: 100%; z-index: 21; - background-color: $white; + background-color: global.$white; box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); padding: 1px; .list-item { - color: $black; + color: global.$black; width: 100%; height: 25px; font-weight: 400; @@ -394,7 +394,7 @@ padding-left: 10px; justify-content: flex-start; color: black; - background-color: $light-gray; + background-color: global.$light-gray; padding: 5px; padding-left: 10px; width: 100%; @@ -417,7 +417,7 @@ top: 100%; background-color: #e3e3e3; box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); - border-radius: $standard-border-radius; + border-radius: global.$standard-border-radius; } } diff --git a/src/client/views/nodes/IconTagBox.scss b/src/client/views/nodes/IconTagBox.scss index c79d662f4..202b0c701 100644 --- a/src/client/views/nodes/IconTagBox.scss +++ b/src/client/views/nodes/IconTagBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .card-button-container { display: flex; @@ -18,7 +18,7 @@ margin: auto; padding: 0; border-radius: 50%; - background-color: $dark-gray; + background-color: global.$dark-gray; background-color: transparent; } } diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index a44f614b2..441fceba4 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -1,11 +1,11 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .keyValueBox-cont { overflow-y: scroll; width: 100%; height: 100%; - background-color: $white; - border: 1px solid $medium-gray; - border-radius: $border-radius; + background-color: global.$white; + border: 1px solid global.$medium-gray; + border-radius: global.$border-radius; box-sizing: border-box; display: inline-block; cursor: default; @@ -56,8 +56,8 @@ $header-height: 30px; width: 100%; position: relative; display: inline-block; - background: $medium-gray; - color: $white; + background: global.$medium-gray; + color: global.$white; text-transform: uppercase; letter-spacing: 2px; font-size: 12px; @@ -66,7 +66,7 @@ $header-height: 30px; th { font-weight: normal; &:first-child { - border-right: 1px solid $white; + border-right: 1px solid global.$white; } } } @@ -76,9 +76,9 @@ $header-height: 30px; display: flex; width: 100%; height: $header-height; - background: $white; + background: global.$white; .formattedTextBox-cont { - background: $white; + background: global.$white; } } .keyValueBox-cont { @@ -116,8 +116,8 @@ $header-height: 30px; display: flex; width: 100%; height: 30px; - background: $light-gray; + background: global.$light-gray; .formattedTextBox-cont { - background: $light-gray; + background: global.$light-gray; } } diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index 46ea9c18e..913ab641c 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .keyValuePair-td-key { display: inline-block; diff --git a/src/client/views/nodes/LinkDescriptionPopup.scss b/src/client/views/nodes/LinkDescriptionPopup.scss index 104301656..b44b69af5 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.scss +++ b/src/client/views/nodes/LinkDescriptionPopup.scss @@ -1,12 +1,12 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .linkDescriptionPopup { display: flex; flex-direction: row; justify-content: center; align-items: center; - border: 2px solid $medium-blue; - background-color: $white; + border: 2px solid global.$medium-blue; + background-color: global.$white; width: auto; position: absolute; @@ -35,7 +35,7 @@ white-space: nowrap; padding: 5px; vertical-align: middle; - background-color: $close-red; + background-color: global.$close-red; border-radius: 3px; color: black; } @@ -46,7 +46,7 @@ white-space: nowrap; padding: 5px; vertical-align: middle; - background-color: $light-blue; + background-color: global.$light-blue; border-radius: 3px; color: black; } diff --git a/src/client/views/nodes/MapBox/AnimationUtility.ts b/src/client/views/nodes/MapBox/AnimationUtility.ts index f4bae66bb..3eac50f1f 100644 --- a/src/client/views/nodes/MapBox/AnimationUtility.ts +++ b/src/client/views/nodes/MapBox/AnimationUtility.ts @@ -65,7 +65,7 @@ export class AnimationUtility { const coords: mapboxgl.LngLatLike = [this.previousLngLat.lng, this.previousLngLat.lat]; // console.log('MAP REF: ', this.MAP_REF) // console.log("current elevation: ", this.MAP_REF?.queryTerrainElevation(coords)); - let altitude = this.MAP_REF ? this.MAP_REF.queryTerrainElevation(coords) ?? 0 : 0; + let altitude = this.MAP_REF ? (this.MAP_REF.queryTerrainElevation(coords) ?? 0) : 0; if (altitude === 0) { altitude += 50; } @@ -178,7 +178,7 @@ export class AnimationUtility { this.ROUTE_COORDINATES = routeCoordinates; this.PATH = turf.lineString(routeCoordinates); - this.PATH_DISTANCE = turf.lineDistance(this.PATH); + this.PATH_DISTANCE = turf.length(this.PATH); this.terrainDisplayed = terrainDisplayed; const bearing = this.calculateBearing( diff --git a/src/client/views/nodes/MapBox/MapBox.scss b/src/client/views/nodes/MapBox/MapBox.scss index 25b4587a5..fdd8a29d7 100644 --- a/src/client/views/nodes/MapBox/MapBox.scss +++ b/src/client/views/nodes/MapBox/MapBox.scss @@ -1,4 +1,6 @@ -@import '../../global/globalCssVariables.module.scss'; +@use 'sass:color'; +@use '../../global/globalCssVariables.module.scss' as global; + .mapBox { width: 100%; height: 100%; @@ -25,14 +27,6 @@ gap: 5px; align-items: center; width: calc(100% - 40px); - - // .editableText-container { - // width: 100%; - // font-size: 16px !important; - // } - // input { - // width: 100%; - // } } .mapbox-settings-panel { @@ -83,7 +77,7 @@ width: 100%; padding: 10px; &:hover { - background-color: lighten(rgb(187, 187, 187), 10%); + background-color: color.adjust(rgb(187, 187, 187), $lightness: 10%); } } } @@ -167,7 +161,7 @@ pointer-events: all; z-index: 1; // so it appears on top of the document's title, if shown - box-shadow: $standard-box-shadow; + box-shadow: global.$standard-box-shadow; transition: 0.2s; &:hover { diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index f6908d5fd..f2160feb7 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .pdfBox, .pdfBox-interactive { @@ -22,11 +22,11 @@ // glr: This should really be the same component as text and PDFs .pdfBox-sidebarBtn { - background: $black; + background: global.$black; height: 25px; width: 25px; right: 5px; - color: $white; + color: global.$white; display: flex; position: absolute; align-items: center; @@ -35,7 +35,7 @@ pointer-events: all; z-index: 1; // so it appears on top of the document's title, if shown - box-shadow: $standard-box-shadow; + box-shadow: global.$standard-box-shadow; transition: 0.2s; &:hover { diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index 460155446..b5405f0fb 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .mini-viewer { cursor: grab; @@ -22,7 +22,7 @@ height: 100%; border-radius: inherit; opacity: 0.99; // hack! overcomes some kind of Chrome weirdness where buttons (e.g., snapshot) disappear at some point as the video is resized larger - background: $dark-gray; + background: global.$dark-gray; } .inkingCanvas-paths-markers { @@ -93,7 +93,7 @@ align-items: center; justify-content: center; display: flex; - background-color: $dark-gray; + background-color: global.$dark-gray; color: white; border-radius: 100px; height: 40px; @@ -128,13 +128,13 @@ width: 25px; height: 25px; border-radius: 50%; - background: $dark-gray; + background: global.$dark-gray; display: flex; align-items: center; justify-content: center; &:hover { - background: $black; + background: global.$black; } svg { @@ -157,7 +157,7 @@ cursor: pointer; &:hover { - background-color: $medium-gray; + background-color: global.$medium-gray; } } @@ -198,7 +198,7 @@ input[type='range']::-webkit-slider-runnable-track { height: 10px; cursor: pointer; box-shadow: 0; - background: $light-gray; + background: global.$light-gray; border-radius: 10px; } @@ -208,7 +208,7 @@ input[type='range']::-webkit-slider-thumb { height: 12px; width: 12px; border-radius: 10px; - background: $medium-blue; + background: global.$medium-blue; cursor: pointer; -webkit-appearance: none; margin-top: -1px; diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index a1686adaf..05d5babf9 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -1,4 +1,4 @@ -@import '../global/globalCssVariables.module.scss'; +@use '../global/globalCssVariables.module.scss' as global; .webBox { height: 100%; @@ -120,7 +120,7 @@ pointer-events: all; z-index: 1; // so it appears on top of the document's title, if shown - box-shadow: $standard-box-shadow; + box-shadow: global.$standard-box-shadow; transition: 0.2s; &:hover { diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss index 9cf760a12..3d27fa887 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.scss @@ -1,3 +1,4 @@ +@use 'sass:color'; @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap'); $primary-color: #3f51b5; @@ -68,7 +69,7 @@ $transition: all 0.2s ease-in-out; &:focus { outline: none; border-color: $primary-color; - box-shadow: 0 0 0 2px rgba($primary-color, 0.2); + box-shadow: 0 0 0 2px color.adjust($primary-color, $alpha: -0.8); } &:disabled { @@ -92,11 +93,11 @@ $transition: all 0.2s ease-in-out; transition: $transition; &:hover { - background-color: darken($primary-color, 10%); + background-color: color.adjust($primary-color, $lightness: -10%); } &:disabled { - background-color: lighten($primary-color, 20%); + background-color: color.adjust($primary-color, $lightness: 20%); cursor: not-allowed; } @@ -178,7 +179,7 @@ $transition: all 0.2s ease-in-out; margin-bottom: 16px; &:hover { - background-color: rgba($primary-color, 0.1); + background-color: color.adjust($primary-color, $alpha: -0.9); } } @@ -220,7 +221,7 @@ $transition: all 0.2s ease-in-out; transition: $transition; &:hover { - background-color: rgba($primary-color, 0.2); + background-color: color.adjust($primary-color, $alpha: -0.8); color: #fff; } } diff --git a/src/client/views/nodes/formattedText/DashFieldView.scss b/src/client/views/nodes/formattedText/DashFieldView.scss index d79df4272..78bbb520e 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.scss +++ b/src/client/views/nodes/formattedText/DashFieldView.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; .dashFieldView-active, .dashFieldView { @@ -64,5 +64,5 @@ } .ProseMirror-selectedNode { - outline: solid 1px $light-blue !important; + outline: solid 1px global.$light-blue !important; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 84859b94d..f9de4ab5a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; .ProseMirror { width: 100%; @@ -22,7 +22,7 @@ &.h-left * { display: flex; - justify-content: flex-start; + justify-content: flex-start; } &.h-right * { @@ -32,7 +32,7 @@ &.template * { ::-webkit-scrollbar-track { - background: none; + background: none; } } @@ -64,7 +64,7 @@ audiotag:hover { background: inherit; padding: 0; border-width: 0px; - border-color: $medium-gray; + border-color: global.$medium-gray; box-sizing: border-box; background-color: inherit; border-style: solid; @@ -79,7 +79,6 @@ audiotag:hover { transform-origin: left top; top: 0; left: 0; - } .formattedTextBox-cont { @@ -88,7 +87,7 @@ audiotag:hover { padding: 0; border-width: 0px; border-radius: inherit; - border-color: $medium-gray; + border-color: global.$medium-gray; box-sizing: border-box; background-color: inherit; border-style: solid; @@ -147,13 +146,13 @@ audiotag:hover { font-size: 11px; border-radius: 3px; color: white; - background: $medium-gray; + background: global.$medium-gray; border-radius: 5px; display: flex; justify-content: center; align-items: center; cursor: grabbing; - box-shadow: $standard-box-shadow; + box-shadow: global.$standard-box-shadow; // transition: 0.2s; opacity: 0.3; &:hover { @@ -646,7 +645,7 @@ footnote::before { } @media only screen and (max-width: 1000px) { - @import '../../global/globalCssVariables.module.scss'; + // @import '../../global/globalCssVariables.module.scss'; .ProseMirror { width: 100%; @@ -664,7 +663,7 @@ footnote::before { padding: 0; border-width: 0px; border-radius: inherit; - border-color: $medium-gray; + border-color: global.$medium-gray; box-sizing: border-box; background-color: inherit; border-style: solid; @@ -1074,4 +1073,3 @@ footnote::before { } } } - diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss index d6ed5ebee..fcc816447 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.scss +++ b/src/client/views/nodes/formattedText/RichTextMenu.scss @@ -1,4 +1,4 @@ -@import '../../global/globalCssVariables.module.scss'; +@use '../../global/globalCssVariables.module.scss' as global; .button-dropdown-wrapper { position: relative; @@ -25,7 +25,7 @@ top: 35px; left: 0; background-color: #323232; - color: $light-gray; + color: global.$light-gray; border: 1px solid #4d4d4d; border-radius: 0 6px 6px 6px; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); diff --git a/src/client/views/nodes/imageEditor/ImageEditor.tsx b/src/client/views/nodes/imageEditor/ImageEditor.tsx index 3c0ab3da5..657e689bb 100644 --- a/src/client/views/nodes/imageEditor/ImageEditor.tsx +++ b/src/client/views/nodes/imageEditor/ImageEditor.tsx @@ -610,7 +610,9 @@ const ImageEditor = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addDoc Date: Tue, 25 Feb 2025 22:25:39 -0500 Subject: updated packages and fixed some cimplier warnings. --- package-lock.json | 35 +++++++--------------- package.json | 4 +-- .../components/src/components/Slider/Slider.tsx | 10 +++---- src/client/util/request-image-size.ts | 9 +++--- src/server/DashUploadUtils.ts | 8 ++--- src/typings/index.d.ts | 1 + 6 files changed, 26 insertions(+), 41 deletions(-) (limited to 'src/client/util') diff --git a/package-lock.json b/package-lock.json index bc1baea46..ccd1ad886 100644 --- a/package-lock.json +++ b/package-lock.json @@ -146,7 +146,7 @@ "i": "^0.3.7", "iink-ts": "^2.0.1", "image-data-uri": "^2.0.1", - "image-size": "^1.0.2", + "image-size": "^2.0.0", "image-size-stream": "^1.1.0", "install": "^0.13.0", "is-plain-obj": "^4.1.0", @@ -293,7 +293,7 @@ "@types/cookie-session": "^2.0.48", "@types/d3": "^7.4.3", "@types/dom-mediacapture-record": "^1.0.19", - "@types/dompurify": "^3.2.0", + "@types/dompurify": "^3.0.5", "@types/exif": "^0.6.5", "@types/express": "^5.0.0", "@types/express-session": "^1.17.10", @@ -14551,14 +14551,13 @@ "license": "MIT" }, "node_modules/@types/dompurify": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.2.0.tgz", - "integrity": "sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==", - "deprecated": "This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed.", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", "dev": true, "license": "MIT", "dependencies": { - "dompurify": "*" + "@types/trusted-types": "*" } }, "node_modules/@types/eslint": { @@ -15388,8 +15387,8 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/@types/unist": { "version": "3.0.3", @@ -24004,13 +24003,10 @@ "license": "MIT" }, "node_modules/image-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.0.tgz", - "integrity": "sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.0.tgz", + "integrity": "sha512-HP07n1SpdIXGUL4VotUIOQz66MQOq8g7VN+Yj02YTVowqZScQ5i/JYU0+lkNr2pwt5j4hOpk94/UBV1ZCbS2fA==", "license": "MIT", - "dependencies": { - "queue": "6.0.2" - }, "bin": { "image-size": "bin/image-size.js" }, @@ -32972,15 +32968,6 @@ "node": ">=0.4.x" } }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "license": "MIT", - "dependencies": { - "inherits": "~2.0.3" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", diff --git a/package.json b/package.json index 8cd6945ff..6eb2a5c98 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@types/cookie-session": "^2.0.48", "@types/d3": "^7.4.3", "@types/dom-mediacapture-record": "^1.0.19", - "@types/dompurify": "^3.2.0", + "@types/dompurify": "^3.0.5", "@types/exif": "^0.6.5", "@types/express": "^5.0.0", "@types/express-session": "^1.17.10", @@ -230,7 +230,7 @@ "i": "^0.3.7", "iink-ts": "^2.0.1", "image-data-uri": "^2.0.1", - "image-size": "^1.0.2", + "image-size": "^2.0.0", "image-size-stream": "^1.1.0", "install": "^0.13.0", "is-plain-obj": "^4.1.0", diff --git a/packages/components/src/components/Slider/Slider.tsx b/packages/components/src/components/Slider/Slider.tsx index f6f53799c..5af945383 100644 --- a/packages/components/src/components/Slider/Slider.tsx +++ b/packages/components/src/components/Slider/Slider.tsx @@ -122,11 +122,11 @@ export const Slider = (props: ISliderProps) => { setEndNumber?.((lastEndVal = Math.max(number + (minDiff ?? 0), val))); setEndNumberLoc((lastEndVal = Math.max(number + (minDiff ?? 0), val))); }; - const Slider: (JSX.Element | null)[] = [!multithumb ? null : valSlider('end', endNumberLoc, onendchange, () => setFinalEndNumber?.(lastEndVal)), valSlider('start', valLoc, onchange, () => setFinalNumber?.(lastVal))]; + const ValSlider: (JSX.Element | null)[] = [!multithumb ? null : valSlider('end', endNumberLoc, onendchange, () => setFinalEndNumber?.(lastEndVal)), valSlider('start', valLoc, onchange, () => setFinalNumber?.(lastVal))]; - const slider: JSX.Element = ( + const slider = (
{ lastVal = valLoc; lastEndVal = endNumberLoc; @@ -143,7 +143,7 @@ export const Slider = (props: ISliderProps) => { }} style={{ height: getHeight(+(height || 0), size) }} onPointerDown={onPointerDown}> - {Slider} + {ValSlider}
{ return formLabel ? (
-
+
{formLabel}
{slider} diff --git a/src/client/util/request-image-size.ts b/src/client/util/request-image-size.ts index c619192ed..32ab23618 100644 --- a/src/client/util/request-image-size.ts +++ b/src/client/util/request-image-size.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ /** * request-image-size: Detect image dimensions via request. * Licensed under the MIT license. @@ -11,12 +10,11 @@ */ // const imageSize = require('image-size'); -const HttpError = require('standard-http-error'); +import * as HttpError from 'standard-http-error'; import * as request from 'request'; import { imageSize } from 'image-size'; import { ISizeCalculationResult } from 'image-size/dist/types/interface'; - -module.exports = function requestImageSize(url: string) { +export function requestImageSize(url: string): Promise { if (!url) { return Promise.reject(new Error('You should provide an URI string or a "request" options object.')); } @@ -60,4 +58,5 @@ module.exports = function requestImageSize(url: string) { req.on('error', reject); }); -}; +} +export default requestImageSize; diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 2177c5d97..a2747257a 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -23,6 +23,7 @@ import { AcceptableMedia, Upload } from './SharedMediaTypes'; import { Directory, clientPathToFile, filesDirectory, pathToDirectory, publicDirectory, serverPathToFile } from './SocketData'; import { resolvedServerUrl } from './server_Initialization'; import { Worker, isMainThread, parentPort } from 'worker_threads'; +import requestImageSize from '../client/util/request-image-size'; // Create an array to store worker threads enum workertasks { @@ -62,9 +63,6 @@ if (isMainThread) { } } -// eslint-disable-next-line @typescript-eslint/no-require-imports -const requestImageSize = require('../client/util/request-image-size'); - export enum SizeSuffix { Small = '_s', Medium = '_m', @@ -349,14 +347,14 @@ export namespace DashUploadUtils { imgReadStream.push(null); await Promise.all( sizes.map(({ suffix }) => - new Promise(res => + new Promise(res => imgReadStream.pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res) ) )); // prettier-ignore } else { await Promise.all( sizes.map(({ suffix }) => - new Promise(res => + new Promise(res => request.get(imgSourcePath).pipe(createWriteStream(writtenFiles[suffix] = InjectSize(outputPath, suffix))).on('close', res) ) )); // prettier-ignore diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index bee79a38d..dbfabed51 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -13,6 +13,7 @@ declare module 'iink-js'; declare module 'pdfjs-dist/web/pdf_viewer'; declare module 'react-jsx-parser'; declare module 'type_decls.d'; +declare module 'standard-http-error'; declare module '@react-pdf/renderer' { import * as React from 'react'; -- cgit v1.2.3-70-g09d2 From 964230a71ce9c2d1171257037592fe40bbbcdc7b Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 25 Feb 2025 22:50:00 -0500 Subject: more compile fixes. --- package-lock.json | 56 +++++++++++++-------------- package.json | 2 +- src/client/util/History.ts | 21 +++++----- src/client/views/nodes/chatbot/types/types.ts | 6 +-- 4 files changed, 37 insertions(+), 48 deletions(-) (limited to 'src/client/util') diff --git a/package-lock.json b/package-lock.json index c935fef59..68611f50a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -201,7 +201,7 @@ "prosemirror-view": "^1.32.5", "pug": "^3.0.2", "puppeteer": "^24.1.1", - "query-string": "^7.1.3", + "query-string": "^9.1.1", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.2", "rc-switch": "^4.1.0", @@ -19675,12 +19675,12 @@ } }, "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">=14.16" } }, "node_modules/decompress-response": { @@ -21778,12 +21778,15 @@ } }, "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/finalhandler": { @@ -32943,18 +32946,17 @@ } }, "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.1.1.tgz", + "integrity": "sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==", "license": "MIT", "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -36165,12 +36167,15 @@ "license": "BDS-3-Clause" }, "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/split-skip": { @@ -36381,15 +36386,6 @@ "bare-events": "^2.2.0" } }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index a2e87f67f..a090ab9b2 100644 --- a/package.json +++ b/package.json @@ -285,7 +285,7 @@ "prosemirror-view": "^1.32.5", "pug": "^3.0.2", "puppeteer": "^24.1.1", - "query-string": "^7.1.3", + "query-string": "^9.1.1", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.2", "rc-switch": "^4.1.0", diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 0d0c056a4..cf156014d 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,10 +1,7 @@ /* eslint-disable no-use-before-define */ /* eslint-disable no-empty */ -/* eslint-disable no-continue */ -/* eslint-disable guard-for-in */ -/* eslint-disable no-restricted-syntax */ /* eslint-disable no-param-reassign */ -import * as qs from 'query-string'; +import queryString from 'query-string'; import { Doc } from '../../fields/Doc'; import { OmitKeys, ClientUtils } from '../../ClientUtils'; import { DocServer } from '../DocServer'; @@ -82,7 +79,7 @@ export namespace HistoryUtil { // } // } - const parsers: { [type: string]: (pathname: string[], opts: qs.ParsedQuery) => ParsedUrl | undefined } = {}; + const parsers: { [type: string]: (pathname: string[], opts: queryString.ParsedQuery) => ParsedUrl | undefined } = {}; const stringifiers: { [type: string]: (state: ParsedUrl) => string } = {}; type ParserValue = true | 'none' | 'json' | ((value: string) => string | null | (string | null)[]); @@ -91,8 +88,8 @@ export namespace HistoryUtil { [key: string]: ParserValue; }; - function addParser(type: string, requiredFields: Parser, optionalFields: Parser, customParser?: (pathname: string[], opts: qs.ParsedQuery, current: ParsedUrl) => ParsedUrl | null | undefined) { - function parse(parser: ParserValue, value: string | (string | null)[] | null | undefined) { + function addParser(type: string, requiredFields: Parser, optionalFields: Parser, customParser?: (pathname: string[], opts: queryString.ParsedQuery, current: ParsedUrl) => ParsedUrl | null | undefined) { + function parseValue(parser: ParserValue, value: string | (string | null)[] | null | undefined) { if (value === undefined || value === null) { return value; } @@ -112,7 +109,7 @@ export namespace HistoryUtil { return undefined; } const parser = requiredFields[required]; - const value = parse(parser, opts[required]); + const value = parseValue(parser, opts[required]); if (value !== null && value !== undefined) { current[required] = value; } @@ -122,7 +119,7 @@ export namespace HistoryUtil { continue; } const parser = optionalFields[opt]; - const value = parse(parser, opts[opt]); + const value = parseValue(parser, opts[opt]); if (value !== undefined) { current[opt] = value; } @@ -152,8 +149,8 @@ export namespace HistoryUtil { Object.keys(queryObj).forEach(key => { query[key] = queryObj[key] === null ? null : JSON.stringify(queryObj[key]); }); - const queryString = qs.stringify(query); - return path + (queryString ? `?${queryString}` : ''); + const qstr = queryString.stringify(query); + return path + (queryString ? `?${qstr}` : ''); }; } @@ -170,7 +167,7 @@ export namespace HistoryUtil { export function parseUrl(location: Location | URL): ParsedUrl | undefined { const pathname = location.pathname.substring(1); const { search } = location; - const opts = search.length ? qs.parse(search, { sort: false }) : {}; + const opts = search.length ? queryString.parse(search, { sort: false }) : {}; const pathnameSplit = pathname.split('/'); const type = pathnameSplit[0]; diff --git a/src/client/views/nodes/chatbot/types/types.ts b/src/client/views/nodes/chatbot/types/types.ts index 995ac531d..882e74ebb 100644 --- a/src/client/views/nodes/chatbot/types/types.ts +++ b/src/client/views/nodes/chatbot/types/types.ts @@ -1,6 +1,3 @@ -import { indexes } from 'd3'; -import { AnyLayer } from 'react-map-gl'; - export enum ASSISTANT_ROLE { USER = 'user', ASSISTANT = 'assistant', @@ -122,9 +119,8 @@ export interface AI_Document { type: string; } +export type Observation = { type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } }; export interface AgentMessage { role: 'system' | 'user' | 'assistant'; content: string | Observation[]; } - -export type Observation = { type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } }; -- cgit v1.2.3-70-g09d2 From 4989f9489e126b7cea4946b5519987804ba46f96 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Feb 2025 11:29:47 -0500 Subject: removed query-string from project --- package-lock.json | 51 -------------- package.json | 1 - src/client/util/History.ts | 23 +++---- src/server/apis/google/GoogleApiServerUtils.ts | 93 +++++++++++++------------- 4 files changed, 56 insertions(+), 112 deletions(-) (limited to 'src/client/util') diff --git a/package-lock.json b/package-lock.json index 68611f50a..79e81128b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -201,7 +201,6 @@ "prosemirror-view": "^1.32.5", "pug": "^3.0.2", "puppeteer": "^24.1.1", - "query-string": "^9.1.1", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.2", "rc-switch": "^4.1.0", @@ -19674,15 +19673,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/decode-uri-component": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", - "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", - "license": "MIT", - "engines": { - "node": ">=14.16" - } - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -21777,18 +21767,6 @@ "node": ">=8" } }, - "node_modules/filter-obj": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", - "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -32945,23 +32923,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/query-string": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.1.1.tgz", - "integrity": "sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==", - "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.4.1", - "filter-obj": "^5.1.0", - "split-on-first": "^3.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -36166,18 +36127,6 @@ "integrity": "sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==", "license": "BDS-3-Clause" }, - "node_modules/split-on-first": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", - "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/split-skip": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz", diff --git a/package.json b/package.json index a090ab9b2..5d036156f 100644 --- a/package.json +++ b/package.json @@ -285,7 +285,6 @@ "prosemirror-view": "^1.32.5", "pug": "^3.0.2", "puppeteer": "^24.1.1", - "query-string": "^9.1.1", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.2", "rc-switch": "^4.1.0", diff --git a/src/client/util/History.ts b/src/client/util/History.ts index cf156014d..9728e3177 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,7 +1,6 @@ /* eslint-disable no-use-before-define */ /* eslint-disable no-empty */ /* eslint-disable no-param-reassign */ -import queryString from 'query-string'; import { Doc } from '../../fields/Doc'; import { OmitKeys, ClientUtils } from '../../ClientUtils'; import { DocServer } from '../DocServer'; @@ -79,7 +78,7 @@ export namespace HistoryUtil { // } // } - const parsers: { [type: string]: (pathname: string[], opts: queryString.ParsedQuery) => ParsedUrl | undefined } = {}; + const parsers: { [type: string]: (pathname: string[], opts: URLSearchParams) => ParsedUrl | undefined } = {}; const stringifiers: { [type: string]: (state: ParsedUrl) => string } = {}; type ParserValue = true | 'none' | 'json' | ((value: string) => string | null | (string | null)[]); @@ -88,7 +87,7 @@ export namespace HistoryUtil { [key: string]: ParserValue; }; - function addParser(type: string, requiredFields: Parser, optionalFields: Parser, customParser?: (pathname: string[], opts: queryString.ParsedQuery, current: ParsedUrl) => ParsedUrl | null | undefined) { + function addParser(type: string, requiredFields: Parser, optionalFields: Parser, customParser?: (pathname: string[], opts: URLSearchParams, current: ParsedUrl) => ParsedUrl | null | undefined) { function parseValue(parser: ParserValue, value: string | (string | null)[] | null | undefined) { if (value === undefined || value === null) { return value; @@ -105,21 +104,21 @@ export namespace HistoryUtil { parsers[type] = (pathname, opts) => { const current: DocUrl & { [key: string]: null | (string | null)[] | string } = { type: 'doc', docId: '' }; for (const required in requiredFields) { - if (!(required in opts)) { + if (!opts.has(required)) { return undefined; } const parser = requiredFields[required]; - const value = parseValue(parser, opts[required]); + const value = parseValue(parser, opts.get(required)); if (value !== null && value !== undefined) { current[required] = value; } } for (const opt in optionalFields) { - if (!(opt in opts)) { + if (!opts.has(opt)) { continue; } const parser = optionalFields[opt]; - const value = parseValue(parser, opts[opt]); + const value = parseValue(parser, opts.get(opt)); if (value !== undefined) { current[opt] = value; } @@ -145,12 +144,12 @@ export namespace HistoryUtil { path = customStringifier(state, path); } const queryObj = OmitKeys(state, keys).extract; - const query: { [key: string]: string | null } = {}; + const query = new URLSearchParams(); Object.keys(queryObj).forEach(key => { - query[key] = queryObj[key] === null ? null : JSON.stringify(queryObj[key]); + query.set(key, queryObj[key] === null ? '' : JSON.stringify(queryObj[key])); }); - const qstr = queryString.stringify(query); - return path + (queryString ? `?${qstr}` : ''); + const qstr = query.toString(); + return path + (qstr ? `?${qstr}` : ''); }; } @@ -167,7 +166,7 @@ export namespace HistoryUtil { export function parseUrl(location: Location | URL): ParsedUrl | undefined { const pathname = location.pathname.substring(1); const { search } = location; - const opts = search.length ? queryString.parse(search, { sort: false }) : {}; + const opts = new URLSearchParams(search); const pathnameSplit = pathname.split('/'); const type = pathnameSplit[0]; diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts index 21c405bee..7373df473 100644 --- a/src/server/apis/google/GoogleApiServerUtils.ts +++ b/src/server/apis/google/GoogleApiServerUtils.ts @@ -1,7 +1,7 @@ +/* eslint-disable no-use-before-define */ import { GaxiosResponse } from 'gaxios'; import { Credentials, OAuth2Client, OAuth2ClientOptions } from 'google-auth-library'; import { google } from 'googleapis'; -import * as qs from 'query-string'; import * as request from 'request-promise'; import { Opt } from '../../../fields/Doc'; import { Database } from '../../database'; @@ -21,7 +21,6 @@ const scope = ['documents.readonly', 'documents', 'presentations', 'presentation * This namespace manages server side authentication for Google API queries, either * from the standard v1 APIs or the Google Photos REST API. */ - export namespace GoogleApiServerUtils { /** * As we expand out to more Google APIs that are accessible from @@ -71,29 +70,29 @@ export namespace GoogleApiServerUtils { /** * A briefer format for the response from a 'googleapis' API request */ - export type ApiResponse = Promise; + export type ApiResponse = Promise>; /** * A generic form for a handler that executes some request on the endpoint */ - export type ApiRouter = (endpoint: Endpoint, parameters: any) => ApiResponse; + export type ApiRouter = (endpoint: Endpoint, parameters: Record) => ApiResponse; /** * A generic form for the asynchronous function that actually submits the - * request to the API and returns the corresporing response. Helpful when + * request to the API and returns the corresponding response. Helpful when * making an extensible endpoint definition. */ - export type ApiHandler = (parameters: any, methodOptions?: any) => ApiResponse; + export type ApiHandler = (parameters: Record, methodOptions?: Record) => ApiResponse; /** * A literal union type indicating the valid actions for these 'googleapis' - * requestions + * requests */ export type Action = 'create' | 'retrieve' | 'update'; /** * An interface defining any entity on which one can invoke - * anuy of the following handlers. All 'googleapis' wrappers + * any of the following handlers. All 'googleapis' wrappers * such as google.docs().documents and google.slides().presentations * satisfy this interface. */ @@ -109,7 +108,7 @@ export namespace GoogleApiServerUtils { * of needless duplicate clients that would arise from * making one new client instance per request. */ - const authenticationClients = new Map(); + const authenticationClients = new Map(); /** * This function receives the target sector ("which G-Suite app's API am I interested in?") @@ -120,23 +119,21 @@ export namespace GoogleApiServerUtils { * @returns the relevant 'googleapis' wrapper, if any */ export async function GetEndpoint(sector: string, userId: string): Promise { - return new Promise(async resolve => { - const auth = await retrieveOAuthClient(userId); - if (!auth) { - return resolve(); - } - let routed: Opt; - const parameters: any = { auth, version: 'v1' }; - switch (sector) { - case Service.Documents: - routed = google.docs(parameters).documents; - break; - case Service.Slides: - routed = google.slides(parameters).presentations; - break; - } - resolve(routed); - }); + const auth = await retrieveOAuthClient(userId); + if (!auth) { + return; + } + let routed: Opt; + const parameters: { version: 'v1' } = { /* auth, */ version: 'v1' }; ///* auth: OAuth2Client;*/ + switch (sector) { + case Service.Documents: + routed = google.docs(parameters).documents; + break; + case Service.Slides: + routed = google.slides(parameters).presentations; + break; + } + return routed; } /** @@ -149,19 +146,17 @@ export namespace GoogleApiServerUtils { * security. */ export async function retrieveOAuthClient(userId: string): Promise { - return new Promise(async resolve => { - const { credentials, refreshed } = await retrieveCredentials(userId); - if (!credentials) { - return resolve(); - } - let client = authenticationClients.get(userId); - if (!client) { - authenticationClients.set(userId, (client = generateClient(credentials))); - } else if (refreshed) { - client.setCredentials(credentials); - } - resolve(client); - }); + const { credentials, refreshed } = await retrieveCredentials(userId); + if (!credentials) { + return; + } + let client = authenticationClients.get(userId); + if (!client) { + authenticationClients.set(userId, (client = generateClient(credentials))); + } else if (refreshed) { + client.setCredentials(credentials); + } + return client; } /** @@ -173,7 +168,9 @@ export namespace GoogleApiServerUtils { */ function generateClient(credentials?: Credentials): OAuth2Client { const client = new google.auth.OAuth2(oAuthOptions); - credentials && client.setCredentials(credentials); + if (credentials) { + client.setCredentials(credentials); + } return client; } @@ -206,7 +203,7 @@ export namespace GoogleApiServerUtils { */ export async function processNewUser(userId: string, authenticationCode: string): Promise { const credentials = await new Promise((resolve, reject) => { - worker.getToken(authenticationCode, async (err, credentials) => { + worker.getToken(authenticationCode, (err, credentials) => { if (err || !credentials) { reject(err); return; @@ -221,7 +218,7 @@ export namespace GoogleApiServerUtils { /** * This type represents the union of the full set of OAuth2 credentials - * and all of a Google user's publically available information. This is the strucure + * and all of a Google user's publicly available information. This is the structure * of the JSON object we ultimately store in the googleAuthentication table of the database. */ export type EnrichedCredentials = Credentials & { userInfo: UserInfo }; @@ -297,15 +294,15 @@ export namespace GoogleApiServerUtils { async function refreshAccessToken(credentials: Credentials, userId: string): Promise { const headerParameters = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }; const { client_id, client_secret } = GoogleCredentialsLoader.ProjectCredentials; - const url = `https://oauth2.googleapis.com/token?${qs.stringify({ - refreshToken: credentials.refresh_token, + const params = new URLSearchParams({ + refresh_token: credentials.refresh_token!, client_id, client_secret, grant_type: 'refresh_token', - })}`; - const { access_token, expires_in } = await new Promise(async resolve => { - const response = await request.post(url, headerParameters); - resolve(JSON.parse(response)); + }); + const url = `https://oauth2.googleapis.com/token?${params.toString()}`; + const { access_token, expires_in } = await new Promise<{ access_token: string; expires_in: number }>(resolve => { + request.post(url, headerParameters).then(response => resolve(JSON.parse(response))); }); // expires_in is in seconds, but we're building the new expiry date in milliseconds const expiry_date = new Date().getTime() + expires_in * 1000; -- cgit v1.2.3-70-g09d2 From 2e03c9bf1af2796faef8b81b326b48f4cd136d95 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Feb 2025 18:31:13 -0500 Subject: fixed toggling number dropdown. Added firefly to gpt popup menu. --- packages/components/src/components/Popup/Popup.tsx | 1 + src/client/Network.ts | 17 ++-- src/client/util/DocumentManager.ts | 5 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 90 ++++++++++++++++------ src/client/views/smartdraw/SmartDrawHandler.tsx | 78 +++++++++++++------ src/server/ApiManagers/FireflyManager.ts | 13 ++-- 7 files changed, 142 insertions(+), 64 deletions(-) (limited to 'src/client/util') diff --git a/packages/components/src/components/Popup/Popup.tsx b/packages/components/src/components/Popup/Popup.tsx index aa732d568..f0920b723 100644 --- a/packages/components/src/components/Popup/Popup.tsx +++ b/packages/components/src/components/Popup/Popup.tsx @@ -71,6 +71,7 @@ export const Popup = (props: IPopupProps) => { if (rect && !(rect.left < e.clientX && rect.top < e.clientY && rect.right > e.clientX && rect.bottom > e.clientY) && !popupContainsPt?.(e.clientX, e.clientY)) { e.preventDefault(); setOpen(false); + e.stopPropagation(); } }; diff --git a/src/client/Network.ts b/src/client/Network.ts index 3b0406141..323a2648c 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -1,5 +1,4 @@ import formidable from 'formidable'; -import * as requestPromise from 'request-promise'; import { ClientUtils } from '../ClientUtils'; import { Utils } from '../Utils'; import { Upload } from '../server/SharedMediaTypes'; @@ -16,13 +15,17 @@ export namespace Networking { } export function PostToServer(relativeRoute: string, body?: unknown) { - const options = { - uri: ClientUtils.prepend(relativeRoute), + return fetch(ClientUtils.prepend(relativeRoute), { method: 'POST', - body, - json: true, - }; - return requestPromise.post(options); + headers: { + 'Content-Type': 'application/json', + }, + body: body ? JSON.stringify(body) : undefined, + }).then(async response => { + if (response.ok) return response.json(); + + return await response.text().then(text => ({ error: '' + response.status + ':' + response.statusText + '-' + text })); + }); } /** diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index acb35f7eb..e33449782 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -354,9 +354,10 @@ export class DocumentManager { // bcz: should this delay be an options parameter? setTimeout(() => { Doc.linkFollowHighlight(viewSpec ? [docView.Document, viewSpec] : docView.Document, undefined, options.effect); - if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && targetDoc.text_html) { + const zoomableText = StrCast(targetDoc.text_html, StrCast(targetDoc.ai_firefly_prompt)); + if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && zoomableText) { // if the docView is a text anchor, the contextView is the PDF/Web/Text doc - contextView.setTextHtmlOverlay(StrCast(targetDoc.text_html), options.effect); + contextView.setTextHtmlOverlay(zoomableText, options.effect); DocumentManager._overlayViews.add(contextView); } Doc.AddUnHighlightWatcher(() => { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 496c3a40a..b6b0e4a8a 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -627,7 +627,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { } else SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput || StrCast(this.Document.title), true).then( action(newImgs => { - if (newImgs[0]) { + if (newImgs[0] && !(newImgs[0] instanceof Doc)) { const url = newImgs[0].pathname; const imgField = new ImageField(url); this._prevImgs.length === 0 && diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 2cf39bec4..efddfb841 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -3,6 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { AiOutlineSend } from 'react-icons/ai'; import { CgCornerUpLeft } from 'react-icons/cg'; import ReactLoading from 'react-loading'; import { TypeAnimation } from 'react-type-animation'; @@ -16,14 +17,15 @@ import { Docs } from '../../../documents/Documents'; import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoable } from '../../../util/UndoManager'; +import { DictationButton } from '../../DictationButton'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { TagItem } from '../../TagsView'; import { ChatSortField, docSortings } from '../../collections/CollectionSubView'; import { DocumentView } from '../../nodes/DocumentView'; +import { SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; import { AnchorMenu } from '../AnchorMenu'; import './GPTPopup.scss'; -import { DictationButton } from '../../DictationButton'; -import { AiOutlineSend } from 'react-icons/ai'; +import { FireflyImageDimensions } from '../../smartdraw/FireflyConstants'; export enum GPTPopupMode { SUMMARY, // summary of seleted document text @@ -32,6 +34,7 @@ export enum GPTPopupMode { GPT_MENU, // menu for choosing type of prompts user will provide USER_PROMPT, // user prompts for sorting,filtering and asking about docs QUIZ_RESPONSE, // user definitions or explanations to be evaluated by GPT + FIREFLY, // firefly image generation } @observer @@ -93,6 +96,7 @@ export class GPTPopup extends ObservableReactComponent { } @observable private _conversationArray: string[] = ['Hi! In this pop up, you can ask ChatGPT questions about your documents and filter / sort them. ']; + @observable private _fireflyArray: string[] = ['Hi! In this pop up, you can ask Firefly to create images. ']; @observable private _chatEnabled: boolean = false; @action private setChatEnabled = (start: boolean) => (this._chatEnabled = start); @observable private _gptProcessing: boolean = false; @@ -197,6 +201,21 @@ export class GPTPopup extends ObservableReactComponent { .catch(err => console.error('GPT call failed', err)) )) // prettier-ignore + generateFireflyImage = (imgDesc: string) => { + // if (this._fireflyRefStrength) { + // DrawingFillHandler.drawingToImage(this.props.Document, this._fireflyRefStrength, this._regenInput || StrCast(this.Document.title), this.Document)?.then( + // action(() => { + // this._regenerateLoading = false; + // }) + // ); + // } else∂ + return SmartDrawHandler.CreateWithFirefly(imgDesc, FireflyImageDimensions.Square, 0) + .then(action(() => (this._userPrompt = ''))) + .catch(e => { + alert(e); + return undefined; + }); + }; /** * Generates a response to the user's question about the docs in the collection. * The type of response depends on the chat's analysis of the type of their question @@ -338,6 +357,21 @@ export class GPTPopup extends ObservableReactComponent { gptMenu = () => (
+
); - callGpt = (isUserPrompt: boolean) => { + callGpt = action((mode: GPTPopupMode) => { this.setGptProcessing(true); - if (isUserPrompt) { - this._conversationArray.push(this._userPrompt); - return this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = ''))); + switch (mode) { + case GPTPopupMode.FIREFLY: + this._fireflyArray.push(this._userPrompt); + return this.generateFireflyImage(this._userPrompt).then(action(() => (this._userPrompt = ''))); + case GPTPopupMode.USER_PROMPT: + this._conversationArray.push(this._userPrompt); + return this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = ''))); + case GPTPopupMode.QUIZ_RESPONSE: + this._conversationArray.push(this._quizAnswer); + return this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = ''))); } - this._conversationArray.push(this._quizAnswer); - return this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = ''))); - }; + }); @action - handleKeyPress = async (e: React.KeyboardEvent, isUserPrompt: boolean) => { + handleKeyPress = async (e: React.KeyboardEvent, mode: GPTPopupMode) => { this._askDictation?.stopDictation(); if (e.key === 'Enter') { e.stopPropagation(); - this.callGpt(isUserPrompt).then(() => { + this.callGpt(mode)?.then(() => { this.setGptProcessing(false); this.scrollToBottom(); }); @@ -401,7 +440,7 @@ export class GPTPopup extends ObservableReactComponent {
- {this._conversationArray.map((message, index) => ( + {(this._mode === GPTPopupMode.FIREFLY ? this._fireflyArray : this._conversationArray).map((message, index) => (
{message}
@@ -414,21 +453,21 @@ export class GPTPopup extends ObservableReactComponent { ); - promptBox = (isUserPrompt: boolean) => ( + promptBox = (heading: string, value: string, onChange: (e: string) => string, placeholder: string) => ( <>
- {this.heading(isUserPrompt ? 'ASK' : 'QUIZ')} + {this.heading(heading)} {this.gptUserInput()}
(isUserPrompt ? this.setUserPrompt : this.setQuizAnswer)(e.target.value)} - onKeyDown={e => this.handleKeyPress(e, isUserPrompt)} + onChange={e => onChange(e.target.value)} + onKeyDown={e => this.handleKeyPress(e, this._mode)} type="text" - placeholder={`${isUserPrompt ? 'Have ChatGPT sort, tag, define, or filter your documents for you!' : 'Describe/answer the selected document!'}`} + placeholder={placeholder} />
); @@ -461,7 +500,7 @@ export class GPTPopup extends ObservableReactComponent { dalle generation -
+
@@ -599,7 +638,7 @@ export class GPTPopup extends ObservableReactComponent { color={Doc.hasDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag) ? 'red' : 'transparent'} onClick={() => this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', GPTPopup.ChatTag, 'remove')} /> - {(this._mode === GPTPopupMode.USER_PROMPT || this._mode === GPTPopupMode.QUIZ_RESPONSE) && ( + {[GPTPopupMode.USER_PROMPT, GPTPopupMode.QUIZ_RESPONSE, GPTPopupMode.FIREFLY].includes(this._mode) && ( } onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} /> )} @@ -613,8 +652,9 @@ export class GPTPopup extends ObservableReactComponent { {(() => { //prettier-ignore switch (this._mode) { - case GPTPopupMode.USER_PROMPT: - case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox(this._mode === GPTPopupMode.USER_PROMPT); + case GPTPopupMode.USER_PROMPT: return this.promptBox("ASK", this._userPrompt, this.setUserPrompt, 'Ask GPT to sort, tag, define, or filter your documents for you!'); + case GPTPopupMode.FIREFLY: return this.promptBox("CREATE", this._userPrompt, this.setUserPrompt, 'Ask Firefly to generate images'); + case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox("QUIZ", this._quizAnswer, this.setQuizAnswer, 'Describe/answer the selected document!'); case GPTPopupMode.GPT_MENU: return this.menuBox(); case GPTPopupMode.SUMMARY: return this.summaryBox(); case GPTPopupMode.DATA: return this.dataAnalysisBox(); diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index 7db9ef133..9d67d111b 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -1,6 +1,6 @@ +import { Button, IconButton } from '@dash/components'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox, FormControlLabel, Radio, RadioGroup, Slider, Switch } from '@mui/material'; -import { Button, IconButton } from '@dash/components'; import { action, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import React from 'react'; @@ -13,7 +13,9 @@ import { Doc, DocListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { InkData, InkField, InkTool } from '../../../fields/InkField'; import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { Networking } from '../../Network'; import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT'; +import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; import { SettingsManager } from '../../util/SettingsManager'; import { undoable } from '../../util/UndoManager'; @@ -21,12 +23,10 @@ import { SVGToBezier, SVGType } from '../../util/bezierFit'; import { InkingStroke } from '../InkingStroke'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { MarqueeView } from '../collections/collectionFreeForm'; -import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkDash, ActiveInkFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; -import './SmartDrawHandler.scss'; -import { Networking } from '../../Network'; +import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; import { OpenWhere } from '../nodes/OpenWhere'; -import { FireflyDimensionsMap, FireflyImageDimensions, FireflyImageData } from './FireflyConstants'; -import { DocumentType } from '../../documents/DocumentTypes'; +import { FireflyDimensionsMap, FireflyImageData, FireflyImageDimensions } from './FireflyConstants'; +import './SmartDrawHandler.scss'; export interface DrawingOptions { text: string; @@ -268,28 +268,56 @@ export class SmartDrawHandler extends ObservableReactComponent { /** * Calls Firefly API to create an image based on user input */ - createImageWithFirefly = (input: string, seed?: number, changeInPlace?: boolean): Promise => { + createImageWithFirefly = (input: string, seed?: number): Promise => { + this._lastInput.text = input; + return SmartDrawHandler.CreateWithFirefly(input, this._imgDims, seed); + }; /** + * Calls Firefly API to create an image based on user input + */ + recreateImageWithFirefly = (input: string, seed?: number): Promise => { this._lastInput.text = input; - const dims = FireflyDimensionsMap[this._imgDims]; + return SmartDrawHandler.ReCreateWithFirefly(input, this._imgDims, seed); + }; + public static ReCreateWithFirefly(input: string, imgDims: FireflyImageDimensions, seed?: number): Promise { + const dims = FireflyDimensionsMap[imgDims]; return Networking.PostToServer('/queryFireflyImage', { prompt: input, width: dims.width, height: dims.height, seed }) .then(img => { - const newseed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1]; - if (!changeInPlace) { - const imgDoc: Doc = Docs.Create.ImageDocument(img.accessPaths.agnostic.client, { - title: input.match(/^(.*?)~~~.*$/)?.[1] || input, - nativeWidth: dims.width, - nativeHeight: dims.height, - ai: 'firefly', - ai_firefly_seed: newseed, - ai_firefly_prompt: input, - }); - DocumentViewInternal.addDocTabFunc(imgDoc, OpenWhere.addRight); - this._selectedDocs.push(imgDoc); + if (img.error) { + alert('recreate image failed: ' + img.error); + return undefined; } return { prompt: input, seed, pathname: img.accessPaths.agnostic.client }; }) - .catch(e => alert('create image failed: ' + e.toString())); - }; + .catch(e => { + alert('recreate image failed: ' + e.toString()); + return undefined; + }); + } + public static CreateWithFirefly(input: string, imgDims: FireflyImageDimensions, seed?: number): Promise { + const dims = FireflyDimensionsMap[imgDims]; + return Networking.PostToServer('/queryFireflyImage', { prompt: input, width: dims.width, height: dims.height, seed }) + .then(img => { + if (img.error) { + alert('create image failed: ' + img.error); + return undefined; + } + const newseed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1]; + const imgDoc: Doc = Docs.Create.ImageDocument(img.accessPaths.agnostic.client, { + title: input.match(/^(.*?)~~~.*$/)?.[1] || input, + nativeWidth: dims.width, + nativeHeight: dims.height, + ai: 'firefly', + ai_firefly_seed: newseed, + ai_firefly_prompt: input, + }); + DocumentViewInternal.addDocTabFunc(imgDoc, OpenWhere.addRight); + return imgDoc; + }) + .catch(e => { + alert('create image failed: ' + e.toString()); + return undefined; + }); + } /** * Regenerates drawings with the option to add a specific regenerate prompt/request. @@ -307,10 +335,12 @@ export class SmartDrawHandler extends ObservableReactComponent { if (this._regenInput) { // if (this._selectedDoc) { const newPrompt = doc.ai_firefly_prompt ? `${doc.ai_firefly_prompt} ~~~ ${this._regenInput}` : this._regenInput; - return this.createImageWithFirefly(newPrompt, NumCast(doc?.ai_firefly_seed), changeInPlace); + return changeInPlace ? this.recreateImageWithFirefly(newPrompt, NumCast(doc?.ai_firefly_seed)) : this.createImageWithFirefly(newPrompt, NumCast(doc?.ai_firefly_seed)); // } } - return this.createImageWithFirefly(this._lastInput.text || StrCast(doc.ai_firefly_prompt), undefined, changeInPlace); + return changeInPlace + ? this.recreateImageWithFirefly(this._lastInput.text || StrCast(doc.ai_firefly_prompt), NumCast(doc?.ai_firefly_seed)) + : this.createImageWithFirefly(this._lastInput.text || StrCast(doc.ai_firefly_prompt), NumCast(doc?.ai_firefly_seed)); case DocumentType.COL: { try { let res; diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts index 160a94d40..8a310aed8 100644 --- a/src/server/ApiManagers/FireflyManager.ts +++ b/src/server/ApiManagers/FireflyManager.ts @@ -132,7 +132,8 @@ export default class FireflyManager extends ApiManager { ], body: body, }) - .then(response2 => response2.json().then(json => ({ seed: json.outputs?.[0]?.seed, url: json.outputs?.[0]?.image?.url }))) + .then(response2 => response2.json()) + .then(json => (json.error_code ? json : { seed: json.outputs?.[0]?.seed, url: json.outputs?.[0]?.image?.url })) .catch(error => { console.error('Error:', error); return undefined; @@ -332,10 +333,12 @@ export default class FireflyManager extends ApiManager { subscription: '/queryFireflyImage', secureHandler: ({ req, res }) => this.generateImage(req.body.prompt, req.body.width, req.body.height, req.body.seed).then(img => - DashUploadUtils.UploadImage(img?.url ?? '', undefined, img?.seed).then(info => { - if (info instanceof Error) _invalid(res, info.message); - else _success(res, info); - }) + img.error_code + ? _invalid(res, img.message) + : DashUploadUtils.UploadImage(img?.url ?? '', undefined, img?.seed).then(info => { + if (info instanceof Error) _invalid(res, info.message); + else _success(res, info); + }) ), }); -- cgit v1.2.3-70-g09d2 From fa8122df7467af3d4410b7daf1cd75227a53fd96 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Feb 2025 18:43:26 -0500 Subject: ping cleanup --- src/client/util/PingManager.ts | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/PingManager.ts b/src/client/util/PingManager.ts index 255e9cee0..170632836 100644 --- a/src/client/util/PingManager.ts +++ b/src/client/util/PingManager.ts @@ -1,44 +1,37 @@ -import { action, makeObservable, observable, runInAction } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { Networking } from '../Network'; import { SnappingManager } from './SnappingManager'; export class PingManager { + PING_INTERVAL_SECONDS = 1; + // not used now, but may need to clear interval + private _interval: NodeJS.Timeout | null = null; // create static instance and getter for global use // eslint-disable-next-line no-use-before-define - @observable static _instance: PingManager; + @observable private static _instance: PingManager; @observable IsBeating = true; static get Instance(): PingManager { return PingManager._instance; } - // not used now, but may need to clear interval - private _interval: NodeJS.Timeout | null = null; - INTERVAL_SECONDS = 1; constructor() { makeObservable(this); PingManager._instance = this; - this._interval = setInterval(this.sendPing, this.INTERVAL_SECONDS * 1000); + this._interval = setInterval(this.sendPing, this.PING_INTERVAL_SECONDS * 1000); } - private setIsBeating = action((status: boolean) => { - this.IsBeating = status; - setTimeout(this.showAlert, 100); - }); + showAlert = () => alert(PingManager.Instance.IsBeating ? 'The server connection is active' : 'The server connection has been interrupted.NOTE: Any changes made will appear to persist but will be lost after a browser refreshes.'); - showAlert = () => { - alert(PingManager.Instance.IsBeating ? 'The server connection is active' : 'The server connection has been interrupted.NOTE: Any changes made will appear to persist but will be lost after a browser refreshes.'); - }; - sendPing = async (): Promise => { - try { - const res = await Networking.PostToServer('/ping', { date: new Date() }); - runInAction(() => { + sendPing = () => { + const setIsBeating = action((status: boolean) => { + this.IsBeating = status; + setTimeout(this.showAlert, 100); + }); + Networking.PostToServer('/ping', { date: new Date() }) + .then(res => { SnappingManager.SetServerVersion(res.message); - }); - !this.IsBeating && this.setIsBeating(true); - } catch { - if (this.IsBeating) { - this.setIsBeating(false); - } - } + !this.IsBeating && setIsBeating(true); + }) + .catch(() => this.IsBeating && setIsBeating(false)); }; } -- cgit v1.2.3-70-g09d2 From a9a1a6a507616a77f70d6525dab5027f5b7a60e6 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 26 Feb 2025 20:48:51 -0500 Subject: added typing to PostToServer calls. made smartDraw popup create images locally. --- src/client/Network.ts | 2 +- src/client/apis/GoogleAuthenticationManager.tsx | 27 ++++--- .../apis/google_docs/GoogleApiClientUtils.ts | 19 ++--- .../apis/google_docs/GooglePhotosClientUtils.ts | 18 ++--- src/client/util/Import & Export/ImageUtils.ts | 4 +- src/client/util/PingManager.ts | 2 +- src/client/util/SettingsManager.tsx | 3 +- src/client/views/collections/CollectionSubView.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 3 +- src/client/views/nodes/ImageBox.tsx | 20 +++-- .../views/nodes/RecordingBox/RecordingView.tsx | 3 +- .../views/nodes/chatbot/tools/CreateCSVTool.ts | 4 +- .../views/nodes/chatbot/tools/ImageCreationTool.ts | 4 +- src/client/views/nodes/chatbot/tools/RAGTool.ts | 2 +- src/client/views/nodes/chatbot/tools/SearchTool.ts | 8 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 13 ++- src/client/views/smartdraw/FireflyConstants.ts | 5 ++ src/client/views/smartdraw/SmartDrawHandler.tsx | 94 ++++++++++------------ 19 files changed, 123 insertions(+), 116 deletions(-) (limited to 'src/client/util') diff --git a/src/client/Network.ts b/src/client/Network.ts index 323a2648c..a2ecf1bea 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -22,7 +22,7 @@ export namespace Networking { }, body: body ? JSON.stringify(body) : undefined, }).then(async response => { - if (response.ok) return response.json(); + if (response.ok) return response.json() as object; return await response.text().then(text => ({ error: '' + response.status + ':' + response.statusText + '-' + text })); }); diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 5269f763b..94ce42d8d 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -11,7 +11,8 @@ const AuthenticationUrl = 'https://accounts.google.com/o/oauth2/v2/auth'; const prompt = 'Paste authorization code here...'; @observer -export class GoogleAuthenticationManager extends React.Component<{}> { +export class GoogleAuthenticationManager extends React.Component { + // eslint-disable-next-line no-use-before-define public static Instance: GoogleAuthenticationManager; private authenticationLink: Opt = undefined; @observable private openState = false; @@ -19,7 +20,7 @@ export class GoogleAuthenticationManager extends React.Component<{}> { @observable private showPasteTargetState = false; @observable private success: Opt = undefined; @observable private displayLauncher = true; - @observable private credentials: any; + @observable private credentials: { user_info: { name: string; picture: string }; access_token: string } | undefined = undefined; private disposer: Opt; private set isOpen(value: boolean) { @@ -35,25 +36,25 @@ export class GoogleAuthenticationManager extends React.Component<{}> { } public fetchOrGenerateAccessToken = async (displayIfFound = false) => { - let response: any = await Networking.FetchFromServer('/readGoogleAccessToken'); + const response = await Networking.FetchFromServer('/readGoogleAccessToken'); // if this is an authentication url, activate the UI to register the new access token if (new RegExp(AuthenticationUrl).test(response)) { this.isOpen = true; this.authenticationLink = response; - return new Promise(async resolve => { + return new Promise(resolve => { this.disposer?.(); this.disposer = reaction( () => this.authenticationCode, async authenticationCode => { if (authenticationCode && /\d{1}\/[\w-]{55}/.test(authenticationCode)) { this.disposer?.(); - const response = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode }); + const response2 = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode }); runInAction(() => { this.success = true; - this.credentials = response; + this.credentials = response2 as { user_info: { name: string; picture: string }; access_token: string }; }); this.resetState(); - resolve(response.access_token); + resolve((response2 as { access_token: string }).access_token); } } ); @@ -61,16 +62,16 @@ export class GoogleAuthenticationManager extends React.Component<{}> { } // otherwise, we already have a valid, stored access token and user info - response = JSON.parse(response); + const response2 = JSON.parse(response) as { user_info: { name: string; picture: string }; access_token: string }; if (displayIfFound) { runInAction(() => { this.success = true; - this.credentials = response; + this.credentials = response2; }); this.resetState(-1, -1); this.isOpen = true; } - return response.access_token; + return (response2 as { access_token: string }).access_token; }; resetState = action((visibleForMS: number = 3000, fadesOutInMS: number = 500) => { @@ -106,7 +107,7 @@ export class GoogleAuthenticationManager extends React.Component<{}> { } }); - constructor(props: {}) { + constructor(props: object) { super(props); GoogleAuthenticationManager.Instance = this; } @@ -128,8 +129,8 @@ export class GoogleAuthenticationManager extends React.Component<{}> { {this.showPasteTargetState ? (this.authenticationCode = e.currentTarget.value))} placeholder={prompt} /> : null} {this.credentials ? ( <> - - Welcome to Dash, {this.credentials.userInfo.name} + + Welcome to Dash, {this.credentials.user_info.name}
{ diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts index 0b303eacf..c1ac352b1 100644 --- a/src/client/apis/google_docs/GoogleApiClientUtils.ts +++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts @@ -1,7 +1,5 @@ -/* eslint-disable no-restricted-syntax */ /* eslint-disable no-use-before-define */ import { docs_v1 as docsV1 } from 'googleapis'; -// eslint-disable-next-line node/no-deprecated-api import { isArray } from 'util'; import { EditorState } from 'prosemirror-state'; import { Opt } from '../../../fields/Doc'; @@ -37,7 +35,7 @@ export namespace GoogleApiClientUtils { text: string | string[]; requests: docsV1.Schema$Request[]; } - export type IdHandler = (id: DocumentId) => any; + export type IdHandler = (id: DocumentId) => unknown; export type CreationResult = Opt; export type ReadLinesResult = Opt<{ title?: string; bodyLines?: string[] }>; export type ReadResult = { title: string; body: string }; @@ -145,7 +143,7 @@ export namespace GoogleApiClientUtils { if (paragraphs.length) { const target = paragraphs[paragraphs.length - 1]; if (target.paragraph && target.paragraph.elements) { - length = target.paragraph.elements.length; + const length = target.paragraph.elements.length; if (length) { const final = target.paragraph.elements[length - 1]; return final.endIndex ? final.endIndex - 1 : undefined; @@ -208,13 +206,13 @@ export namespace GoogleApiClientUtils { }); export const setStyle = async (options: UpdateOptions) => { - const replies: any = await update({ + const replies = await update({ documentId: options.documentId, requests: options.requests, }); - if ('errors' in replies) { + if (replies && 'errors' in replies) { console.log('Write operation failed:'); - console.log(replies.errors.map((error: any) => error.message)); + console.log(replies); //.errors.map((error: any) => error.message)); } return replies; }; @@ -229,7 +227,6 @@ export namespace GoogleApiClientUtils { const { mode } = options; if (!(index && mode === WriteMode.Insert)) { const schema = await retrieve({ documentId }); - // eslint-disable-next-line no-cond-assign if (!schema || !(index = Utils.endOf(schema))) { return undefined; } @@ -258,10 +255,10 @@ export namespace GoogleApiClientUtils { return undefined; } requests.push(...options.content.requests); - const replies: any = await update({ documentId, requests }); - if ('errors' in replies) { + const replies = await update({ documentId, requests }); + if (replies && 'errors' in replies) { console.log('Write operation failed:'); - console.log(replies.errors.map((error: any) => error.message)); + console.log(replies); // .errors.map((error: any) => error.message)); } return replies; }; diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index b238f07e9..4b86a8341 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import Photos = require('googlephotos'); +import Photos from 'googlephotos'; import { AssertionError } from 'assert'; import { EditorState } from 'prosemirror-state'; import { ClientUtils } from '../../../ClientUtils'; @@ -118,7 +118,7 @@ export namespace GooglePhotos { } export namespace Import { - export type CollectionConstructor = (data: Array, options: DocumentOptions, ...args: any) => Doc; + export type CollectionConstructor = (data: Array, options: DocumentOptions, ...args: unknown[]) => Doc; export const CollectionFromSearch = async (constructor: CollectionConstructor, requested: Opt>): Promise => { await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); @@ -147,7 +147,7 @@ export namespace GooglePhotos { values.forEach(async value => { const searched = (await ContentSearch({ included: [value] }))?.mediaItems?.map(({ id }) => id); searched?.forEach(async id => { - const image = await Cast(idMapping[id], Doc); + const image = await Cast(idMapping[id as string], Doc); if (image) { const key = image[Id]; const tags = tagMapping.get(key); @@ -193,7 +193,7 @@ export namespace GooglePhotos { } export interface SearchResponse { - mediaItems: any[]; + mediaItems: MediaItem[]; nextPageToken: string; } @@ -204,7 +204,7 @@ export namespace GooglePhotos { const found = 0; do { // eslint-disable-next-line no-await-in-loop - const response: any = await photos.mediaItems.search(albumId, pageSize, nextPageTokenStored); + const response = await photos.mediaItems.search(albumId, pageSize, nextPageTokenStored); mediaItems.push(...response.mediaItems); nextPageTokenStored = response.nextPageToken; } while (found); @@ -278,9 +278,9 @@ export namespace GooglePhotos { return undefined; }; - export const WriteMediaItemsToServer = async (body: { mediaItems: any[] }): Promise => { + export const WriteMediaItemsToServer = async (body: { mediaItems: MediaItem[] }): Promise => { const uploads = await Networking.PostToServer('/googlePhotosMediaGet', body); - return uploads; + return uploads as UploadInformation[]; }; export const UploadThenFetch = async (sources: Doc[], album?: AlbumReference, descriptionKey = 'caption') => { @@ -320,7 +320,7 @@ export namespace GooglePhotos { }); if (media.length) { const results = await Networking.PostToServer('/googlePhotosMediaPost', { media, album }); - return results; + return results as Opt; } return undefined; }; @@ -331,7 +331,7 @@ export namespace GooglePhotos { if (typeof target === 'string') { description = target; } else if (target instanceof RichTextField) { - description = RichTextUtils.ToPlainText(EditorState.fromJSON(new FormattedTextBox({} as any).config, JSON.parse(target.Data))); + description = RichTextUtils.ToPlainText(EditorState.fromJSON(FormattedTextBox.MakeConfig(undefined, undefined), JSON.parse(target.Data))); } return description; }; diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index f73149fdc..43807397f 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -8,9 +8,9 @@ import { Upload } from '../../../server/SharedMediaTypes'; import { Networking } from '../../Network'; export namespace ImageUtils { - export const ExtractImgInfo = async (document: Doc): Promise => { + export const ExtractImgInfo = async (document: Doc) => { const field = Cast(document.data, ImageField); - return field ? Networking.PostToServer('/inspectImage', { source: field.url.href }) : undefined; + return field ? (Networking.PostToServer('/inspectImage', { source: field.url.href }) as Promise) : undefined; }; export const AssignImgInfo = (document: Doc, data?: Upload.InspectionResults) => { diff --git a/src/client/util/PingManager.ts b/src/client/util/PingManager.ts index 170632836..0e4f8cab0 100644 --- a/src/client/util/PingManager.ts +++ b/src/client/util/PingManager.ts @@ -29,7 +29,7 @@ export class PingManager { }); Networking.PostToServer('/ping', { date: new Date() }) .then(res => { - SnappingManager.SetServerVersion(res.message); + SnappingManager.SetServerVersion((res as { message: string }).message); !this.IsBeating && setIsBeating(true); }) .catch(() => this.IsBeating && setIsBeating(false)); diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 5d041f7b4..6ea242fc3 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -598,7 +598,8 @@ export class SettingsManager extends React.Component { }); } else { const passwordBundle = { curr_pass: this._curr_password, new_pass: this._new_password, new_confirm: this._new_confirm }; - const { error } = await Networking.PostToServer('/internalResetPassword', passwordBundle); + const reset = await Networking.PostToServer('/internalResetPassword', passwordBundle); + const { error } = reset as { error: { msg: string }[] }; runInAction(() => { this._passwordResultText = error ? 'Error: ' + error[0].msg + '...' : 'Password successfully updated!'; }); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b40cd2761..ca830aa6f 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -28,6 +28,7 @@ import { FieldViewProps } from '../nodes/FieldView'; import { DocumentView, DocumentViewProps } from '../nodes/DocumentView'; import { FlashcardPracticeUI } from './FlashcardPracticeUI'; import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere'; +import { Upload } from '../../../server/SharedMediaTypes'; export enum docSortings { Time = 'time', @@ -407,7 +408,7 @@ export function CollectionSubView() { const imgSrc = img.split('src="')[1].split('"')[0]; const imgOpts = { ...options, _width: 300 }; if (imgSrc.startsWith('data:image') && imgSrc.includes('base64')) { - const result = (await Networking.PostToServer('/uploadRemoteImage', { sources: [imgSrc] })).lastElement(); + const result = ((await Networking.PostToServer('/uploadRemoteImage', { sources: [imgSrc] })) as Upload.ImageInformation[]).lastElement(); const newImgSrc = result.accessPaths.agnostic.client.indexOf('dashblobstore') === -1 // ? ClientUtils.prepend(result.accessPaths.agnostic.client) diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 3c31b584e..b33c267ee 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1291,7 +1291,7 @@ export class CollectionFreeFormView extends CollectionSubView { + addDrawing = (doc: Doc, opts: DrawingOptions, gptRes: string, x?: number, y?: number) => { const docData = doc[DocData]; docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text; docData._width = opts.size; @@ -1302,6 +1302,9 @@ export class CollectionFreeFormView extends CollectionSubView { const res = await gptImageCall(prompt); if (res) { - const result = await Networking.PostToServer('/uploadRemoteImage', { sources: res }); + const result = (await Networking.PostToServer('/uploadRemoteImage', { sources: res })) as Upload.FileInformation[]; const source = ClientUtils.prepend(result[0].accessPaths.agnostic.client); return source; } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index b6b0e4a8a..9395863d8 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -36,7 +36,7 @@ import { OverlayView } from '../OverlayView'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { PinDocView, PinProps } from '../PinFuncs'; import { DrawingFillHandler } from '../smartdraw/DrawingFillHandler'; -import { FireflyImageData } from '../smartdraw/FireflyConstants'; +import { FireflyImageData, isFireflyImageData } from '../smartdraw/FireflyConstants'; import { SmartDrawHandler } from '../smartdraw/SmartDrawHandler'; import { StickerPalette } from '../smartdraw/StickerPalette'; import { StyleProp } from '../StyleProp'; @@ -354,7 +354,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { const ext = extname(file); return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext); })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href), - }).then((info: Upload.ImageInformation) => { + }).then(res => { + const info = res as Upload.ImageInformation; const img = Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { title: 'expand:' + this.Document.title }); DocUtils.assignImageInfo(info, img); this._props.addDocTab(img, OpenWhere.addRight); @@ -627,14 +628,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { } else SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput || StrCast(this.Document.title), true).then( action(newImgs => { - if (newImgs[0] && !(newImgs[0] instanceof Doc)) { - const url = newImgs[0].pathname; + const firstImg = newImgs[0]; + if (isFireflyImageData(firstImg)) { + const url = firstImg.pathname; const imgField = new ImageField(url); this._prevImgs.length === 0 && this._prevImgs.push({ prompt: StrCast(this.dataDoc.ai_firefly_prompt), seed: this.dataDoc.ai_firefly_seed as number, href: this.paths.lastElement(), pathname: field.url.pathname }); - this._prevImgs.unshift({ prompt: newImgs[0].prompt, seed: newImgs[0].seed, pathname: url }); + this._prevImgs.unshift({ prompt: firstImg.prompt, seed: firstImg.seed, pathname: url }); this.dataDoc.ai_firefly_history = JSON.stringify(this._prevImgs); - this.dataDoc.ai_firefly_prompt = newImgs[0].prompt; + this.dataDoc.ai_firefly_prompt = firstImg.prompt; this.dataDoc[this.fieldKey] = imgField; this._regenerateLoading = false; this._regenInput = ''; @@ -688,7 +690,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { const ext = extname(file); return file.replace(ext, (this._error ? '_o' : this._curSuffix) + ext); })(ImageCast(this.Document[Doc.LayoutFieldKey(this.Document)])?.url.href), - }).then((info: Upload.ImageInformation) => { + }).then(res => { + const info = res as Upload.ImageInformation; const img = Docs.Create.ImageDocument(info.accessPaths.agnostic.client, { title: 'expand:' + this.Document.title }); DocUtils.assignImageInfo(info, img); const genratedDocs = this.Document.generatedDocs @@ -741,7 +744,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { focus = (anchor: Doc, options: FocusViewOptions) => (anchor.type === DocumentType.CONFIG ? undefined : this._ffref.current?.focus(anchor, options)); renderedPixelDimensions = async () => { - const { nativeWidth: width, nativeHeight: height } = await Networking.PostToServer('/inspectImage', { source: this.paths[0] }); + const res = await Networking.PostToServer('/inspectImage', { source: this.paths[0] }); + const { nativeWidth: width, nativeHeight: height } = res as { nativeWidth: number; nativeHeight: number }; return { width, height }; }; savedAnnotations = () => this._savedAnnotations; diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx index 37ffca2d6..e7a6193d4 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/button-has-type */ import * as React from 'react'; import { useEffect, useRef, useState } from 'react'; import { IconContext } from 'react-icons'; @@ -72,7 +71,7 @@ export function RecordingView(props: IRecordingViewProps) { const serverPaths: string[] = (await Networking.UploadFilesToServer(videoFiles.map(file => ({ file })))).map(res => (res.result instanceof Error ? '' : res.result.accessPaths.agnostic.server)); // concat the segments together using post call - const result: Upload.AccessPathInfo | Error = await Networking.PostToServer('/concatVideos', serverPaths); + const result = (await Networking.PostToServer('/concatVideos', serverPaths)) as Upload.AccessPathInfo | Error; !(result instanceof Error) ? props.setResult(result, concatPres || undefined) : console.error('video conversion failed'); })(); } diff --git a/src/client/views/nodes/chatbot/tools/CreateCSVTool.ts b/src/client/views/nodes/chatbot/tools/CreateCSVTool.ts index e8ef3fbfe..290c48d6c 100644 --- a/src/client/views/nodes/chatbot/tools/CreateCSVTool.ts +++ b/src/client/views/nodes/chatbot/tools/CreateCSVTool.ts @@ -38,10 +38,10 @@ export class CreateCSVTool extends BaseTool { async execute(args: ParametersType): Promise { try { console.log('Creating CSV file:', args.filename, ' with data:', args.csvData); - const { fileUrl, id } = await Networking.PostToServer('/createCSV', { + const { fileUrl, id } = (await Networking.PostToServer('/createCSV', { filename: args.filename, data: args.csvData, - }); + })) as { fileUrl: string; id: string }; this._handleCSVResult(fileUrl, args.filename, id, args.csvData); diff --git a/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts b/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts index dc6140871..e92d87dfd 100644 --- a/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts +++ b/src/client/views/nodes/chatbot/tools/ImageCreationTool.ts @@ -37,9 +37,9 @@ export class ImageCreationTool extends BaseTool { console.log(`Generating image for prompt: ${image_prompt}`); // Create an array of promises, each one handling a search for a query try { - const { result, url } = await Networking.PostToServer('/generateImage', { + const { result, url } = (await Networking.PostToServer('/generateImage', { image_prompt, - }); + })) as { result: Upload.FileInformation & Upload.InspectionResults; url: string }; console.log('Image generation result:', result); this._createImage(result, { text: RTFCast(image_prompt) }); return url diff --git a/src/client/views/nodes/chatbot/tools/RAGTool.ts b/src/client/views/nodes/chatbot/tools/RAGTool.ts index 2db61c768..ef374ed22 100644 --- a/src/client/views/nodes/chatbot/tools/RAGTool.ts +++ b/src/client/views/nodes/chatbot/tools/RAGTool.ts @@ -75,7 +75,7 @@ export class RAGTool extends BaseTool { async getFormattedChunks(relevantChunks: RAGChunk[]): Promise { try { - const { formattedChunks } = await Networking.PostToServer('/formatChunks', { relevantChunks }); + const { formattedChunks } = await Networking.PostToServer('/formatChunks', { relevantChunks }) as { formattedChunks: Observation[]} if (!formattedChunks) { throw new Error('Failed to format chunks'); diff --git a/src/client/views/nodes/chatbot/tools/SearchTool.ts b/src/client/views/nodes/chatbot/tools/SearchTool.ts index 5fc6ab768..6a11407a5 100644 --- a/src/client/views/nodes/chatbot/tools/SearchTool.ts +++ b/src/client/views/nodes/chatbot/tools/SearchTool.ts @@ -41,15 +41,15 @@ export class SearchTool extends BaseTool { // Create an array of promises, each one handling a search for a query const searchPromises = queries.map(async query => { try { - const { results } = await Networking.PostToServer('/getWebSearchResults', { + const { results } = (await Networking.PostToServer('/getWebSearchResults', { query, max_results: this._max_results, - }); + })) as { results: { url: string; snippet: string }[] }; const data = results.map((result: { url: string; snippet: string }) => { const id = uuidv4(); this._addLinkedUrlDoc(result.url, id); return { - type: 'text', + type: 'text' as const, text: `${result.url}${result.snippet}`, }; }); @@ -58,7 +58,7 @@ export class SearchTool extends BaseTool { console.log(error); return [ { - type: 'text', + type: 'text' as const, text: `An error occurred while performing the web search for query: ${query}`, }, ]; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index efddfb841..f4ab2f41c 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -21,11 +21,13 @@ import { DictationButton } from '../../DictationButton'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { TagItem } from '../../TagsView'; import { ChatSortField, docSortings } from '../../collections/CollectionSubView'; -import { DocumentView } from '../../nodes/DocumentView'; +import { DocumentView, DocumentViewInternal } from '../../nodes/DocumentView'; import { SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; import { AnchorMenu } from '../AnchorMenu'; import './GPTPopup.scss'; import { FireflyImageDimensions } from '../../smartdraw/FireflyConstants'; +import { Upload } from '../../../../server/SharedMediaTypes'; +import { OpenWhere } from '../../nodes/OpenWhere'; export enum GPTPopupMode { SUMMARY, // summary of seleted document text @@ -210,7 +212,12 @@ export class GPTPopup extends ObservableReactComponent { // ); // } else∂ return SmartDrawHandler.CreateWithFirefly(imgDesc, FireflyImageDimensions.Square, 0) - .then(action(() => (this._userPrompt = ''))) + .then( + action(doc => { + doc instanceof Doc && DocumentViewInternal.addDocTabFunc(doc, OpenWhere.addRight); + this._userPrompt = ''; + }) + ) .catch(e => { alert(e); return undefined; @@ -259,7 +266,7 @@ export class GPTPopup extends ObservableReactComponent { .then(imageUrls => imageUrls?.[0] ? Networking.PostToServer('/uploadRemoteImage', { sources: [imageUrls[0]] }).then(res => { - const source = ClientUtils.prepend(res[0].accessPaths.agnostic.client); + const source = ClientUtils.prepend((res as Upload.FileInformation[])[0].accessPaths.agnostic.client); return this.setImgUrls([[imageUrls[0]!, source]]); }) : undefined diff --git a/src/client/views/smartdraw/FireflyConstants.ts b/src/client/views/smartdraw/FireflyConstants.ts index 1f1781617..8cc9e36a5 100644 --- a/src/client/views/smartdraw/FireflyConstants.ts +++ b/src/client/views/smartdraw/FireflyConstants.ts @@ -5,6 +5,11 @@ export interface FireflyImageData { href?: string; } +export function isFireflyImageData(obj: unknown): obj is FireflyImageData { + const tobj = obj as FireflyImageData; + return typeof obj === 'object' && obj !== null && typeof tobj.pathname === 'string' && typeof tobj.prompt === 'string' && typeof tobj.seed === 'number'; +} + export enum FireflyImageDimensions { Square = 'square', Landscape = 'landscape', diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index 9d67d111b..532391ac6 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -23,10 +23,10 @@ import { SVGToBezier, SVGType } from '../../util/bezierFit'; import { InkingStroke } from '../InkingStroke'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { MarqueeView } from '../collections/collectionFreeForm'; -import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; -import { OpenWhere } from '../nodes/OpenWhere'; +import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView'; import { FireflyDimensionsMap, FireflyImageData, FireflyImageDimensions } from './FireflyConstants'; import './SmartDrawHandler.scss'; +import { Upload } from '../../../server/SharedMediaTypes'; export interface DrawingOptions { text: string; @@ -60,7 +60,6 @@ export class SmartDrawHandler extends ObservableReactComponent { private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 }; private _lastResponse: string = ''; private _selectedDocs: Doc[] = []; - private _errorOccurredOnce = false; @observable private _display: boolean = false; @observable private _pageX: number = 0; @@ -95,7 +94,7 @@ export class SmartDrawHandler extends ObservableReactComponent { CollectionFreeForm, FormattedTextBox, StickerPalette) to define how a drawing document should be added or removed in their respective locations (to the freeform canvas, to the sticker palette's preview, etc.) */ - public AddDrawing: (doc: Doc, opts: DrawingOptions, gptRes: string) => void = unimplementedFunction; + public AddDrawing: (doc: Doc, opts: DrawingOptions, gptRes: string, x?: number, y?: number) => void = unimplementedFunction; public RemoveDrawing: (useLastContainer: boolean, doc?: Doc) => void = unimplementedFunction; /** * This creates the ink document that represents a drawing, so it goes through the strokes that make up the drawing, @@ -206,16 +205,15 @@ export class SmartDrawHandler extends ObservableReactComponent { this._isLoading = true; this._canInteract = false; if (this.ShowRegenerate) { - await this.regenerate(this._selectedDocs); - runInAction(() => { - this._selectedDocs = []; - this._regenInput = ''; - this._showEditBox = false; - }); + await this.regenerate(this._selectedDocs).then( + action(() => { + this._selectedDocs = []; + this._regenInput = ''; + this._showEditBox = false; + }) + ); } else { - runInAction(() => { - this._showOptions = false; - }); + this._showOptions = false; try { if (this._generateImage) { await this.createImageWithFirefly(this._userInput); @@ -224,18 +222,8 @@ export class SmartDrawHandler extends ObservableReactComponent { await this.drawWithGPT({ X: this._pageX, Y: this._pageY }, this._userInput, this._complexity, this._size, this._autoColor); } this.hideSmartDrawHandler(); - - runInAction(() => { - this.ShowRegenerate = true; - }); } catch (err) { - if (this._errorOccurredOnce) { - console.error('GPT call failed', err); - this._errorOccurredOnce = false; - } else { - this._errorOccurredOnce = true; - await this.handleSendClick(); - } + console.error('GPT call failed', err); } } runInAction(() => { @@ -256,7 +244,6 @@ export class SmartDrawHandler extends ObservableReactComponent { const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData.data, strokeData.lastInput, strokeData.lastRes); drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res); drawingDoc && this._selectedDocs.push(drawingDoc); - this._errorOccurredOnce = false; return strokeData; } else { console.error('GPT call failed'); @@ -270,7 +257,10 @@ export class SmartDrawHandler extends ObservableReactComponent { */ createImageWithFirefly = (input: string, seed?: number): Promise => { this._lastInput.text = input; - return SmartDrawHandler.CreateWithFirefly(input, this._imgDims, seed); + return SmartDrawHandler.CreateWithFirefly(input, this._imgDims, seed).then(doc => { + doc instanceof Doc && this.AddDrawing(doc, this._lastInput, input, this._pageX, this._pageY); + return doc; + }); }; /** * Calls Firefly API to create an image based on user input */ @@ -281,9 +271,11 @@ export class SmartDrawHandler extends ObservableReactComponent { public static ReCreateWithFirefly(input: string, imgDims: FireflyImageDimensions, seed?: number): Promise { const dims = FireflyDimensionsMap[imgDims]; return Networking.PostToServer('/queryFireflyImage', { prompt: input, width: dims.width, height: dims.height, seed }) - .then(img => { - if (img.error) { - alert('recreate image failed: ' + img.error); + .then(res => { + const img = res as Upload.FileInformation; + const error = res as { error: string }; + if ('error' in error) { + alert('recreate image failed: ' + error.error); return undefined; } return { prompt: input, seed, pathname: img.accessPaths.agnostic.client }; @@ -296,21 +288,22 @@ export class SmartDrawHandler extends ObservableReactComponent { public static CreateWithFirefly(input: string, imgDims: FireflyImageDimensions, seed?: number): Promise { const dims = FireflyDimensionsMap[imgDims]; return Networking.PostToServer('/queryFireflyImage', { prompt: input, width: dims.width, height: dims.height, seed }) - .then(img => { - if (img.error) { - alert('create image failed: ' + img.error); + .then(res => { + const img = res as Upload.FileInformation; + const error = res as { error: string }; + if ('error' in error) { + alert('create image failed: ' + error.error); return undefined; } - const newseed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)[1]; + const newseed = img.accessPaths.agnostic.client.match(/\/(\d+)upload/)?.[1]; const imgDoc: Doc = Docs.Create.ImageDocument(img.accessPaths.agnostic.client, { title: input.match(/^(.*?)~~~.*$/)?.[1] || input, nativeWidth: dims.width, nativeHeight: dims.height, ai: 'firefly', - ai_firefly_seed: newseed, + ai_firefly_seed: +(newseed ?? 0), ai_firefly_prompt: input, }); - DocumentViewInternal.addDocTabFunc(imgDoc, OpenWhere.addRight); return imgDoc; }) .catch(e => { @@ -331,26 +324,21 @@ export class SmartDrawHandler extends ObservableReactComponent { return Promise.all( drawingDocs.map(async doc => { switch (doc.type) { - case DocumentType.IMG: - if (this._regenInput) { - // if (this._selectedDoc) { - const newPrompt = doc.ai_firefly_prompt ? `${doc.ai_firefly_prompt} ~~~ ${this._regenInput}` : this._regenInput; - return changeInPlace ? this.recreateImageWithFirefly(newPrompt, NumCast(doc?.ai_firefly_seed)) : this.createImageWithFirefly(newPrompt, NumCast(doc?.ai_firefly_seed)); - // } - } - return changeInPlace - ? this.recreateImageWithFirefly(this._lastInput.text || StrCast(doc.ai_firefly_prompt), NumCast(doc?.ai_firefly_seed)) - : this.createImageWithFirefly(this._lastInput.text || StrCast(doc.ai_firefly_prompt), NumCast(doc?.ai_firefly_seed)); + case DocumentType.IMG: { + const func = changeInPlace ? this.recreateImageWithFirefly : this.createImageWithFirefly; + const newPrompt = doc.ai_firefly_prompt ? `${doc.ai_firefly_prompt} ~~~ ${this._regenInput}` : this._regenInput; + return this._regenInput ? func(newPrompt, NumCast(doc?.ai_firefly_seed)) : func(this._lastInput.text || StrCast(doc.ai_firefly_prompt)); + } case DocumentType.COL: { try { - let res; - if (this._regenInput) { - const prompt = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`; - res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true); - this._lastInput.text = `${this._lastInput.text} ~~~ ${this._regenInput}`; - } else { - res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true); - } + const res = await (async () => { + if (this._regenInput) { + const prompt = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`; + this._lastInput.text = `${this._lastInput.text} ~~~ ${this._regenInput}`; + return gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true); + } + return gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true); + })(); if (res) { const strokeData = await this.parseSvg(res, { X: this._lastInput.x, Y: this._lastInput.y }, true, lastInput?.autoColor || this._autoColor); this.RemoveDrawing !== unimplementedFunction && this.RemoveDrawing(true, doc); -- cgit v1.2.3-70-g09d2 From 532f0fa22281fef1e35e3d0a6064ee57e4673253 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 28 Feb 2025 14:52:39 -0500 Subject: added drop target for regenerating images --- src/client/util/DragManager.ts | 3 + src/client/views/nodes/ImageBox.scss | 8 ++ src/client/views/nodes/ImageBox.tsx | 90 +++++++++++++++-------- src/client/views/smartdraw/DrawingFillHandler.tsx | 23 +++--- 4 files changed, 83 insertions(+), 41 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 81ea840f1..6c8179c82 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -555,9 +555,12 @@ export namespace DragManager { let scrollAwaiter: Opt; let startWindowDragTimer: NodeJS.Timeout | undefined; + let startCanEmbed = SnappingManager.CanEmbed; const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (docDragData) { + if (e.ctrlKey) SnappingManager.SetCanEmbed(true); + else if (!startCanEmbed) SnappingManager.SetCanEmbed(false); docDragData.userDropAction = e.ctrlKey && e.altKey ? dropActionType.copy : e.shiftKey ? dropActionType.move : e.ctrlKey ? dropActionType.embed : docDragData.defaultDropAction; const targClassName = e.target instanceof HTMLElement && typeof e.target.className === 'string' ? e.target.className : ''; if (['lm_tab', 'lm_title_wrap', 'lm_tabs', 'lm_header'].includes(targClassName) && docDragData.draggedDocuments.length === 1) { diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss index 59e093683..671621bbe 100644 --- a/src/client/views/nodes/ImageBox.scss +++ b/src/client/views/nodes/ImageBox.scss @@ -122,6 +122,7 @@ } } } +.imageBox-regenerateDropTarget, .imageBox-alternateDropTarget { position: absolute; color: white; @@ -136,6 +137,13 @@ height: 100%; } } +.imageBox-regenerateDropTarget { + right: 30; + border-radius: 50%; + svg { + border-radius: 50%; + } +} .imageBox-fader img { position: absolute; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 55474cb7e..d122ca5b0 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -36,7 +36,7 @@ import { OverlayView } from '../OverlayView'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { PinDocView, PinProps } from '../PinFuncs'; import { DrawingFillHandler } from '../smartdraw/DrawingFillHandler'; -import { FireflyImageData, isFireflyImageData } from '../smartdraw/FireflyConstants'; +import { FireflyImageData, FireflyImageDimensions, isFireflyImageData } from '../smartdraw/FireflyConstants'; import { SmartDrawHandler } from '../smartdraw/SmartDrawHandler'; import { StickerPalette } from '../smartdraw/StickerPalette'; import { StyleProp } from '../StyleProp'; @@ -45,6 +45,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import './ImageBox.scss'; import { OpenWhere } from './OpenWhere'; +import { RichTextField } from '../../../fields/RichTextField'; export class ImageEditorData { // eslint-disable-next-line no-use-before-define @@ -83,6 +84,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { private _disposers: { [name: string]: IReactionDisposer } = {}; private _getAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = () => undefined; private _overlayIconRef = React.createRef(); + private _regenerateIconRef = React.createRef(); private _mainCont: HTMLDivElement | null = null; private _annotationLayer: React.RefObject = React.createRef(); imageRef: HTMLImageElement | null = null; //