From 940e83b0f52c54d1eaea62d3fd31f6f0608f290b Mon Sep 17 00:00:00 2001 From: Joanne Date: Tue, 24 Jun 2025 11:07:07 -0400 Subject: minor tutorial fixes --- .../CollectionFreeFormInfoUI.tsx | 526 +++++++++------------ 1 file changed, 213 insertions(+), 313 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 5a54553b1..efc22f523 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -1,22 +1,21 @@ import { makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, FieldResult, FieldType } from '../../../../fields/Doc'; -import { InkTool } from '../../../../fields/InkField'; -import { StrCast } from '../../../../fields/Types'; +import { Doc } from '../../../../fields/Doc'; import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton'; -import { TopBar } from '../../topbar/TopBar'; -import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState'; -import { CollectionFreeFormView } from './CollectionFreeFormView'; -import { Button } from '@dash/components'; +import { CollectionFreeFormInfoState, infoState } from './CollectionFreeFormInfoState'; +import { Button } from '../../../util/CurrentUserUtils'; +import { InfoState } from './CollectionFreeFormInfoState'; +import { DocButtonState } from '../../nodes/DocumentLinksButton'; +import { InkTool } from '../../../../fields/InkField'; +import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; +import { CollectionFreeFormView } from '.'; +import { DocListCast } from '../../../../fields/Doc'; import { ButtonType } from '../../nodes/FontIconBox/FontIconBox'; -import './CollectionFreeFormView.scss'; - export interface CollectionFreeFormInfoUIProps { - Doc: Doc; - layoutDoc: Doc; + Document: Doc; + LayoutDoc: Doc; childDocs: () => Doc[]; close: () => void; } @@ -24,13 +23,18 @@ export interface CollectionFreeFormInfoUIProps { @observer export class CollectionFreeFormInfoUI extends ObservableReactComponent { _originalBackground: string | undefined; - public tutorialStates: { [key: string]: infoState } = {}; + private tutorialStates: { [key: string]: infoState } = {}; public static Init() { - CollectionFreeFormView.SetInfoUICreator((doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => ( - // - - )); + CollectionFreeFormView.SetInfoUICreator( + (doc: Doc, layout: Doc, childDocs: () => Doc[], close: () => void) => + + ); } constructor(props: CollectionFreeFormInfoUIProps) { @@ -39,6 +43,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent { this._currState = val; @@ -54,303 +59,203 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent { runInAction(() => { - console.log('Transitioning to next state:', newState); if (!this._currState) { this._currState = newState; // Assign directly if undefined } else { this._currState = newState; - } + } }); }; createNextButton = (newState: ReturnType) => { return { - title: 'Next', - toolTip: 'Next', + title: "Next", + toolTip: "Next", btnType: ButtonType.ClickButton, scripts: { - onClick: `this.skipToState(${newState})`, + onClick: `this.skipToState(${newState})` }, - targetState: newState, + targetState: newState }; }; setupStates = () => { - this._originalbackground = StrCast(this._props.Doc.$backgroundColor); - // state entry functions - // const setBackground = (colour: string) => () => {this._props.Doc.$backgroundColor = colour;} // prettier-ignore - // const setOpacity = (opacity: number) => () => {this._props.layoutDoc.opacity = opacity;} // prettier-ignore - // arc transition trigger conditions - const firstDoc = () => (this._props.childDocs().length ? this._props.childDocs()[0] : undefined); - const numDocs = () => this._props.childDocs().length; - - let docX: FieldResult; - let docY: FieldResult; - - const docNewX = () => firstDoc()?.x; - const docNewY = () => firstDoc()?.y; - - const linkStart = () => DocumentLinksButton.StartLink; - const linkUnstart = () => !DocumentLinksButton.StartLink; - - const numDocLinks = () => Doc.Links(firstDoc())?.length; - const linkMenuOpen = () => DocButtonState.Instance.LinkEditorDocView; - - const activeTool = () => Doc.ActiveTool; - - const pin = () => DocListCast(Doc.ActivePresentation?.data); - - let trail: number; - - const presentationMode = () => Doc.ActivePresentation?.presentation_status; - - // set of states - const start = InfoState( - 'Click anywhere and begin typing to create your first text document.', - { - docCreated: [() => numDocs(), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - // eslint-disable-next-line no-use-before-define - return oneDoc; - }], - } - ); // prettier-ignore - - const oneDoc = InfoState( - 'Hello world! You can drag and drop to move your document around.', - { - // docCreated: [() => numDocs() > 1, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX !== docNewX()) || (docY && docY !== docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - // eslint-disable-next-line no-use-before-define - return movedDoc; - }], - } - ); // prettier-ignore - - const movedDoc = InfoState( - 'Great moves. Try creating a second document. You can see the list of supported document types by typing a colon (":")', - { + let docCounter = this._props.childDocs().length; + let lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + let linkCounter = Doc.Links(lastDocCreated)?.length; + let presentationCounter = DocListCast(Doc.ActivePresentation?.data).length + this._originalBackground = this._props.Document.backgroundColor as string; + + this.tutorialStates.multipleDocs = InfoState("Let's create a new link! Click the link icon on one document and connect it to another.", { // eslint-disable-next-line no-use-before-define - linkStarted: [ - () => DocumentLinksButton.StartLink, - () => { - linkCounter = Doc.Links(lastDocCreated).length; - // eslint-disable-next-line no-use-before-define - return startedLink; - }, - ], + linkStarted: [() => DocumentLinksButton.StartLink, () => { + linkCounter = Doc.Links(lastDocCreated).length + // eslint-disable-next-line no-use-before-define + return startedLink}], + // docCreated: [() => this._props.childDocs().length > docCounter, () => { + // docCounter += 1 + // lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + // // eslint-disable-next-line no-use-before-define + // return this.tutorialStates.makePresentation}] }, 'dash-create-link-board.gif' ); - this.tutorialStates.presentDocs = InfoState( - 'Click the pin icon in the top left corner while clicking a doc to create your presentation.', - { + this.tutorialStates.presentDocs = InfoState("Select a document then click the 'pin' button in the top left to create your presentation.", { // eslint-disable-next-line no-use-before-define - docPinned: [ - () => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, - () => { - presentationCounter++; - // eslint-disable-next-line no-use-before-define - return pinnedDoc; - }, - ], - }, - 'pin-explanation.gif' - ); - - this.tutorialStates.nestedCollections = InfoState( - "Want to learn how to create a nested collection? Click the : button and add a 'collection' doc", - { + docPinned: [() => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, () => { + presentationCounter++ // eslint-disable-next-line no-use-before-define - docCreated: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - // eslint-disable-next-line no-use-before-define - return marqueeSelection; - }, - ], + return pinnedDoc}], }, - 'dash-nested-collection.gif' - ); - - this.tutorialStates.makePresentation = InfoState('Add a new document to create a presentation!', { - docCreated: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - // eslint-disable-next-line no-use-before-define - return this.tutorialStates.presentDocs; - }, - ], - }); + 'pin-explanation.gif'); + this.tutorialStates.nestedCollections = InfoState("Want to learn how to create a nested collection? Click the : button and add a 'collection' doc", { + // eslint-disable-next-line no-use-before-define + docCreated: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + // eslint-disable-next-line no-use-before-define + return marqueeSelection}] + }, + 'dash-nested-collection.gif') + + + this.tutorialStates.makePresentation = InfoState("Add a new document to create a presentation!", { + docCreated: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + // eslint-disable-next-line no-use-before-define + return this.tutorialStates.presentDocs}], + }); + const skipToLinksButton: Button = { - title: 'Links Tutorial', - toolTip: 'Skip', + title: "Links Tutorial", + toolTip: "Skip", btnType: ButtonType.ClickButton, scripts: { - onClick: 'this.skipToState(this.tutorialStates.multipleDocs)', + onClick: "this.skipToState(this.tutorialStates.multipleDocs)" }, - targetState: this.tutorialStates.multipleDocs, + targetState: this.tutorialStates.multipleDocs }; const skipToPinsButton: Button = { - title: 'Pins Tutorial', - toolTip: 'Skip', + title: "Pins Tutorial", + toolTip: "Skip", btnType: ButtonType.ClickButton, scripts: { - onClick: 'this.skipToState(this.tutorialStates.makePresentation)', + onClick: "this.skipToState(this.tutorialStates.makePresentation)" }, - targetState: this.tutorialStates.makePresentation, + targetState: this.tutorialStates.makePresentation }; const skipToPresentationButton: Button = { - title: 'Collections Tutorial', - toolTip: 'Skip', + title: "Collections Tutorial", + toolTip: "Skip", btnType: ButtonType.ClickButton, scripts: { - onClick: 'this.skipToState(this.tutorialStates.nestedCollections)', + onClick: "this.skipToState(this.tutorialStates.nestedCollections)" }, - targetState: this.tutorialStates.nestedCollections, + targetState: this.tutorialStates.nestedCollections }; - const ending = InfoState("If you have any more questions, feel free to ask Dash's AI Bot!", {}); + const ending = InfoState("If you have any more questions, feel free to ask Dash's AI Bot!") // Traditional tutorial - const completed = InfoState('Eager to learn more? Click the ? icon in the top right corner to read our full documentation.', { docRemoved: [() => this._props.childDocs().length === 1, () => this.tutorialStates.start] }, 'documentation.png'); + const completed = InfoState( + "Eager to learn more? Click the ? icon in the top right corner to read our full documentation.", + { docRemoved: [() => this._props.childDocs().length === 1, () => this.tutorialStates.start] }, + 'documentation.png', + ); const penMode = InfoState("You're in pen mode! Click and drag to draw your first masterpiece, then click the Ink button once you're done.", { activePen: [() => Doc.ActiveTool !== InkTool.Ink, () => completed], }); - + const briefArtisticFeature = InfoState("Finally, want to explore the art feature of Dash? Click the 'Ink' button on the hotbar then click the pen button.", { penModeActivated: [() => Doc.ActiveTool === InkTool.Ink, () => penMode], }); - - const activatePresentation = InfoState('Lastly, click the linked node and start the presentation!', { - presentation: [() => Doc.ActivePresentation?.presentation_status === 'auto', () => briefArtisticFeature], + + const activatePresentation = InfoState("Lastly, click the linked node and start the presentation!", { + presentation: [() => Doc.ActivePresentation?.presentation_status === "auto", () => briefArtisticFeature], }); + + const deletePresentation = InfoState("Cool! Click 'setOnClick to follow primary link' for your non-presentation doc and try deleting the presentation.", { + docRemoved: [() => this._props.childDocs().length < docCounter, () => { + docCounter -= 1 + return activatePresentation}], + }, + 'onclick-node.gif'); + + const trailedPresentation = InfoState("Try linking your presentation to the last doc you created (now highlighted).", { + linkAdd: [() => Doc.Links(lastDocCreated)?.length > linkCounter, () => { + linkCounter += 1 + return deletePresentation + }], + docAdded: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + // Last doc that is not the presentation + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2] + linkCounter = Doc.Links(lastDocCreated)?.length + return deletePresentation}] + }, + 'link-presentation.gif'); + + const pinnedPresentation = InfoState("Want to see something cool? Zoom out, click the trail button on the presentation, and drag it inside the canvas.", { + docAdded: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + // Last doc that is not the presentation + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2] + Doc.HighlightDoc(lastDocCreated) + linkCounter = Doc.Links(lastDocCreated)?.length + return trailedPresentation}], + }, + 'dash-trail-explanation.gif'); - const deletePresentation = InfoState( - "Cool! Click 'setOnClick to follow primary link' for your linked doc and try deleting the presentation.", - { - docRemoved: [ - () => this._props.childDocs().length < docCounter, - () => { - docCounter -= 1; - return activatePresentation; - }, - ], - }, - 'onclick-node.gif' - ); - - const trailedPresentation = InfoState( - 'See the new dragged-in presentation? Try linking it to the highlighted doc.', - { - linkAdd: [ - () => Doc.Links(lastDocCreated)?.length > linkCounter, - () => { - linkCounter += 1; - return deletePresentation; - }, - ], - }, - 'link-presentation.gif' - ); - - const pinnedPresentation = InfoState( - 'Want to see something cool? Click the trail button on the presentation and drag it inside the canvas.', - { - docAdded: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - // Last doc that is not the presentation - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 2]; - Doc.HighlightDoc(lastDocCreated); - linkCounter = Doc.Links(lastDocCreated)?.length; - return trailedPresentation; - }, - ], - }, - 'dash-trail-explanation.gif' - ); - - const pinnedDoc2 = InfoState('You pinned another doc. Press play to the right to show your presentation!', { - autoPresentation: [() => Doc.ActivePresentation?.presentation_status === 'auto', () => pinnedPresentation], + const pinnedDoc2 = InfoState("You pinned another doc. Press autoplay to the right to show your presentation!", { + autoPresentation: [() => Doc.ActivePresentation?.presentation_status === "auto", () => pinnedPresentation], }); - const pinnedDoc = InfoState('You just pinned your doc. Pin another doc to add to the presentation!', { + const pinnedDoc = InfoState("You just pinned your doc. Pin another doc to add to the presentation!", { // eslint-disable-next-line no-use-before-define - addedDoc: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - return pinnedDoc; - }, - ], - docPinned: [ - () => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, - () => { - presentationCounter++; - // eslint-disable-next-line no-use-before-define - return pinnedDoc2; - }, - ], + addedDoc: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + return pinnedDoc}], + docPinned: [() => DocListCast(Doc.ActivePresentation?.data).length > presentationCounter, () => { + presentationCounter++ + // eslint-disable-next-line no-use-before-define + return pinnedDoc2}], }); + + const editLink = InfoState("Want to make your link visible? Click 'show link'.", { + docCreated: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + return this.tutorialStates.makePresentation}], + }, + 'show-link.gif'); - const editLink = InfoState( - "Want to make your link visible? Click 'show link'.", - { - docCreated: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - return this.tutorialStates.makePresentation; - }, - ], - }, - 'show-link.gif' - ); - - const madeLink = InfoState( - 'You made your first link! You can view your links by selecting the blue dot.', - { - linkViewed: [() => DocButtonState.Instance.LinkEditorDocView, () => editLink], - }, - 'dash-following-link.gif' - ); - - const startedLink = InfoState( - 'Now click the highlighted link icon on your other document.', - { - linkAdd: [ - () => Doc.Links(lastDocCreated)?.length > linkCounter, - () => { - linkCounter += 1; - return madeLink; - }, - ], - }, - 'dash-create-link-board.gif' - ); + const madeLink = InfoState("You made your first link! You can view your links by selecting the blue dot.", { + linkViewed: [() => DocButtonState.Instance.LinkEditorDocView, () => { + docCounter = this._props.childDocs().length + return editLink}], + }, + 'dash-following-link.gif'); + + const startedLink = InfoState("Now click the highlighted link icon on your other document.", { + linkAdd: [() => Doc.Links(lastDocCreated)?.length > linkCounter, () => { + linkCounter += 1 + return madeLink + }] + }, + 'dash-create-link-board.gif'); this.tutorialStates.movedDoc = InfoState("Great moves! Try creating a second document.", { docCreated: [() => this._props.childDocs().length > docCounter, () => { @@ -359,85 +264,80 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - return this.tutorialStates.movedDoc; - }, - ], - }, - undefined, - [skipToLinksButton, skipToPinsButton, skipToPresentationButton] - ); - + + this.tutorialStates.start = InfoState("Welcome to Dash! Click anywhere and begin typing ':' to create your first document.", { + docCreated: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + return this.tutorialStates.movedDoc}] + }, + undefined, + [skipToLinksButton, skipToPinsButton]) + // Information on created nested collections - const createdMarquee = InfoState( - 'Next, right click and drag a square to create the collection', - { - // eslint-disable-next-line no-use-before-define - marqueeMade: [ - () => this._props.childDocs().length < docCounter, - () => { - docCounter -= 1; - return ending; - }, - ], - }, - 'dash-create-collection-marquee.gif' - ); - - const marqueeSelection = InfoState('Want an easier way to make a collection of docs? First add two docs you want to make a collection of', { - marqueeMade: [ - () => this._props.childDocs().length > docCounter, - () => { - docCounter += 1; - lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1]; - return createdMarquee; - }, - ], - }); + const createdMarquee = InfoState("Next, right click and drag a square to create the collection", { + // eslint-disable-next-line no-use-before-define + marqueeMade: [() => this._props.childDocs().length < docCounter, () => { + docCounter -= 1 + return ending}], + }, + 'dash-create-collection-marquee.gif') + + const marqueeSelection = InfoState("Want an easier way to make a collection of docs? First add two docs you want to make a collection of", { + marqueeMade: [() => this._props.childDocs().length > docCounter, () => { + docCounter += 1 + lastDocCreated = this._props.childDocs()[this.props.childDocs().length - 1] + return createdMarquee}] + }) // Explanation of importing - const easierImport = InfoState('Or, for easier access, you can drag any of the accepted file types from your computer or a webpage and drop it into your dashboard. This includes images, videos, audio, pdfs, and more!', {}, 'dash-', [ - this.createNextButton(ending), - ]); - - this.tutorialStates.importFile = InfoState('Want to learn how to import a file? Import using the import menu on the left hand side', {}, 'dash-import.gif', [this.createNextButton(easierImport)]); + const easierImport = InfoState("Or, for easier access, you can drag any of the accepted file types from your computer or a webpage and drop it into your dashboard. This includes images, videos, audio, pdfs, and more!", { + }, + 'dash-', + [this.createNextButton(ending)]) + + this.tutorialStates.importFile = InfoState("Want to learn how to import a file? Import using the import menu on the left hand side", { + }, + 'dash-import.gif', + [this.createNextButton(easierImport)]) // Editing documents // Accessed by right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome - const extraContentsOfDoc = InfoState('Lastly, all documents also have a context-sensitive toolbar. The toolbar contents vary depending on the document type.', {}, 'context-toolbar.png', [this.createNextButton(ending)]); + const extraContentsOfDoc = InfoState("Lastly, all documents also have a context-sensitive toolbar. The toolbar contents vary depending on the document type.", { + }, + 'context-toolbar.png', + [this.createNextButton(ending)]) - const contentsofDoc = InfoState('You can access the context of a doc through right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome', {}, 'dash-context-menu.gif', [ - this.createNextButton(extraContentsOfDoc), - ]); + const contentsofDoc = InfoState("You can access the context of a doc through right-clicking anywhere on the target document or selecting the three bars menu at the bottom of the document chrome", { + }, + 'dash-context-menu.gif', + [this.createNextButton(extraContentsOfDoc)]) - const propertiesofDoc = InfoState('You can also access the properties of a doc through the double arrows in the top right or the single arrow on the right edge of the screen', {}, 'dash-properties-pane.gif', [ - this.createNextButton(contentsofDoc), - ]); + const propertiesofDoc = InfoState("You can also access the properties of a doc through the double arrows in the top right or the single arrow on the right edge of the screen", { + }, + 'dash-properties-pane.gif', + [this.createNextButton(contentsofDoc)]) - this.tutorialStates.editingDocuments = InfoState('Want to learn how to edit a document? Either left or right click the document', {}, 'document-chrome.png', [this.createNextButton(propertiesofDoc)]); - return this.tutorialStates.start; + this.tutorialStates.editingDocuments = InfoState("Want to learn how to edit a document? Either left or right click the document", { + }, + 'document-chrome.png', + [this.createNextButton(propertiesofDoc)]) + return this.tutorialStates.start }; + render() { if (!this.currState) return null; - + return ( - ); } -} +} \ No newline at end of file -- cgit v1.2.3-70-g09d2