diff --git a/web/src/components/JoinProjectModal/JoinProjectModal.js b/web/src/components/JoinProjectModal/JoinProjectModal.tsx
similarity index 70%
rename from web/src/components/JoinProjectModal/JoinProjectModal.js
rename to web/src/components/JoinProjectModal/JoinProjectModal.tsx
index 8c5879290..535cda7e5 100644
--- a/web/src/components/JoinProjectModal/JoinProjectModal.js
+++ b/web/src/components/JoinProjectModal/JoinProjectModal.tsx
@@ -39,23 +39,24 @@ function JoinProjectForm({
-
-
-
+
+ {/* @ts-ignore */}
+
+
)
}
-function ProjectJoinFollowUp({ onDone, peerFound, checkDone }) {
+function ProjectJoinFollowUp({ onDone, checkDone }) {
return (
-
- {!peerFound && (
+
- )}
-
-
- {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.`}
-
-
+
+
+ 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.
+
+
)
@@ -95,7 +88,6 @@ export default function JoinProjectModal({
setProjectSecret('')
setValidatingSecret(false)
setInvalidText('')
- setPeerFound(false)
setCheckDone(false)
}
const onValidate = async () => {
@@ -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)
}
}
@@ -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('')
@@ -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.')
}
}
@@ -144,14 +138,9 @@ export default function JoinProjectModal({
onClose={onDone}
className="join-project-modal-wrapper"
>
-
+
>
- deactivateApp: (appId: string, cellId: string) => Promise
+ deactivateProject: (appId: string, cellId: string) => Promise
}) {
const [expanded, setExpanded] = useState(false)
const [passphrases, setPassphrases] = useState({})
@@ -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)
diff --git a/web/src/migrating/import/import.ts b/web/src/migrating/import/import.ts
index 726a93dd1..d9d28ab8d 100644
--- a/web/src/migrating/import/import.ts
+++ b/web/src/migrating/import/import.ts
@@ -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,
@@ -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)
@@ -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)
}
@@ -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
diff --git a/web/src/migrating/import/installProjectAppAndImport.ts b/web/src/migrating/import/installProjectAndImport.ts
similarity index 50%
rename from web/src/migrating/import/installProjectAppAndImport.ts
rename to web/src/migrating/import/installProjectAndImport.ts
index a52e7c727..525035d2a 100644
--- a/web/src/migrating/import/installProjectAppAndImport.ts
+++ b/web/src/migrating/import/installProjectAndImport.ts
@@ -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
)
@@ -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
)
}
diff --git a/web/src/projects/createProject.ts b/web/src/projects/createProject.ts
new file mode 100644
index 000000000..30f475e20
--- /dev/null
+++ b/web/src/projects/createProject.ts
@@ -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
+ )
+}
diff --git a/web/src/projects/deactivateProject.ts b/web/src/projects/deactivateProject.ts
new file mode 100644
index 000000000..1f756fa9b
--- /dev/null
+++ b/web/src/projects/deactivateProject.ts
@@ -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))
+}
diff --git a/web/src/projects/installProject.ts b/web/src/projects/installProject.ts
new file mode 100644
index 000000000..06e77e4c7
--- /dev/null
+++ b/web/src/projects/installProject.ts
@@ -0,0 +1,60 @@
+import { AdminWebsocket, CellId, CellType } from '@holochain/client'
+import { getAdminWs, getAgentPubKey } from '../hcWebsockets'
+import { PROJECT_APP_PREFIX } from '../holochainConfig'
+import { passphraseToUid } from '../secrets'
+import { CellIdString } from '../types/shared'
+import { cellIdToString } from '../utils'
+
+export async function internalInstallProject(
+ passphrase: string,
+ adminWs: AdminWebsocket,
+): Promise<[CellIdString, CellId, string]> {
+ const uid = passphraseToUid(passphrase)
+ // add a bit of randomness so that
+ // the same passphrase can be tried multiple different times
+ // without conflicting
+ // in order to eventually find their peers
+ // note that this will leave a graveyard of deactivated apps for attempted
+ // joins
+ const installed_app_id = `${PROJECT_APP_PREFIX}-${Math.random()
+ .toString()
+ .slice(-6)}-${uid}`
+ const agent_key = getAgentPubKey()
+ if (!agent_key) {
+ throw new Error(
+ 'Cannot install a new project because no AgentPubKey is known locally'
+ )
+ }
+ // the dna hash HAS to act deterministically
+ // in order for the 'joining' of Projects to work
+ const happPath = window.require
+ ? await window.require('electron').ipcRenderer.invoke('getProjectsPath')
+ : './happ/workdir/projects/projects.happ'
+ // INSTALL
+ const installedApp = await adminWs.installApp({
+ agent_key,
+ installed_app_id,
+ // what to do about the membrane_proof?
+ membrane_proofs: {},
+ path: happPath,
+ network_seed: uid,
+ })
+ const cellInfo = Object.values(installedApp.cell_info)[0][0]
+ const cellId =
+ CellType.Provisioned in cellInfo
+ ? cellInfo[CellType.Provisioned].cell_id
+ : null
+ const cellIdString = cellIdToString(cellId)
+ await adminWs.enableApp({ installed_app_id })
+
+ //authorize zome calls for the new cell
+ await adminWs.authorizeSigningCredentials(cellId)
+ return [cellIdString, cellId, installed_app_id]
+}
+
+export async function installProject(
+ passphrase: string
+): Promise<[CellIdString, CellId, string]> {
+ const adminWs = await getAdminWs()
+ return internalInstallProject(passphrase, adminWs)
+}
diff --git a/web/src/projects/installProjectApp.ts b/web/src/projects/installProjectApp.ts
deleted file mode 100644
index b597a7554..000000000
--- a/web/src/projects/installProjectApp.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { CellId, CellType } from "@holochain/client"
-import { getAdminWs, getAgentPubKey } from "../hcWebsockets"
-import { PROJECT_APP_PREFIX } from "../holochainConfig"
-import { passphraseToUid } from "../secrets"
-import { CellIdString } from "../types/shared"
-import { cellIdToString } from "../utils"
-
-export async function installProjectApp(
- passphrase: string
- ): Promise<[CellIdString, CellId, string]> {
- const uid = passphraseToUid(passphrase)
- // add a bit of randomness so that
- // the same passphrase can be tried multiple different times
- // without conflicting
- // in order to eventually find their peers
- // note that this will leave a graveyard of deactivated apps for attempted
- // joins
- const installed_app_id = `${PROJECT_APP_PREFIX}-${Math.random()
- .toString()
- .slice(-6)}-${uid}`
- const adminWs = await getAdminWs()
- const agent_key = getAgentPubKey()
- if (!agent_key) {
- throw new Error(
- 'Cannot install a new project because no AgentPubKey is known locally'
- )
- }
- // the dna hash HAS to act deterministically
- // in order for the 'joining' of Projects to work
- const happPath = window.require
- ? await window.require('electron').ipcRenderer.invoke('getProjectsPath')
- : './happ/workdir/projects/projects.happ'
- console.log(happPath)
- // INSTALL
- const installedApp = await adminWs.installApp({
- agent_key,
- installed_app_id,
- // what to do about the membrane_proof?
- membrane_proofs: {},
- path: happPath,
- network_seed: uid,
- })
- const cellInfo = Object.values(installedApp.cell_info)[0][0]
- const cellId = (CellType.Provisioned in cellInfo) ? cellInfo[CellType.Provisioned].cell_id : null
- const cellIdString = cellIdToString(cellId)
- await adminWs.enableApp({ installed_app_id })
-
- //authorize zome calls for the new cell
- await adminWs.authorizeSigningCredentials(cellId)
- return [cellIdString, cellId, installed_app_id]
- }
\ No newline at end of file
diff --git a/web/src/projects/joinProject.ts b/web/src/projects/joinProject.ts
new file mode 100644
index 000000000..9d9341f52
--- /dev/null
+++ b/web/src/projects/joinProject.ts
@@ -0,0 +1,47 @@
+import { AppWebsocket, CellId } from '@holochain/client'
+import { installProject } from './installProject'
+import { PROJECTS_ZOME_NAME } from '../holochainConfig'
+import { getAgentPubKey } from '../hcWebsockets'
+import { joinProjectCellId } from '../redux/persistent/cells/actions'
+import { CellIdString } from '../types/shared'
+
+export async function internalJoinProject(
+ passphrase: string,
+ dispatch: any,
+ iInstallProject: typeof installProject
+) {
+ const [cellIdString, _cellId, _installedAppId] = await iInstallProject(
+ passphrase
+ )
+ // this will trigger the fetching of project meta
+ // checks and other things
+ dispatch(joinProjectCellId(cellIdString))
+ return cellIdString
+}
+
+export async function joinProject(
+ passphrase: string,
+ dispatch: any
+): Promise {
+ return internalJoinProject(passphrase, dispatch, installProject)
+}
+
+export function triggerJoinSignal(cellId: CellId, appWs: AppWebsocket) {
+ // trigger a side effect...
+ // this will let other project members know you're here
+ // without 'blocking' the thread or the UX
+ appWs
+ .callZome(
+ {
+ cap_secret: null,
+ cell_id: cellId,
+ zome_name: PROJECTS_ZOME_NAME,
+ fn_name: 'init_signal',
+ payload: null,
+ provenance: getAgentPubKey(), // FIXME: this will need correcting after holochain changes this
+ },
+ 50000
+ )
+ .then(() => console.log('succesfully triggered init_signal'))
+ .catch((e) => console.error('failed while triggering init_signal: ', e))
+}
diff --git a/web/src/routes/Dashboard/Dashboard.component.tsx b/web/src/routes/Dashboard/Dashboard.component.tsx
index 3575afe12..12a633440 100644
--- a/web/src/routes/Dashboard/Dashboard.component.tsx
+++ b/web/src/routes/Dashboard/Dashboard.component.tsx
@@ -44,9 +44,9 @@ export type DashboardDispatchProps = {
cellIdString: CellIdString
) => Promise
fetchEntryPointDetails: (cellIdString: CellIdString) => Promise
- joinProject: (passphrase: string) => Promise
- deactivateApp: (appId: string, cellId: CellIdString) => Promise
- importProject: (
+ joinProject: (passphrase: string) => Promise
+ deactivateProject: (appId: string, cellId: CellIdString) => Promise
+ installProjectAndImport: (
agentAddress: AgentPubKeyB64,
projectData: any,
passphrase: string
@@ -57,7 +57,7 @@ export type DashboardDispatchProps = {
export type DashboardProps = DashboardStateProps & DashboardDispatchProps
const Dashboard: React.FC = ({
- deactivateApp,
+ deactivateProject,
agentAddress,
cells,
projects,
@@ -68,7 +68,7 @@ const Dashboard: React.FC = ({
updateProjectMeta,
createProject,
joinProject,
- importProject,
+ installProjectAndImport,
setShowInviteMembersModal,
}) => {
const { setShowUpdateModal } = useContext(UpdateModalContext)
@@ -114,7 +114,7 @@ const Dashboard: React.FC = ({
const onJoinProject = (passphrase: string) => joinProject(passphrase)
const onImportProject = (projectData: any, passphrase: string) =>
- importProject(agentAddress, projectData, passphrase)
+ installProjectAndImport(agentAddress, projectData, passphrase)
const setSortBy = (sortBy) => () => {
setSelectedSort(sortBy)
@@ -230,7 +230,7 @@ const Dashboard: React.FC = ({
pendingProjects={pendingProjects}
fetchProjectMeta={fetchProjectMeta}
setPendingProjects={setPendingProjects}
- deactivateApp={deactivateApp}
+ deactivateProject={deactivateProject}
/>
)}
{!hasFetchedForAllProjects &&
diff --git a/web/src/routes/Dashboard/Dashboard.connector.ts b/web/src/routes/Dashboard/Dashboard.connector.ts
index fcd92dc3d..4a4ffeb67 100644
--- a/web/src/routes/Dashboard/Dashboard.connector.ts
+++ b/web/src/routes/Dashboard/Dashboard.connector.ts
@@ -1,25 +1,18 @@
import { connect } from 'react-redux'
-import { PROJECTS_ZOME_NAME } from '../../holochainConfig'
-import { getAdminWs, getAppWs, getAgentPubKey } from '../../hcWebsockets'
+import { getAdminWs, getAppWs } from '../../hcWebsockets'
import { fetchEntryPointDetails } from '../../redux/persistent/projects/entry-points/actions'
import {
fetchMembers,
- setMember,
} from '../../redux/persistent/projects/members/actions'
import {
- simpleCreateProjectMeta,
fetchProjectMeta,
updateProjectMeta,
} from '../../redux/persistent/projects/project-meta/actions'
import selectEntryPoints from '../../redux/persistent/projects/entry-points/select'
import { setActiveProject } from '../../redux/ephemeral/active-project/actions'
-import {
- joinProjectCellId,
- removeProjectCellId,
-} from '../../redux/persistent/cells/actions'
-import { installProjectAppAndImport } from '../../migrating/import/import'
+import { installProjectAndImport } from '../../migrating/import/installProjectAndImport'
import { openInviteMembersModal } from '../../redux/ephemeral/invite-members-modal/actions'
import ProjectsZomeApi from '../../api/projectsApi'
import { cellIdFromString } from '../../utils'
@@ -31,77 +24,9 @@ import Dashboard, {
} from './Dashboard.component'
import { LayeringAlgorithm, ProjectMeta } from '../../types'
import selectProjectMembersPresent from '../../redux/persistent/projects/realtime-info-signal/select'
-import { installProjectApp } from '../../projects/installProjectApp'
-
-async function createProject(
- passphrase: string,
- projectMeta: ProjectMeta,
- agentAddress: AgentPubKeyB64,
- dispatch: any
-) {
- const [cellIdString] = await installProjectApp(passphrase)
- const cellId = cellIdFromString(cellIdString)
- // because we are acting optimistically,
- // we will directly set ourselves as a member of this cell
- const appWebsocket = await getAppWs()
- const projectsZomeApi = new ProjectsZomeApi(appWebsocket)
- await dispatch(setMember(cellIdString, { agentPubKey: agentAddress }))
- const b1 = Date.now()
- const simpleCreatedProjectMeta = await projectsZomeApi.projectMeta.simpleCreateProjectMeta(
- cellId,
- projectMeta
- )
- await dispatch(
- simpleCreateProjectMeta(cellIdString, simpleCreatedProjectMeta)
- )
- const b2 = Date.now()
- console.log('duration in MS over createProjectMeta ', b2 - b1)
- return cellIdString
-}
-
-async function joinProject(passphrase: string, dispatch): Promise {
- // joinProject
- // join a DNA
- // then try to find a peer
- // either way, just push the project into the 'queue'
- const [cellIdString, cellId, installedAppId] = await installProjectApp(
- passphrase
- )
- const appWs = await getAppWs()
- // trigger a side effect...
- // this will let other project members know you're here
- // without 'blocking' the thread or the UX
- appWs
- .callZome(
- {
- cap_secret: null,
- cell_id: cellId,
- zome_name: PROJECTS_ZOME_NAME,
- fn_name: 'init_signal',
- payload: null,
- provenance: getAgentPubKey(), // FIXME: this will need correcting after holochain changes this
- },
- 50000
- )
- .then(() => console.log('succesfully triggered init_signal'))
- .catch((e) => console.error('failed while triggering init_signal: ', e))
- // this will trigger the fetching of project meta
- // checks and other things
- dispatch(joinProjectCellId(cellIdString))
- return false
-}
-
-async function deactivateApp(
- appId: string,
- cellId: CellIdString,
- dispatch: any
-) {
- const adminWs = await getAdminWs()
- await adminWs.disableApp({
- installed_app_id: appId,
- })
- await dispatch(removeProjectCellId(cellId))
-}
+import { deactivateProject } from '../../projects/deactivateProject'
+import { createProject } from '../../projects/createProject'
+import { joinProject, triggerJoinSignal } from '../../projects/joinProject'
// ACTUAL REDUX FUNCTIONS
@@ -137,8 +62,9 @@ function mapDispatchToProps(dispatch): DashboardDispatchProps {
setShowInviteMembersModal: (passphrase: string) => {
return dispatch(openInviteMembersModal(passphrase))
},
- deactivateApp: async (appId: string, cellId: CellIdString) => {
- return deactivateApp(appId, cellId, dispatch)
+ deactivateProject: async (appId: string, cellId: CellIdString) => {
+ const adminWs = await getAdminWs()
+ return deactivateProject(appId, cellId, dispatch, adminWs)
},
fetchEntryPointDetails: async (cellIdString: CellIdString) => {
const appWebsocket = await getAppWs()
@@ -165,12 +91,27 @@ function mapDispatchToProps(dispatch): DashboardDispatchProps {
)
return dispatch(fetchProjectMeta(cellIdString, projectMeta))
},
+ updateProjectMeta: async (
+ projectMeta: ProjectMeta,
+ actionHash: ActionHashB64,
+ cellIdString: CellIdString
+ ) => {
+ const appWebsocket = await getAppWs()
+ const projectsZomeApi = new ProjectsZomeApi(appWebsocket)
+ const cellId = cellIdFromString(cellIdString)
+ const updatedProjectMeta = await projectsZomeApi.projectMeta.update(
+ cellId,
+ { entry: projectMeta, actionHash }
+ )
+ return dispatch(updateProjectMeta(cellIdString, updatedProjectMeta))
+ },
createProject: async (
agentAddress: AgentPubKeyB64,
project: { name: string; image: string },
passphrase: string
) => {
- // matches the createProjectMeta fn and type signature
+ const appWs = await getAppWs()
+ const projectsZomeApi = new ProjectsZomeApi(appWs)
const projectMeta: ProjectMeta = {
...project, // name and image
passphrase,
@@ -181,27 +122,17 @@ function mapDispatchToProps(dispatch): DashboardDispatchProps {
topPriorityOutcomes: [],
isMigrated: null,
}
- await createProject(passphrase, projectMeta, agentAddress, dispatch)
+ await createProject(passphrase, projectMeta, agentAddress, dispatch, projectsZomeApi)
},
- updateProjectMeta: async (
- projectMeta: ProjectMeta,
- actionHash: ActionHashB64,
- cellIdString: CellIdString
- ) => {
- const appWebsocket = await getAppWs()
- const projectsZomeApi = new ProjectsZomeApi(appWebsocket)
+ joinProject: async (passphrase: string) => {
+ const appWs = await getAppWs()
+ const cellIdString = await joinProject(passphrase, dispatch)
const cellId = cellIdFromString(cellIdString)
- const updatedProjectMeta = await projectsZomeApi.projectMeta.update(
- cellId,
- { entry: projectMeta, actionHash }
- )
- return dispatch(updateProjectMeta(cellIdString, updatedProjectMeta))
- },
- joinProject: (passphrase: string) => {
- return joinProject(passphrase, dispatch)
+ triggerJoinSignal(cellId, appWs)
+ return cellIdString
},
- importProject: (agentAddress, projectData, passphrase) => {
- return installProjectAppAndImport(
+ installProjectAndImport: (agentAddress, projectData, passphrase) => {
+ return installProjectAndImport(
agentAddress,
projectData,
passphrase,
diff --git a/web/test/createProject.test.ts b/web/test/createProject.test.ts
new file mode 100644
index 000000000..99765710b
--- /dev/null
+++ b/web/test/createProject.test.ts
@@ -0,0 +1,28 @@
+import { finalizeCreateProject } from '../src/projects/createProject'
+import mockUnmigratedProjectMeta from './mockProjectMeta'
+
+
+describe('finalizeCreateProject', () => {
+ it('should dispatch actions', () => {
+
+ const dispatch = jest.fn()
+ // const cellIdString = 'testCellIdString'
+ // await finalizeCreateProject()
+
+ // expect(dispatch).toHaveBeenCalledTimes(2)
+ // expect(dispatch).toHaveBeenNthCalledWith(1, {
+ // type: 'SIMPLE_CREATE_PROJECT_META',
+ // payload: mockUnmigratedProjectMeta,
+ // meta: { cellIdString: mockCellIdString },
+ // })
+ // expect(dispatch).toHaveBeenNthCalledWith(2, {
+ // type: 'SET_MEMBER',
+ // payload: {
+ // cellIdString: mockCellIdString,
+ // member: {
+ // agentPubKey: 'testAgentAddress',
+ // },
+ // },
+ // })
+ })
+})
\ No newline at end of file
diff --git a/web/test/import.test.ts b/web/test/import.test.ts
index 883f1cd73..1b4d05e4c 100644
--- a/web/test/import.test.ts
+++ b/web/test/import.test.ts
@@ -6,7 +6,7 @@ import { OutcomeMember, ProjectMeta, Tag } from '../src/types'
import { WireRecord } from '../src/api/hdkCrud'
import mockUnmigratedProjectMeta from './mockProjectMeta'
import mockBaseRootState from './mockRootState'
-import { installProjectApp as _installProjectApp } from '../src/projects/installProjectApp'
+import { installProject as _installProject } from '../src/projects/installProject'
import { getAppWs as _getAppWs } from '../src/hcWebsockets'
import { AppWebsocket } from '@holochain/client'
import { RootState } from '../src/redux/reducer'
@@ -41,12 +41,13 @@ import {
internalCreateActionHashMapAndImportProjectData,
} from '../src/migrating/import/createActionHashMapAndImportProjectData'
import {
- installProjectAppAndImport as _installProjectAppAndImport,
- internalInstallProjectAppAndImport,
-} from '../src/migrating/import/installProjectAppAndImport'
+ installProjectAndImport as _installProjectAndImport,
+ internalInstallProjectAndImport,
+} from '../src/migrating/import/installProjectAndImport'
import mockWhoami from './mockWhoami'
import { cellIdFromString } from '../src/utils'
import mockActionHashMaps from './mockActionHashMaps'
+import { finalizeCreateProject as _finalizeCreateProject } from '../src/projects/createProject'
let store: any // too complex of a type to mock
@@ -54,8 +55,9 @@ let createProfilesZomeApi: typeof _createProfilesZomeApi
let createProjectsZomeApi: typeof _createProjectsZomeApi
let profilesZomeApi: ProfilesZomeApi
let projectsZomeApi: ProjectsZomeApi
-let installProjectAppAndImport: typeof _installProjectAppAndImport
-let installProjectApp: typeof _installProjectApp
+let installProjectAndImport: typeof _installProjectAndImport
+let installProject: typeof _installProject
+let finalizeCreateProject: typeof _finalizeCreateProject
let createActionHashMapAndImportProjectData: typeof _createActionHashMapAndImportProjectData
let baseRootState: typeof mockBaseRootState
let mockGetState: () => RootState
@@ -118,14 +120,16 @@ beforeEach(() => {
})
profilesZomeApi = createProfilesZomeApi(mockAppWs)
projectsZomeApi = createProjectsZomeApi(mockAppWs)
- installProjectAppAndImport = jest.fn()
+ installProjectAndImport = jest.fn()
mockCellIdString =
'132,45,36,204,129,221,8,19,206,244,229,30,210,95,157,234,241,47,13,85,105,207,55,138,160,87,204,162,244,122,186,195,125,254,5,185,165,224,66[:cell_id_divider:]132,32,36,97,138,27,24,136,8,80,164,189,194,243,82,224,72,205,215,225,2,27,126,146,190,40,102,187,244,75,191,172,155,196,247,226,220,92,1'
- installProjectApp = jest
+ installProject = jest
.fn()
.mockResolvedValue([mockCellIdString, ['abc'], 'testString'])
+ finalizeCreateProject = jest.fn()
+
createActionHashMapAndImportProjectData = jest.fn().mockResolvedValue({
tagActionHashMap: {},
outcomeActionHashMap: {},
@@ -153,9 +157,8 @@ describe('importProjectsData()', () => {
it('successfully parses and imports project data and user profile', async () => {
await internalImportProjectsData(
profilesZomeApi,
- projectsZomeApi,
- installProjectAppAndImport,
- installProjectApp,
+ installProjectAndImport,
+ installProject,
store,
mockMigrationData,
onStep
@@ -174,17 +177,16 @@ describe('importProjectsData()', () => {
sampleGoodDataExport.projects[1].projectMeta.isMigrated
).not.toBeNull()
- expect(installProjectAppAndImport).toHaveBeenCalledTimes(1)
- expect(installProjectAppAndImport).toHaveBeenCalledWith(
+ expect(installProjectAndImport).toHaveBeenCalledTimes(1)
+ expect(installProjectAndImport).toHaveBeenCalledWith(
'testAgentAddress',
sampleGoodDataExport.projects[0],
sampleGoodDataExport.projects[0].projectMeta.passphrase,
store.dispatch,
- projectsZomeApi
)
- expect(installProjectApp).toHaveBeenCalledTimes(1)
- expect(installProjectApp).toHaveBeenCalledWith(
+ expect(installProject).toHaveBeenCalledTimes(1)
+ expect(installProject).toHaveBeenCalledWith(
sampleGoodDataExport.projects[1].projectMeta.passphrase
)
@@ -217,9 +219,8 @@ describe('importProjectsData()', () => {
try {
await internalImportProjectsData(
profilesZomeApi,
- projectsZomeApi,
- installProjectAppAndImport,
- installProjectApp,
+ installProjectAndImport,
+ installProject,
store,
mockMigrationData,
onStep
@@ -233,9 +234,8 @@ describe('importProjectsData()', () => {
try {
await internalImportProjectsData(
profilesZomeApi,
- projectsZomeApi,
- installProjectAppAndImport,
- installProjectApp,
+ installProjectAndImport,
+ installProject,
store,
mockMigrationData,
onStep
@@ -249,21 +249,22 @@ describe('importProjectsData()', () => {
})
})
-describe('installProjectAppAndImport()', () => {
+describe('installProjectAndImport()', () => {
const agentAddress = 'testAgentAddress'
it('installs DNA and imports project into new cell', async () => {
- await internalInstallProjectAppAndImport(
+ await internalInstallProjectAndImport(
agentAddress,
sampleGoodDataExport.projects[0],
sampleGoodDataExport.projects[0].projectMeta.passphrase,
store.dispatch,
- installProjectApp,
+ installProject,
createActionHashMapAndImportProjectData,
+ finalizeCreateProject,
projectsZomeApi
)
- expect(installProjectApp).toHaveBeenCalledTimes(1)
- expect(installProjectApp).toHaveBeenCalledWith(
+ expect(installProject).toHaveBeenCalledTimes(1)
+ expect(installProject).toHaveBeenCalledWith(
sampleGoodDataExport.projects[0].projectMeta.passphrase
)
@@ -274,21 +275,27 @@ describe('installProjectAppAndImport()', () => {
store.dispatch
)
- expect(store.dispatch).toHaveBeenCalledTimes(2)
- expect(store.dispatch).toHaveBeenNthCalledWith(1, {
- type: 'SIMPLE_CREATE_PROJECT_META',
- payload: projectMeta,
- meta: { cellIdString: mockCellIdString },
- })
- expect(store.dispatch).toHaveBeenNthCalledWith(2, {
- type: 'SET_MEMBER',
- payload: {
- cellIdString: mockCellIdString,
- member: {
- agentPubKey: 'testAgentAddress',
- },
- },
- })
+ expect(finalizeCreateProject).toHaveBeenCalledTimes(1)
+ const expectedProjectMeta = {
+ creatorAgentPubKey: 'testAgentAddress',
+ // use expect.anything() because of Date.now()
+ // being used internally
+ createdAt: expect.anything(),
+ name: 'new project',
+ image: '',
+ passphrase: 'daily plant employee shorten define',
+ isImported: false,
+ layeringAlgorithm: 'CoffmanGraham',
+ topPriorityOutcomes: [],
+ isMigrated: null
+ }
+ expect(finalizeCreateProject).toHaveBeenCalledWith(
+ mockCellIdString,
+ expectedProjectMeta,
+ 'testAgentAddress',
+ store.dispatch,
+ projectsZomeApi
+ )
})
})