Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -39,48 +39,41 @@ function JoinProjectForm({
<ProjectModalHeading title="Join an existing project" />
<ProjectModalSubHeading title="You will need to sync with a peer to get started" />
<ProjectModalContentSpacer>
<ProjectModalContent>
<ValidatingFormInput
value={projectSecret}
onChange={onSecretChange}
invalidInput={invalidText}
errorText={invalidText}
label="Project Invitation Secret"
helpText="Paste the 5 word secret you received from the project host"
/>
</ProjectModalContent>
<ProjectModalContent>
{/* @ts-ignore */}
<ValidatingFormInput
value={projectSecret}
onChange={onSecretChange}
invalidInput={invalidText}
errorText={invalidText}
label="Project Invitation Secret"
helpText="Paste the 5 word secret you received from the project host"
/>
</ProjectModalContent>
</ProjectModalContentSpacer>
<ProjectModalButton text={validateButtonContent} onClick={onValidate} />
</div>
)
}

function ProjectJoinFollowUp({ onDone, peerFound, checkDone }) {
function ProjectJoinFollowUp({ onDone, checkDone }) {
return (
<div
className={`project-join-follow-up ${
checkDone ? 'project-join-check-is-done' : ''
}`}
>
<div>
<ProjectModalHeading
title={
peerFound
? 'Project joined successfully'
: 'Project has been queued for syncing'
}
/>
{!peerFound && (
<ProjectModalHeading title="Project has been queued for syncing" />
<ProjectModalSubHeading title="In order to join this project, you and a peer must simultaneously open the app." />
)}
</div>
<ProjectModalContent>
<div className="project-join-follow-up-content-wrapper">
{peerFound
? 'Peers in this project were found so now you will get synced with them.'
: `If a peer is found, you are likely to be able to immediately begin to access the project, although a short sync period in the queue may be required before you can access it.`}
</div>
</ProjectModalContent>
<ProjectModalContent>
<div className="project-join-follow-up-content-wrapper">
If a peer is found, you are likely to be able to immediately begin to
access the project, although a short sync period in the queue may be
required before you can access it.
</div>
</ProjectModalContent>
<ProjectModalButton text="I understand" onClick={onDone} />
</div>
)
Expand All @@ -95,7 +88,6 @@ export default function JoinProjectModal({
setProjectSecret('')
setValidatingSecret(false)
setInvalidText('')
setPeerFound(false)
setCheckDone(false)
}
const onValidate = async () => {
Expand All @@ -105,12 +97,12 @@ export default function JoinProjectModal({
}
setValidatingSecret(true)
try {
const peerWasFound = await onJoinProject(projectSecret)
setPeerFound(peerWasFound)
await onJoinProject(projectSecret)
setCheckDone(true)
setValidatingSecret(false)
} catch (e) {
console.log(e)
// TODO: add better detail here
setInvalidText('There was an error while joining project: ' + e.message)
}
}
Expand All @@ -120,7 +112,6 @@ export default function JoinProjectModal({
}

const [checkDone, setCheckDone] = useState(false)
const [peerFound, setPeerFound] = useState(true)
const [projectSecret, setProjectSecret] = useState('')
const [invalidText, setInvalidText] = useState('')

Expand All @@ -132,7 +123,10 @@ export default function JoinProjectModal({
setProjectSecret(val)
if (!val) {
setInvalidText('')
} else if (val.split(' ').length !== 5 || !val.split(' ').every(word => word.length)) {
} else if (
val.split(' ').length !== 5 ||
!val.split(' ').every((word) => word.length)
) {
setInvalidText('Secret must be 5 words.')
}
}
Expand All @@ -144,14 +138,9 @@ export default function JoinProjectModal({
onClose={onDone}
className="join-project-modal-wrapper"
>
<ProjectJoinFollowUp
onDone={onDone}
checkDone={checkDone}
peerFound={peerFound}
/>
<ProjectJoinFollowUp onDone={onDone} checkDone={checkDone} />
<JoinProjectForm
checkDone={checkDone}
peerFound={peerFound}
projectSecret={projectSecret}
onSecretChange={onSecretChange}
invalidText={invalidText}
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/PendingProjects/PendingProjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ function PendingProjects({
pendingProjects,
fetchProjectMeta,
setPendingProjects,
deactivateApp,
deactivateProject,
}: {
pendingProjects: string[]
fetchProjectMeta: any
setPendingProjects: React.Dispatch<React.SetStateAction<string[]>>
deactivateApp: (appId: string, cellId: string) => Promise<void>
deactivateProject: (appId: string, cellId: string) => Promise<void>
}) {
const [expanded, setExpanded] = useState(false)
const [passphrases, setPassphrases] = useState<AppInfoStore>({})
Expand Down Expand Up @@ -77,7 +77,7 @@ function PendingProjects({
}, [JSON.stringify(pendingProjects)])

const cancelProjectJoin = async (appId: string, cellId: string) => {
await deactivateApp(appId, cellId)
await deactivateProject(appId, cellId)
// remove this project from pendingProjects
setPendingProjects((pendingProjects: string[]) => {
return pendingProjects.filter((c) => c !== cellId)
Expand Down
25 changes: 10 additions & 15 deletions web/src/migrating/import/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ import { cellIdFromString } from '../../utils'
import { RootState } from '../../redux/reducer'
import { AllProjectsDataExport } from '../export'
import { createWhoami } from '../../redux/persistent/profiles/who-am-i/actions'
import { installProjectApp } from '../../projects/installProjectApp'
import { installProject } from '../../projects/installProject'
import { joinProjectCellId } from '../../redux/persistent/cells/actions'
import { createProfilesZomeApi, createProjectsZomeApi } from './zomeApiCreators'
import { installProjectAppAndImport } from './installProjectAppAndImport'
import { createProfilesZomeApi } from './zomeApiCreators'
import { installProjectAndImport } from './installProjectAndImport'
import ProfilesZomeApi from '../../api/profilesApi'
import ProjectsZomeApi from '../../api/projectsApi'
import { internalJoinProject } from '../../projects/joinProject'

export async function internalImportProjectsData(
// dependencies
profilesZomeApi: ProfilesZomeApi,
projectsZomeApi: ProjectsZomeApi,
_installProjectAppAndImport: typeof installProjectAppAndImport,
_installProjectApp: typeof installProjectApp,
_installProjectAndImport: typeof installProjectAndImport,
_installProject: typeof installProject,
store: any,
// main input data and callbacks
migrationData: string,
Expand Down Expand Up @@ -60,12 +59,11 @@ export async function internalImportProjectsData(
// one completes
for await (let projectData of projectsToMigrate) {
const passphrase = projectData.projectMeta.passphrase
await _installProjectAppAndImport(
await _installProjectAndImport(
myAgentPubKey,
projectData,
passphrase,
store.dispatch,
projectsZomeApi
)
stepsSoFar++
onStep(stepsSoFar, totalSteps)
Expand All @@ -74,8 +72,7 @@ export async function internalImportProjectsData(
// join each project that has already been migrated by a peer
for await (let projectData of migratedProjectsToJoin) {
const passphrase = projectData.projectMeta.passphrase
const [cellIdString, _, __] = await _installProjectApp(passphrase)
store.dispatch(joinProjectCellId(cellIdString))
await internalJoinProject(passphrase, store.dispatch, _installProject)
stepsSoFar++
onStep(stepsSoFar, totalSteps)
}
Expand All @@ -88,12 +85,10 @@ export default async function importProjectsData(
) {
const appWebsocket = await getAppWs()
const profilesZomeApi = createProfilesZomeApi(appWebsocket)
const projectsZomeApi = createProjectsZomeApi(appWebsocket)
return internalImportProjectsData(
profilesZomeApi,
projectsZomeApi,
installProjectAppAndImport,
installProjectApp,
installProjectAndImport,
installProject,
store,
migrationData,
onStep
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import ProjectsZomeApi from '../../api/projectsApi'
import { installProjectApp } from '../../projects/installProjectApp'
import { setMember } from '../../redux/persistent/projects/members/actions'
import { simpleCreateProjectMeta } from '../../redux/persistent/projects/project-meta/actions'
import { finalizeCreateProject } from '../../projects/createProject'
import { getAppWs } from '../../hcWebsockets'
import { installProject } from '../../projects/installProject'
import { AgentPubKeyB64 } from '../../types/shared'
import { cellIdFromString } from '../../utils'
import { ProjectExportDataV1 } from '../export'
import { cloneProjectMeta } from './cloneFunctions'
import { createActionHashMapAndImportProjectData } from './createActionHashMapAndImportProjectData'

export async function internalInstallProjectAppAndImport(
export async function internalInstallProjectAndImport(
agentAddress: AgentPubKeyB64,
projectData: ProjectExportDataV1,
passphrase: string,
dispatch: any,
_installProjectApp: typeof installProjectApp,
_importProjectData: typeof createActionHashMapAndImportProjectData,
iInstallProject: typeof installProject,
iCreateActionHashMapAndImportProjectData: typeof createActionHashMapAndImportProjectData,
iFinalizeCreateProject: typeof finalizeCreateProject,
projectsZomeApi: ProjectsZomeApi
) {

// first step is to install the dna
const [projectsCellIdString] = await _installProjectApp(passphrase)
const cellId = cellIdFromString(projectsCellIdString)
const [cellIdString] = await iInstallProject(passphrase)

// next step is to import the bulk of the data into that project
const oldToNewAddressMaps = await _importProjectData(
const oldToNewAddressMaps = await iCreateActionHashMapAndImportProjectData(
projectData,
projectsCellIdString,
cellIdString,
dispatch
)

Expand All @@ -39,32 +38,31 @@ export async function internalInstallProjectAppAndImport(
passphrase
)(projectData.projectMeta)
delete projectMeta.actionHash
const simpleCreatedProjectMeta = await projectsZomeApi.projectMeta.simpleCreateProjectMeta(
cellId,
projectMeta
)
dispatch(
simpleCreateProjectMeta(projectsCellIdString, simpleCreatedProjectMeta)
await iFinalizeCreateProject(
cellIdString,
projectMeta,
agentAddress,
dispatch,
projectsZomeApi
)
// this registers the agent to redux as a member of the project
dispatch(setMember(projectsCellIdString, { agentPubKey: agentAddress }))

}

export async function installProjectAppAndImport(
export async function installProjectAndImport(
agentAddress: AgentPubKeyB64,
projectData: ProjectExportDataV1,
passphrase: string,
dispatch: any,
projectsZomeApi: ProjectsZomeApi
) {
internalInstallProjectAppAndImport(
const appWebsocket = await getAppWs()
const projectsZomeApi = new ProjectsZomeApi(appWebsocket)
return internalInstallProjectAndImport(
agentAddress,
projectData,
passphrase,
dispatch,
installProjectApp,
installProject,
createActionHashMapAndImportProjectData,
finalizeCreateProject,
projectsZomeApi
)
}
65 changes: 65 additions & 0 deletions web/src/projects/createProject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { AgentPubKeyB64 } from '@holochain/client'
import ProjectsZomeApi from '../api/projectsApi'
import { setMember } from '../redux/persistent/projects/members/actions'
import { simpleCreateProjectMeta } from '../redux/persistent/projects/project-meta/actions'
import { ProjectMeta } from '../types'
import { cellIdFromString } from '../utils'
import { installProject } from './installProject'
import { CellIdString } from '../types/shared'

export async function finalizeCreateProject(
cellIdString: CellIdString,
projectMeta: ProjectMeta,
agentAddress: AgentPubKeyB64,
dispatch: any,
projectsZomeApi: ProjectsZomeApi
) {
const cellId = cellIdFromString(cellIdString)
const createdProjectMeta = await projectsZomeApi.projectMeta.simpleCreateProjectMeta(
cellId,
projectMeta
)
dispatch(simpleCreateProjectMeta(cellIdString, createdProjectMeta))
// because we are acting optimistically,
// we will directly set ourselves as a member of this cell
dispatch(setMember(cellIdString, { agentPubKey: agentAddress }))
}

export async function internalCreateProject(
passphrase: string,
projectMeta: ProjectMeta,
agentAddress: AgentPubKeyB64,
dispatch: any,
iInstallProject: typeof installProject,
projectsZomeApi: ProjectsZomeApi
) {
const startTime = Date.now()
const [cellIdString] = await iInstallProject(passphrase)
await finalizeCreateProject(
cellIdString,
projectMeta,
agentAddress,
dispatch,
projectsZomeApi
)
const endTime = Date.now()
console.log('duration in MS over createProject ', endTime - startTime)
return cellIdString
}

export async function createProject(
passphrase: string,
projectMeta: ProjectMeta,
agentAddress: AgentPubKeyB64,
dispatch: any,
projectsZomeApi: ProjectsZomeApi
) {
return internalCreateProject(
passphrase,
projectMeta,
agentAddress,
dispatch,
installProject,
projectsZomeApi
)
}
17 changes: 17 additions & 0 deletions web/src/projects/deactivateProject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AdminWebsocket } from '@holochain/client'
import { removeProjectCellId } from '../redux/persistent/cells/actions'
import { CellIdString } from '../types/shared'

export async function deactivateProject(
appId: string,
cellId: CellIdString,
dispatch: any,
adminWs: AdminWebsocket
) {
// deactivate it in holochain
await adminWs.disableApp({
installed_app_id: appId,
})
// remove it from our redux state
dispatch(removeProjectCellId(cellId))
}
Loading