const { contract, selectedProjectId, setSelectedProjectId, functionLoader, setFunctionLoader, componentOwnerId, accountId, addActionStatus } = 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; `; const [boardMembers, setBoardMembers] = useState([]); const [addMemberStatus, setAddMemberStatus] = useState(undefined); const [addMemberInputOpen, setMemberInputOpen] = useState(false); const [selectedUser, setSelectedUser] = useState(undefined); const [users, setUsers] = useState([]); const [boards, setBoards] = useState([]); const [boardName, setBoardName] = useState(""); const [showAddBoardDialog, setShowAddBoardDialog] = useState(false); const [showEditBoardDialog, setShowEditBoardDialog] = useState(false); const [editedBoardId, setEditedBoardId] = useState(undefined); const [editedBoardName, setEditedBoardName] = useState(""); const [editBoardNameStatus, setEditBoardNameStatus] = useState([]); const [deleteBoardId, setDeleteBoardId] = useState(undefined); const [addBoardNameMissing, setAddBoardNameMissing] = useState(false); const [editBoardNameMissing, setEditBoardNameMissing] = useState(false); const [enableEditBoardName, setEnableEditBoardName] = useState(false); const [createBoardStatus, setCreateBoardStatus] = useState([]); const [showDeleteBoardDialog, setShowDeleteBoardDialog] = useState(false); const isApplicationUser = (accountId, users) => { return users.includes(accountId); }; const onChangeBoardName = ({ target }) => { setAddBoardNameMissing(false); setBoardName(target.value); }; const onChangeShowAddBoardDialog = (open) => { setAddBoardNameMissing(false); setBoardName(""); setShowAddBoardDialog(open); }; const onChangeEnableEditBoardName = (open) => { setEnableEditBoardName(open); }; const onChangeEditBoardName = ({ target }) => { setEditedBoardName(target.value); }; const onChangeShowEditBoardDialog = (open, id, name) => { setShowEditBoardDialog(open); setEditedBoardId(id); setEditedBoardName(name); }; const onChangeShowDeleteBoardDialog = (open, id) => { setDeleteBoardId(id); setShowDeleteBoardDialog(open); }; const cleanBoardCreateStatus = (name) => { let foundStatus = createBoardStatus.find((b) => b.name === name); foundStatus.status = ""; const filteredStatuses = createBoardStatus.filter((b) => b.name !== name); setCreateBoardStatus([...filteredStatuses, foundStatus]); }; const removeBoardMember = useCallback((member) => { setBoardMembers(boardMembers.filter((m) => m.id !== member.id)); }, [boardMembers, setBoardMembers]); const createBoard = useCallback(async () => { if (!boardName || boardName.trim() === "") { setAddBoardNameMissing(true); return; } const newStatus = { name: boardName, status: "Saving..." }; const newStatuses = [...createBoardStatus, newStatus]; const oldBoards = boards; try { const newBoardName = boardName; setFunctionLoader(true); setCreateBoardStatus(newStatuses); const newBoard = [null, 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); handleBoards(); Near.fakCalimeroCall(contract, "create_new_project", { name: newBoardName, owner: context.accountId, members: [context.accountId], statuses: ["TO DO", "IN PROGRESS", "DONE"], }).then(() => { let foundStatus = newStatuses.find((b) => b.name === newBoardName); foundStatus.status = "Saved"; const filteredStatuses = newStatuses.filter( (b) => b.name !== newBoardName ); setCreateBoardStatus([...filteredStatuses, foundStatus]); setTimeout(() => { let foundStatus = newStatuses.find((b) => b.name === newBoardName); foundStatus.status = ""; const filteredStatuses = newStatuses.filter( (b) => b.name !== newBoardName ); setCreateBoardStatus([...filteredStatuses, foundStatus]); }, 3000); setTimeout(getBoards, 3000); }); } catch (e) { let foundStatus = newStatuses.find((b) => b.name === newBoardName); foundStatus.status = "Error"; const filteredStatuses = newStatuses.filter((b) => b.name !== newBoardName); setCreateBoardStatus([...filteredStatuses, foundStatus]); setTimeout(() => setBoards(oldBoards), 3000); Storage.privateSet("tempBoards" + contract, ""); } setFunctionLoader(false); onChangeShowAddBoardDialog(false); }, [boardName]); const editBoardName = useCallback(async () => { onChangeEnableEditBoardName(false); let oldBoard = boards.find((b) => b[0] === editedBoardId); if (!editedBoardName || editedBoardName.trim() === "") { setEditBoardNameMissing(true); setTimeout(() => setEditBoardName(oldBoard[1]), 3000); setTimeout(() => setEditBoardNameMissing(false), 3000); return; } if (editedBoardName === oldBoard[1]) { return; } const newStatuses = [ ...editBoardNameStatus, { id: editedBoardId, status: "Saving..." }, ]; try { setEditBoardNameStatus(newStatuses); const newBoard = [editedBoardId, 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); handleBoards(); Near.fakCalimeroCall(contract, "edit_name", { project_id: editedBoardId, new_name: editedBoardName, }).then(() => { let foundStatus = newStatuses.find((b) => b.id === editedBoardId); foundStatus.status = "Saved"; const filteredStatuses = newStatuses.filter( (b) => b.id !== editedBoardId ); setEditBoardNameStatus([...filteredStatuses, foundStatus]); setTimeout(() => { const filteredStatuses = newStatuses.filter( (b) => b.id !== editedBoardId ); setEditBoardNameStatus([...filteredStatuses]); }, 3000); }); } catch (e) { let foundStatus = newStatuses.find((b) => b.id === editedBoardId); foundStatus.status = "Error saving"; const filteredStatuses = newStatuses.filter((b) => b.id !== editedBoardId); setEditBoardNameStatus([...filteredStatuses, foundStatus]); Storage.privateSet("tempBoards" + contract, ""); setTimeout(getBoards, 3000); } }, [editedBoardName]); const deleteBoard = () => { const oldBoards = state.boards; const boardId = deleteBoardId; const actionStatusPrefix = "Delete board"; let newActionStatus = { id: actionStatusPrefix + boardId, status: `Deleting board: ${boardId}` }; try { addActionStatus(newActionStatus); const newBoards = boards.filter((board) => board[0] !== boardId); setBoards(newBoards); Near.fakCalimeroCall(contract, "delete_project", { project_id: boardId, }).then(() => { newActionStatus.status = `Deleted board: ${boardId}`; addActionStatus(newActionStatus); }); } catch (e) { newActionStatus.status = `Error deleting board: ${boardId}`; addActionStatus(newActionStatus); setBoards(oldBoards); } onChangeShowEditBoardDialog(false, undefined, undefined); onChangeShowDeleteBoardDialog(false, undefined); }; const handleBoards = useCallback(async () => { try { let boards = []; Near.asyncCalimeroView(contract, "get_members_projects", { member_id: 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]; } } setBoards(newBoards); } else { handleBoards(); } }); } catch (e) { console.log(e); Storage.privateSet("tempBoards" + contract, ""); } }, []); const addMember = useCallback(async (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) { setBoardMembers(oldMembers); setAddMemberStatus("Error"); } }, [boardMembers, selectedProjectId, contract]); const getBoards = useCallback(async () => { try { Near.fakCalimeroCall(contract, "get_members_projects", { member_id: accountId, }).then((boards) => { setBoards(boards); setSelectedProjectId(boards.length > 0 ? boards[0][0] : undefined); }); } catch (e) { console.log("getBoards", e); } }, [contract, accountId]); const getMembers = useCallback(async (projectId) => { try { Near.asyncCalimeroView(contract, "get_members", { project_id: projectId, }).then((members) => { setBoardMembers(members.map((member) => ({ id: member }))); }); } catch (e) { console.log("getMembers", e); } }, [contract]); const getUsers = useCallback(async () => { 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); } }, [contract, accountId]); useEffect(() => { getBoards(); getUsers(); }, [accountId]); useEffect(() => { if (selectedProjectId) { getMembers(selectedProjectId); } }, [selectedProjectId]); return ( <> {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?", }} /> )} {showAddBoardDialog && ( <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.CreateBoardDialog`} props={{ componentOwnerId, createBoard, onChangeShowAddBoardDialog, open: showAddBoardDialog, functionLoader, onChangeBoardName, boardName, addBoardNameMissing, }} /> )} {showEditBoardDialog && ( <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.SideMenu.EditBoardDialog`} props={{ createBoard, onClose: () => onChangeShowEditBoardDialog(false, undefined, undefined), open: showEditBoardDialog, functionLoader, onChangeEditBoardName, boardName, editedBoardId, editedBoardName, editBoardName, editBoardNameStatus, onChangeShowDeleteBoardDialog, componentOwnerId, editBoardNameMissing, enableEditBoardName, onChangeEnableEditBoardName, componentOwnerId, onEditBoardSelectorOptionClick: undefined, editBoardSelectedOption: undefined, boardMembers, selectedProjectId, users, boardMembers, addMember, addMemberStatus, setMemberInputOpen, addMemberInputOpen, selectedUser, setSelectedUser, addActionStatus, removeBoardMember, contract }} /> )} <SideMenuContainer> <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.SideMenu.AddBoard`} props={{ onClick: () => onChangeShowAddBoardDialog(true), }} /> <Widget src={`${componentOwnerId}/widget/Calimero.TaskChain.SideMenu.BoardList`} props={{ componentOwnerId, selectedProjectId, setSelectedProjectId, boards, onEditBoardClick: () => {}, editBoard: () => {}, onChangeShowEditBoardDialog, createBoardStatus, }} /> </SideMenuContainer> </> );