const { contract, selectedProjectId, onBoardSelected, functionLoader, componentOwnerId } = props; const SideMenuContainer = styled.div` display: flex; flex-direction: column; flex-shrink: 0; width: 230px; padding-left: 0; background-color: #0E0E10; color: white; padding: 3px; gap: 16px; `; State.init( { boards: [], boardName: "", showAddBoardDialog: false, showEditBoardDialog: false, editedBoardId: undefined, editedBoardName: "", editBoardNameStatus: [], deleteBoardId: undefined, deleteBoardStatus: [], addBoardNameMissing: false, editBoardNameMissing: false, enableEditBoardName: false, createBoardStatus: [], } ); const [ boardMembers, setBoardMembers ] = useState( [] ); const [ addMemberStatus, setAddMemberStatus ] = useState( undefined ); const [ addMemberInputOpen, setMemberInputOpen ] = useState( false ); const [ selectedUser, setSelectedUser ] = useState( undefined ); const [ users, setUsers ] = useState( [] ); const getMembers = useCallback( async ( projectId ) => { try { Near.asyncCalimeroView( contract, "get_members", { project_id: projectId } ).then( ( members ) => { setBoardMembers( members.map( member => ( { id: member } ) ) ); } ); } catch ( error ) { console.log( "getMembers", e ); } }, [] ); const getUsers = useCallback( async ( accountId ) => { try { Near.asyncCalimeroView( contract, "get_application_members", {} ).then( ( usersResponse ) => { setUsers( usersResponse.map( user => ( { id: user } ) ) ); if ( !isApplicationUser( accountId, usersResponse ) ) { Near.fakCalimeroCall( contract, "add_application_member", { new_member: accountId } ); } } ); } catch ( e ) { console.log( "getUsers", e ); } }, [] ); const isApplicationUser = ( accountId, users ) => { return ( users ) .includes( accountId ); }; const onChangeBoardName = ( { target } ) => { setAddBoardNameMissing( false ); State.update( { boardName: target.value } ); }; const onChangeShowAddBoardDialog = ( open ) => { setAddBoardNameMissing( false ); State.update( { showAddBoardDialog: open, boardName: "" } ); }; const addMember = ( accountId ) => { const oldMembers = JSON.parse( JSON.stringify( boardMembers ) ); try { setAddMemberStatus( "Saving..." ); Near.fakCalimeroCall( contract, "add_member", { project_id: selectedProjectId, new_member: accountId } ).then( () => { setAddMemberStatus( "Saved" ); setMemberInputOpen( false ); setTimeout( () => setAddMemberStatus( undefined ), 3000 ); } ); setSelectedUser( undefined ); setBoardMembers( [ ...oldMembers, { id: accountId } ] ); } catch ( e ) { console.log( "addMember", e ); setBoardMembers( oldMembers ); setAddMemberStatus( "Error" ); } }; const setEditBoardNameMissing = ( missing ) => { State.update( { editBoardNameMissing: missing } ); }; const onChangeEnableEditBoardName = ( open ) => { State.update( { enableEditBoardName: open } ); }; const setAddBoardNameMissing = ( missing ) => { State.update( { addBoardNameMissing: missing } ); }; const cleanBoardCreateStatus = ( name ) => { let foundStatus = state.createBoardStatus.find( b => b.name === name ); foundStatus.status = ""; const filteredStatuses = state.createBoardStatus.filter( b => b.name !== name ); State.update( { createBoardStatus: [ ...filteredStatuses, foundStatus ] } ); }; const cleanBoardEditStatus = ( id ) => { const filteredStatuses = state.editBoardNameStatus.filter( b => b.id !== id ); State.update( { editBoardNameStatus: [ ...filteredStatuses ] } ); }; const setEditBoardName = ( name ) => { State.update( { editedBoardName: name } ); }; const onChangeEditBoardName = ( { target } ) => { State.update( { editedBoardName: target.value } ); }; const onEditBoardName = ( { target } ) => { State.update( { editedBoardName: target.value } ); }; const onChangeShowEditBoardDialog = ( open, id, name ) => { State.update( { showEditBoardDialog: open, editedBoardId: id, editedBoardName: name } ); }; const onChangeShowDeleteBoardDialog = ( open, id ) => { State.update( { showDeleteBoardDialog: open, deleteBoardId: id, } ); }; const cleanDeleteBoardStatus = ( id ) => { const filteredStatuses = state.deleteTaskStatus.filter( b => b.boardId !== id ); State.update( { deleteBoardStatus: filteredStatuses } ); }; // List all boards // Add new board // Edit board name // Delete board const getBoards = () => { Near.fakCalimeroCall( contract, "get_members_projects", { member_id: context.accountId } ) .then( ( boards ) => { State.update( { boards, selectedProjectId: boards.length > 0 ? boards[ 0 ][ 0 ] : undefined, } ); } ); }; const editBoardName = () => { onChangeEnableEditBoardName( false ); let oldBoard = state.boards.find( b => b[ 0 ] === state.editedBoardId ); if ( ( !state.editedBoardName || state.editedBoardName.trim() === '' ) ) { setEditBoardNameMissing( true ); setTimeout( () => setEditBoardName( oldBoard[ 1 ] ), 3000 ); setTimeout( () => setEditBoardNameMissing( false ), 3000 ); return; } if ( state.editedBoardName === oldBoard[ 1 ] ) { return; } try { State.update( { editBoardNameStatus: [ ...state.editBoardNameStatus, { id: state.editedBoardId, status: "Saving..." } ] } ); const newBoard = [ state.editedBoardId, state.editedBoardName, ]; let newBoardsArray = []; const storageBoards = Storage.privateGet( "tempBoards" + contract ); if ( storageBoards && JSON.parse( storageBoards ).length > 0 ) { newBoardsArray = JSON.parse( storageBoards ); newBoardsArray.push( newBoard ); } else { newBoardsArray.push( newBoard ); } const jsonStringArray = JSON.stringify( newBoardsArray ); Storage.privateSet( "tempBoards" + contract, jsonStringArray ); setBoards(); Near.fakCalimeroCall( contract, "edit_name", { project_id: state.editedBoardId, new_name: state.editedBoardName } ).then( () => { let foundStatus = state.editBoardNameStatus.find( b => b.id === state.editedBoardId ); foundStatus.status = "Saved"; const filteredStatuses = state.editBoardNameStatus.filter( b => b.id !== state.editedBoardId ); State.update( { editBoardNameStatus: [ ...filteredStatuses, foundStatus ] } ); setTimeout( () => cleanBoardEditStatus( state.editedBoardId ), 3000 ); } ); } catch ( e ) { let foundStatus = state.editBoardNameStatus.find( b => b.id === state.editedBoardId ); foundStatus.status = "Error saving"; const filteredStatuses = state.editBoardNameStatus.filter( b => b.id !== state.editedBoardId ); State.update( { editBoardNameStatus: [ ...filteredStatuses, foundStatus ] } ); Storage.privateSet( "tempBoards" + contract, "" ); setTimeout( getBoards, 3000 ); } }; const createBoard = () => { if ( !state.boardName || state.boardName.trim() === '' ) { setAddBoardNameMissing( true ); return; } try { const boardName = state.boardName; State.update( { functionLoader: true } ); State.update( { createBoardStatus: [ ...state.createBoardStatus, { name: state.boardName, status: "Saving..." } ] } ); const newBoard = [ null, state.boardName, ]; let newBoardsArray = []; const storageBoards = Storage.privateGet( "tempBoards" + contract ); if ( storageBoards && JSON.parse( storageBoards ).length > 0 ) { newBoardsArray = JSON.parse( storageBoards ); newBoardsArray.push( newBoard ); } else { newBoardsArray.push( newBoard ); } const jsonStringArray = JSON.stringify( newBoardsArray ); Storage.privateSet( "tempBoards" + contract, jsonStringArray ); setBoards(); Near.fakCalimeroCall( contract, "create_new_project", { name: boardName, owner: context.accountId, members: [ context.accountId ], statuses: [ "TO DO", "IN PROGRESS", "DONE" ] } ).then( () => { let foundStatus = state.createBoardStatus.find( b => b.name === boardName ); foundStatus.status = "Saved"; const filteredStatuses = state.createBoardStatus.filter( b => b.name !== boardName ); State.update( { createBoardStatus: [ ...filteredStatuses, foundStatus ] } ); setTimeout( () => cleanBoardCreateStatus( boardName ), 3000 ); setTimeout( getBoards, 3000 ); } ); } catch ( e ) { let foundStatus = state.createBoardStatus.find( b => b.name === boardName ); foundStatus.status = "Error"; const filteredStatuses = state.createBoardStatus.filter( b => b.name !== boardName ); State.update( { createBoardStatus: [ ...filteredStatuses, foundStatus ] } ); Storage.privateSet( "tempBoards" + contract, "" ); } State.update( { functionLoader: false } ); onChangeShowAddBoardDialog( false ); }; const setBoards = () => { try { let boards = []; Near.asyncCalimeroView( contract, "get_members_projects", { member_id: context.accountId } ).then( ( b ) => { boards = b; const storageBoards = Storage.privateGet( "tempBoards" + contract ); if ( storageBoards && JSON.parse( storageBoards ).length > 0 ) { const storageArray = JSON.parse( storageBoards ); let newBoards = boards; for ( let newBoard of storageArray ) { if ( boards.find( b => b[ 0 ] === newBoard[ 0 ] ) ) { let editBoard = boards.find( b => b[ 0 ] === newBoard[ 0 ] ); editBoard[ 1 ] = newBoard[ 1 ]; newBoards = boards.map( b => { if ( b[ 0 ] === newBoard[ 0 ] ) { return editBoard; } else { return b; } } ); } else if ( !boards.some( b => b[ 1 ] === newBoard[ 1 ] ) ) { newBoards = [ ...newBoards, newBoard ]; } } State.update( { boards: newBoards } ); } else { setBoards(); } } ); } catch ( e ) { console.log( e ); Storage.privateSet( "tempBoards" + contract, "" ); } }; const deleteBoard = () => { const oldBoards = state.boards; const boardId = state.deleteBoardId; const newDeleteBoardStatus = [ ...state.deleteBoardStatus, { boardId: boardId, status: `Deleting board: ${ boardId }` } ]; State.update( { deleteBoardStatus: newDeleteBoardStatus } ); try { const newBoards = state.boards.filter( board => board[ 0 ] !== boardId ); State.update( { boards: newBoards } ); Near.fakCalimeroCall( contract, "delete_project", { project_id: boardId, } ).then( () => { let foundStatus = newDeleteBoardStatus.find( b => b.boardId === boardId ); foundStatus.status = `Deleted board: ${ boardId }`; const filteredStatuses = newDeleteBoardStatus.filter( b => b.boardId !== boardId ); State.update( { deleteBoardStatus: [ ...filteredStatuses, foundStatus ] } ); setTimeout( () => cleanDeleteBoardStatus( boardId ), 3000 ); } ); } catch ( e ) { let foundStatus = newDeleteBoardStatus.find( b => b.boardId === boardId ); foundStatus.status = `Error deleting board: ${ board }`; const filteredStatuses = newDeleteBoardStatus.filter( b => b.boardId !== boardId ); State.update( { deleteBoardStatus: [ ...filteredStatuses, foundStatus ] } ); State.update( { boards: oldBoards } ); } onChangeShowEditBoardDialog( false, undefined, undefined ); onChangeShowDeleteBoardDialog( false, undefined ); }; useEffect( () => { getUsers( context.accountId ); getBoards(); }, [ context.accountId ] ); return ( <> { state.showDeleteBoardDialog && <Widget src={ `${ componentOwnerId }/widget/Calimero.TaskChain.ConfirmationPopup` } props={ { onClick: () => deleteBoard(), onClose: () => onChangeShowDeleteBoardDialog( false, undefined, title ), title: "Are you sure you want to delete the board?" } } /> } { state.showAddBoardDialog && <Widget src={ `${ componentOwnerId }/widget/Calimero.TaskChain.CreateBoardDialog` } props={ { componentOwnerId, createBoard, onChangeShowAddBoardDialog, open: state.showAddBoardDialog, functionLoader, onChangeBoardName, boardName: state.boardName, addBoardNameMissing: state.addBoardNameMissing } } /> } { state.showEditBoardDialog && <Widget src={ `${ componentOwnerId }/widget/Calimero.TaskChain.SideMenu.EditBoardDialog` } props={ { createBoard, onClose: () => onChangeShowEditBoardDialog( false, undefined, undefined ), open: state.showEditBoardDialog, functionLoader, onChangeEditBoardName, boardName: state.boardName, editedBoardId: state.editedBoardId, editedBoardName: state.editedBoardName, editBoardName, editBoardNameStatus: state.editBoardNameStatus, onChangeShowDeleteBoardDialog, componentOwnerId, editBoardNameMissing: state.editBoardNameMissing, enableEditBoardName: state.enableEditBoardName, onChangeEnableEditBoardName, componentOwnerId, onEditBoardSelectorOptionClick: undefined, editBoardSelectedOption: undefined, boardMembers, selectedProjectId, users: state.users, boardMembers, addMember, addMemberStatus, setMemberInputOpen, addMemberInputOpen, selectedUser, setSelectedUser } } /> } <SideMenuContainer> <Widget src={ `${ componentOwnerId }/widget/Calimero.TaskChain.SideMenu.AddBoard` } props={ { onClick: () => onChangeShowAddBoardDialog( true ) } } /> <Widget src={ `${ componentOwnerId }/widget/Calimero.TaskChain.SideMenu.BoardList` } props={ { componentOwnerId, selected: selectedProjectId, onClick: onBoardSelected, boards: state.boards, onEditBoardClick: () => { }, editBoard: () => { }, onChangeShowEditBoardDialog, createBoardStatus: state.createBoardStatus } } /> </SideMenuContainer> </> );