import { AnyAction } from "redux" ; import { findIndex } from "lodash" ; import { EthAddress , CharterData , RosterMember } from "@joincivil/typescript-types" ; import { Civil } from "@joincivil/core" ; import { getInfuraUrlFromIpfs , sanitizeConstitutionHtml } from "@joincivil/utils" ; import { NewsroomState , StateWithNewsroom } from "./reducers" ; import { CmsUserData } from "./types" ; import { makeUserObject } from "./utils" ; export enum newsroomActions { ADD_NEWSROOM = "ADD_NEWSROOM" , UPDATE_NEWSROOM = "UPDATE_NEWSROOM" , CHANGE_NAME = "CHANGE_NAME" , ADD_EDITOR = "ADD_EDITOR" , ADD_OWNER = "ADD_OWNER" , REMOVE_EDITOR = "REMOVE_EDITOR" , SET_IS_OWNER = "SET_IS_OWNER" , SET_IS_EDITOR = "SET_IS_EDITOR" } export enum uiActions { ADD_GET_CMS_USER_DATA_FOR_ADDRESS = "ADD_GET_CMS_USER_DATA_FOR_ADDRESS" , GET_CMS_USER_DATA_FOR_ADDRESS = "GET_CMS_USER_DATA_FOR_ADDRESS" , ADD_PERSIST_CHARTER = "ADD_PERSIST_CHARTER" , PERSIST_CHARTER = "PERSIST_CHARTER" } export enum userActions { STORE_USER_DATA = "STORE_USER_DATA" } export enum governmentActions { ADD_CONSTITUTION_URI = "ADD_CONSTITUTION_URI" , ADD_CONSTITUTION_HASH = "ADD_CONSTITUTION_HASH" , ADD_CONSTITUTION_CONTENT = "ADD_CONSTITUTION_CONTENT" } export const getEditors = ( address , civil ) : any => async ( dispatch , getState ) : Promise < void > => { const newsroom = await civil . newsroomAtUntrusted ( address ) ; newsroom . editors ( ) . distinct ( ) . forEach ( val => { dispatch ( initContractMember ( address , val ) ) ; dispatch ( addEditor ( address , val ) ) ; } ) ; } ; export const getNewsroom = ( address , civil ) : any => async ( dispatch , getState ) : Promise < AnyAction > => { const newsroom = await civil . newsroomAtUntrusted ( address ) ; const wrapper = await newsroom . getNewsroomWrapper ( ) ; wrapper . data . owners . forEach ( ( userAddress ) => { dispatch ( initContractMember ( address , userAddress ) ) ; } ) ; return dispatch ( updateNewsroom ( address , { wrapper , newsroom } ) ) ; } ; export const getIsOwner = ( address , civil ) : any => async ( dispatch , getState ) : Promise < AnyAction > => { const newsroom = await civil . newsroomAtUntrusted ( address ) ; return dispatch ( setIsOwner ( address , await newsroom . isOwner ( ) ) ) ; } ; export const getIsEditor = ( address , civil ) : any => async ( dispatch , getState ) : Promise < AnyAction > => { const newsroom = await civil . newsroomAtUntrusted ( address ) ; return dispatch ( setIsEditor ( address , await newsroom . isEditor ( ) ) ) ; } ; export const addNewsroom = ( newsroom ) : AnyAction => { return { type : newsroomActions . ADD_NEWSROOM , data : newsroom , } ; } ; export const updateNewsroom = ( address , data ) : AnyAction => { return { type : newsroomActions . UPDATE_NEWSROOM , data : { address , ... data , } , } ; } ; export const addEditor = ( address , editor ) : AnyAction => { return { type : newsroomActions . ADD_EDITOR , data : { address , editor , } , } ; } ; export const addOwner = ( address , owner ) : AnyAction => { return { type : newsroomActions . ADD_OWNER , data : { address , owner , } , } ; } ; export const removeEditor = ( address , editor ) => { return { type : newsroomActions . REMOVE_EDITOR , data : { address , editor , } , } ; } ; export const setIsOwner = ( address , isOwner ) => { return { type : newsroomActions . SET_IS_OWNER , data : { address , isOwner , } , } ; } ; export const setIsEditor = ( address , isEditor ) => { return { type : newsroomActions . SET_IS_EDITOR , data : { address , isEditor , } , } ; } ; export const changeName = ( address , name ) : AnyAction => { return { type : newsroomActions . CHANGE_NAME , data : { name , address } , } ; } ; export const updateCharter = ( address , charter ) : any => ( dispatch , getState ) : AnyAction => { const { newsrooms , newsroomUi } = getState ( ) ; const newsroom = newsrooms . get ( address ) || { wrapper : { data : { } } } ; const persistCharter = newsroomUi . get ( uiActions . PERSIST_CHARTER ) ; if ( persistCharter ) { persistCharter ( charter ) ; } return dispatch ( updateNewsroom ( address , { ... newsroom , charter , } ) ) ; } ; export const fetchNewsroom = ( address ) : any => async ( dispatch , getState ) => { const { newsrooms } = getState ( ) ; const newsroom = newsrooms . get ( address ) ; const wrapper = await newsroom . newsroom ! . getNewsroomWrapper ( ) ; await dispatch ( updateNewsroom ( address , { ... newsroom , wrapper } ) ) ; wrapper . data . owners . forEach ( ( userAddress ) => { dispatch ( initContractMember ( address , userAddress ) ) ; } ) ; } ; export const addGetCmsUserDataForAddress = ( func ) : AnyAction => { return { type : uiActions . ADD_GET_CMS_USER_DATA_FOR_ADDRESS , data : func , } ; } ; export const addPersistCharter = ( func ) : AnyAction => { return { type : uiActions . ADD_PERSIST_CHARTER , data : func , } ; } ; export const ensureUserOnRoster = ( newsroomAddress , address , userData ? ) : any => ( dispatch , getState ) => { const { newsrooms , newsroomUsers } = getState ( ) ; const charter = ( newsrooms . get ( newsroomAddress ) || { } ) . charter || { } ; let roster = charter . roster || [ ] ; const rosterMemberIndex = findIndex ( roster , member => ( member . ethAddress || "" ) . toLowerCase ( ) === address . toLowerCase ( ) ) ; if ( rosterMemberIndex === - 1 ) { const user = makeUserObject ( address , userData || newsroomUsers . get ( address ) ) ; roster = roster . concat ( user . rosterData as RosterMember ) ; } else { if ( userData ) { const rosterMember = roster [ rosterMemberIndex ] ; roster [ rosterMemberIndex ] = { ... rosterMember , name : userData . displayName || rosterMember . name , avatarUrl : userData . avatarUrl || rosterMember . avatarUrl , } ; } } dispatch ( updateCharter ( newsroomAddress , { ... charter , roster , } ) ) ; } ; export const storeUserData = ( newsroomAddress , address , userData ) : AnyAction => { return { type : userActions . STORE_USER_DATA , data : { address , userData , } , } ; } ; export const initContractMember = ( newsroomAddress , userAddress ) : any => async ( dispatch , getState ) => { const state = getState ( ) ; let userData = state . newsroomUsers . get ( userAddress ) ; const getCmsUserDataForAddress = state . newsroomUi . get ( uiActions . GET_CMS_USER_DATA_FOR_ADDRESS ) ; if ( ! userData && getCmsUserDataForAddress ) { userData = await getCmsUserDataForAddress ( userAddress ) ; dispatch ( storeUserData ( newsroomAddress , userAddress , userData ) ) ; } dispatch ( ensureUserOnRoster ( newsroomAddress , userAddress , userData ) ) ; } ; export const addAndHydrateEditor = ( newsroomAddress , editorAddress ) : any => async ( dispatch , getState ) => { dispatch ( addEditor ( newsroomAddress , editorAddress ) ) ; return dispatch ( initContractMember ( newsroomAddress , editorAddress ) ) ; } ; export const addAndHydrateOwner = ( newsroomAddress , ownerAddress ) : any => async ( dispatch , getState ) => { dispatch ( addOwner ( newsroomAddress , ownerAddress ) ) ; return dispatch ( initContractMember ( newsroomAddress , ownerAddress ) ) ; } ; export const addConstitutionUri = ( uri ) : AnyAction => { return { type : governmentActions . ADD_CONSTITUTION_URI , data : { uri , } , } ; } ; export const fetchConstitution = ( ipfsAddress ) : any => async ( dispatch ) => { const infuraUrl = getInfuraUrlFromIpfs ( ipfsAddress ) ; const constitution = await fetch ( infuraUrl ) . then ( async ( body ) => body . json ( ) ) ; return dispatch ( { type : governmentActions . ADD_CONSTITUTION_CONTENT , data : { content : sanitizeConstitutionHtml ( constitution . content ) , } , } ) ; } ; export const addConstitutionHash = ( hash ) : AnyAction => { return { type : governmentActions . ADD_CONSTITUTION_HASH , data : { hash , } , } ; } ;