Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(import): github import wizard #6507

Merged
merged 28 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions editor/src/components/editor/action-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ import type { Optic } from '../../core/shared/optics/optics'
import { makeOptic } from '../../core/shared/optics/optics'
import type { ElementPathTrees } from '../../core/shared/element-path-tree'
import { assertNever } from '../../core/shared/utils'
import type {
ImportOperation,
ImportOperationAction,
} from '../../core/shared/import/import-operation-types'
import type { ProjectRequirements } from '../../core/shared/import/proejct-health-check/utopia-requirements-types'
export { isLoggedIn, loggedInUser, notLoggedIn } from '../../common/user'
export type { LoginState, UserDetails } from '../../common/user'

Expand Down Expand Up @@ -997,6 +1002,22 @@ export interface UpdateGithubOperations {
type: GithubOperationType
}

export interface UpdateImportOperations {
action: 'UPDATE_IMPORT_OPERATIONS'
operations: ImportOperation[]
type: ImportOperationAction
}

export interface UpdateProjectRequirements {
action: 'UPDATE_PROJECT_REQUIREMENTS'
requirements: Partial<ProjectRequirements>
}

export interface SetImportWizardOpen {
action: 'SET_IMPORT_WIZARD_OPEN'
open: boolean
}

export interface SetRefreshingDependencies {
action: 'SET_REFRESHING_DEPENDENCIES'
value: boolean
Expand Down Expand Up @@ -1354,6 +1375,9 @@ export type EditorAction =
| UpdateAgainstGithub
| SetImageDragSessionState
| UpdateGithubOperations
| UpdateImportOperations
| UpdateProjectRequirements
| SetImportWizardOpen
| UpdateBranchContents
| SetRefreshingDependencies
| ApplyCommandsAction
Expand Down
35 changes: 35 additions & 0 deletions editor/src/components/editor/actions/action-creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ import type {
ToggleDataCanCondense,
UpdateMetadataInEditorState,
SetErrorBoundaryHandling,
SetImportWizardOpen,
UpdateImportOperations,
UpdateProjectRequirements,
} from '../action-types'
import type { InsertionSubjectWrapper, Mode } from '../editor-modes'
import { EditorModes, insertionSubject } from '../editor-modes'
Expand Down Expand Up @@ -268,6 +271,11 @@ import type { Collaborator } from '../../../core/shared/multiplayer'
import type { PageTemplate } from '../../canvas/remix/remix-utils'
import type { Bounds } from 'utopia-vscode-common'
import type { ElementPathTrees } from '../../../core/shared/element-path-tree'
import type {
ImportOperation,
ImportOperationAction,
} from '../../../core/shared/import/import-operation-types'
import type { ProjectRequirements } from '../../../core/shared/import/proejct-health-check/utopia-requirements-types'

export function clearSelection(): EditorAction {
return {
Expand Down Expand Up @@ -1591,6 +1599,33 @@ export function resetCanvas(): ResetCanvas {
}
}

export function updateImportOperations(
operations: ImportOperation[],
type: ImportOperationAction,
): UpdateImportOperations {
return {
action: 'UPDATE_IMPORT_OPERATIONS',
operations: operations,
type: type,
}
}

export function updateProjectRequirements(
requirements: Partial<ProjectRequirements>,
): UpdateProjectRequirements {
return {
action: 'UPDATE_PROJECT_REQUIREMENTS',
requirements: requirements,
}
}

export function setImportWizardOpen(open: boolean): SetImportWizardOpen {
return {
action: 'SET_IMPORT_WIZARD_OPEN',
open: open,
}
}

export function setFilebrowserDropTarget(target: string | null): SetFilebrowserDropTarget {
return {
action: 'SET_FILEBROWSER_DROPTARGET',
Expand Down
3 changes: 3 additions & 0 deletions editor/src/components/editor/actions/action-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ export function isTransientAction(action: EditorAction): boolean {
case 'RESET_ONLINE_STATE':
case 'INCREASE_ONLINE_STATE_FAILURE_COUNT':
case 'SET_ERROR_BOUNDARY_HANDLING':
case 'SET_IMPORT_WIZARD_OPEN':
case 'UPDATE_IMPORT_OPERATIONS':
case 'UPDATE_PROJECT_REQUIREMENTS':
return true

case 'TRUE_UP_ELEMENTS':
Expand Down
2 changes: 2 additions & 0 deletions editor/src/components/editor/actions/actions.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ describe('UPDATE_FROM_WORKER', () => {
updateToCheck,
startingEditorState,
defaultUserState,
NO_OP,
)

// Check that the model hasn't changed, because of the stale revised time.
Expand Down Expand Up @@ -1180,6 +1181,7 @@ describe('UPDATE_FROM_WORKER', () => {
updateToCheck,
startingEditorState,
defaultUserState,
NO_OP,
)

// Get the same values that we started with but from the updated editor state.
Expand Down
82 changes: 78 additions & 4 deletions editor/src/components/editor/actions/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ import type {
ToggleDataCanCondense,
UpdateMetadataInEditorState,
SetErrorBoundaryHandling,
SetImportWizardOpen,
UpdateImportOperations,
UpdateProjectRequirements,
} from '../action-types'
import { isAlignment, isLoggedIn } from '../action-types'
import type { Mode } from '../editor-modes'
Expand Down Expand Up @@ -630,6 +633,13 @@ import { getNavigatorTargetsFromEditorState } from '../../navigator/navigator-ut
import { getParseCacheOptions } from '../../../core/shared/parse-cache-utils'
import { applyValuesAtPath } from '../../canvas/commands/adjust-number-command'
import { styleP } from '../../inspector/inspector-common'
import { getUpdateOperationResult } from '../../../core/shared/import/import-operation-service'
import {
notifyCheckingRequirement,
notifyResolveRequirement,
updateRequirements,
} from '../../../core/shared/import/proejct-health-check/utopia-requirements-service'
import { RequirementResolutionResult } from '../../../core/shared/import/proejct-health-check/utopia-requirements-types'

export const MIN_CODE_PANE_REOPEN_WIDTH = 100

Expand Down Expand Up @@ -1033,6 +1043,9 @@ export function restoreEditorState(
githubSettings: currentEditor.githubSettings,
imageDragSessionState: currentEditor.imageDragSessionState,
githubOperations: currentEditor.githubOperations,
importOperations: currentEditor.importOperations,
projectRequirements: currentEditor.projectRequirements,
importWizardOpen: currentEditor.importWizardOpen,
branchOriginContents: currentEditor.branchOriginContents,
githubData: currentEditor.githubData,
refreshingDependencies: currentEditor.refreshingDependencies,
Expand Down Expand Up @@ -1630,19 +1643,44 @@ function createStoryboardFileWithPlaceholderContents(
}

export function createStoryboardFileIfNecessary(
dispatch: EditorDispatch,
projectContents: ProjectContentTreeRoot,
createPlaceholder: 'create-placeholder' | 'skip-creating-placeholder',
): ProjectContentTreeRoot {
notifyCheckingRequirement(dispatch, 'storyboard', 'Checking for storyboard.js')
const storyboardFile = getProjectFileByFilePath(projectContents, StoryboardFilePath)
if (storyboardFile != null) {
notifyResolveRequirement(
dispatch,
'storyboard',
RequirementResolutionResult.Found,
'Storyboard.js found',
)
return projectContents
}

return (
const result =
createStoryboardFileIfRemixProject(projectContents) ??
createStoryboardFileIfMainComponentPresent(projectContents) ??
createStoryboardFileWithPlaceholderContents(projectContents, createPlaceholder)
)

if (result == projectContents) {
notifyResolveRequirement(
dispatch,
'storyboard',
RequirementResolutionResult.Partial,
'Storyboard.js skipped',
)
} else {
notifyResolveRequirement(
dispatch,
'storyboard',
RequirementResolutionResult.Fixed,
'Storyboard.js created',
)
}

return result
}

// JS Editor Actions:
Expand Down Expand Up @@ -2232,6 +2270,34 @@ export const UPDATE_FNS = {
githubOperations: operations,
}
},
UPDATE_IMPORT_OPERATIONS: (action: UpdateImportOperations, editor: EditorModel): EditorModel => {
const resultImportOperations = getUpdateOperationResult(
editor.importOperations,
action.operations,
action.type,
)
return {
...editor,
importOperations: resultImportOperations,
}
},
UPDATE_PROJECT_REQUIREMENTS: (
action: UpdateProjectRequirements,
editor: EditorModel,
dispatch: EditorDispatch,
): EditorModel => {
const result = updateRequirements(dispatch, editor.projectRequirements, action.requirements)
return {
...editor,
projectRequirements: result,
}
},
SET_IMPORT_WIZARD_OPEN: (action: SetImportWizardOpen, editor: EditorModel): EditorModel => {
return {
...editor,
importWizardOpen: action.open,
}
},
SET_REFRESHING_DEPENDENCIES: (
action: SetRefreshingDependencies,
editor: EditorModel,
Expand Down Expand Up @@ -3950,6 +4016,7 @@ export const UPDATE_FNS = {
action: UpdateFromWorker,
editor: EditorModel,
userState: UserState,
dispatch: EditorDispatch,
): EditorModel => {
let workingProjectContents: ProjectContentTreeRoot = editor.projectContents
let anyParsedUpdates: boolean = false
Expand Down Expand Up @@ -3986,6 +4053,7 @@ export const UPDATE_FNS = {
return {
...editor,
projectContents: createStoryboardFileIfNecessary(
dispatch,
workingProjectContents,
// If we are in the process of cloning a Github repository, do not create placeholder Storyboard
userState.githubState.gitRepoToLoad != null
Expand Down Expand Up @@ -4811,7 +4879,11 @@ export const UPDATE_FNS = {
propertyControlsInfo: action.propertyControlsInfo,
}
},
UPDATE_TEXT: (action: UpdateText, editorStore: EditorStoreUnpatched): EditorStoreUnpatched => {
UPDATE_TEXT: (
action: UpdateText,
editorStore: EditorStoreUnpatched,
dispatch: EditorDispatch,
): EditorStoreUnpatched => {
const { textProp } = action
// This flag is useful when editing conditional expressions:
// if the edited element is a js expression AND the content is still between curly brackets after editing,
Expand Down Expand Up @@ -5009,6 +5081,7 @@ export const UPDATE_FNS = {
updateFromWorker(workerUpdates),
withFileChanges.unpatchedEditor,
withFileChanges.userState,
dispatch,
)
return {
...withFileChanges,
Expand Down Expand Up @@ -5623,7 +5696,7 @@ export const UPDATE_FNS = {
requestedNpmDependency('tailwindcss', tailwindVersion.version),
requestedNpmDependency('postcss', postcssVersion.version),
]
void fetchNodeModules(updatedNpmDeps, builtInDependencies).then(
void fetchNodeModules(dispatch, updatedNpmDeps, builtInDependencies).then(
(fetchNodeModulesResult) => {
const loadedPackagesStatus = createLoadedPackageStatusMapFromDependencies(
updatedNpmDeps,
Expand Down Expand Up @@ -6333,6 +6406,7 @@ export async function load(
const migratedModel = applyMigrations(model)
const npmDependencies = dependenciesWithEditorRequirements(migratedModel.projectContents)
const fetchNodeModulesResult = await fetchNodeModules(
dispatch,
npmDependencies,
builtInDependencies,
retryFetchNodeModules,
Expand Down
12 changes: 10 additions & 2 deletions editor/src/components/editor/editor-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import {
navigatorTargetsSelector,
navigatorTargetsSelectorNavigatorTargets,
} from '../navigator/navigator-utils'
import { ImportWizard } from './import-wizard/import-wizard'

const liveModeToastId = 'play-mode-toast'

Expand Down Expand Up @@ -520,6 +521,7 @@ export const EditorComponentInner = React.memo((props: EditorProps) => {
<ProjectForkFlow />
<LockedOverlay />
<SharingDialog />
<ImportWizard />
</SimpleFlexRow>
{portalTarget != null
? ReactDOM.createPortal(<ComponentPickerContextMenu />, portalTarget)
Expand Down Expand Up @@ -683,6 +685,12 @@ const LockedOverlay = React.memo(() => {
'LockedOverlay refreshingDependencies',
)

const importWizardOpen = useEditorState(
Substores.restOfEditor,
(store) => store.editor.importWizardOpen,
'LockedOverlay importWizardOpen',
)

const forking = useEditorState(
Substores.restOfEditor,
(store) => store.editor.forking,
Expand All @@ -699,8 +707,8 @@ const LockedOverlay = React.memo(() => {
`

const locked = React.useMemo(() => {
return editorLocked || refreshingDependencies || forking
}, [editorLocked, refreshingDependencies, forking])
return (editorLocked || refreshingDependencies || forking) && !importWizardOpen
}, [editorLocked, refreshingDependencies, forking, importWizardOpen])

const dialogContent = React.useMemo((): string | null => {
if (refreshingDependencies) {
Expand Down
Loading
Loading